Compare commits

..

2 commits

Author SHA1 Message Date
Alexander Borsuk
bc3e3d3bdf Minor consistency fixes 2022-07-04 23:27:43 +02:00
eeeb6e962d New API 2022-07-03 15:11:30 +03:00
17 changed files with 75 additions and 198 deletions

View file

@ -14,8 +14,6 @@ using Organic Maps to show points of interest (POI) and providing more informati
Please refer to [sample application][linkSampleSource] for demo.
**Note**: this library provides convenience wrappers for [deep links](https://omaps.app/api). Your application can also use deep links directly without including the library as a dependency. You can look at the library implementation for ideas on how to do that.
## Prerequisites
It is supposed that you are familiar with Android Development.
@ -75,7 +73,7 @@ For multiple points use [Point][linkPointClass] class:
We support PendingIntent interaction (just like Android native
NotificationManager does). You should specify ID for each point to
distinguish it later, and PendingIntent that Organic Maps will send back to
distinguish it later, and PentingIntent that Organic Maps will send back to
your application when user press "More Info" button :
// Here is how to pass points with ID ant PendingIntent
@ -125,12 +123,13 @@ your application when user press "More Info" button :
## FAQ
#### Which versions of Organic Maps support API calls?
#### How should I detect if user has Organic Maps installed?
`Api.isOrganicMapsInstalled(Context)` will return `true` if user has *Lite* or *Pro* version that supports API call installed.
All versions since 2022-07-26 and above support API calls.
#### Which versions of Organic Maps support API calls?
All versions since 2.4.0 and above support API calls.
#### What will happen if I call for `Api.showPoint()` but Organic Maps application is not installed?
Nothing serious. API library will show simple dialog with gentle offer to download Organic Maps. You can see how it looks like below.
![Please install us](site/images/dlg.png)
@ -142,12 +141,9 @@ Nothing serious. API library will show simple dialog with gentle offer to downlo
-------------------------------------------------------------------------------
## API Code License
Copyright (c) 2024, Organic Maps OÜ.
Copyright (c) 2022, Organic Maps OÜ.
Copyright (c) 2019, MY.COM B.V.
Copyright (c) 2013, MapsWithMe GmbH.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@ -158,11 +154,11 @@ Redistribution and use in source and binary forms, with or without modification,
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[linkOM]: https://organicmaps.app/ "Organic Maps"
[linkPIntent]: https://developer.android.com/reference/android/app/PendingIntent.html "PendingIntent"
[linkPIntent]: http://developer.android.com/reference/android/app/PendingIntent.html "PendingIntent"
[linkRepo]: https://github.com/organicmaps/api-android "GitHub Repository"
[linkLibProj]: https://developer.android.com/tools/projects/index.html#LibraryProjects "Android Library Project"
[linkIntents]: https://developer.android.com/guide/components/intents-filters.html "Intents and Intent Filters"
[linkApiClass]: lib/src/main/java/app/organicmaps/api/OrganicMapsApi.java "OrganicMapsApi.java"
[linkPointClass]: lib/src/main/java/app/organicmaps/api/Point.java "Point.java"
[linkRespClass]: lib/src/main/java/app/organicmaps/api/PickPointResponse.java "PickPointResponse.java"
[linkLibProj]: http://developer.android.com/tools/projects/index.html#LibraryProjects "Android Library Project"
[linkIntents]: http://developer.android.com/guide/components/intents-filters.html "Intents and Intent Filters"
[linkApiClass]: lib/src/app/organicmaps/api/Api.java "Api.java"
[linkPointClass]: lib/src/app/organicmaps/api/Point.java "Point.java"
[linkRespClass]: lib/src/app/organicmaps/api/PickPointResponse.java "PickPointResponse.java"
[linkSampleSource]: https://github.com/organicmaps/api-android/tree/master/sample-app-capitals "Api Source Code"

View file

@ -1,15 +1,16 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.5.1' apply false
id 'com.android.library' version '8.5.1' apply false
id 'com.android.application' version '7.2.1' apply false
id 'com.android.library' version '7.2.1' apply false
}
project.ext {
minSdkVersion = 21
targetSdkVersion = 34
targetSdkVersion = 31
buildToolsVersion = '32.0.0'
javaVersion = JavaVersion.VERSION_11
}
task clean(type: Delete) {
delete rootProject.buildDir
}
}

View file

@ -1,5 +1,6 @@
#Mon Jun 06 09:48:49 TRT 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View file

@ -3,12 +3,12 @@ plugins {
}
android {
namespace 'app.organicmaps.api'
compileSdk project.targetSdkVersion
defaultConfig {
minSdk project.minSdkVersion
targetSdk project.targetSdkVersion
buildToolsVersion project.buildToolsVersion
consumerProguardFiles "consumer-rules.pro"
}
@ -25,11 +25,8 @@ android {
}
}
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
}
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
}

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest package="app.organicmaps.api"
xmlns:android="http://schemas.android.com/apk/res/android">
<queries>
<!-- packages we want to see using the package manager need to be declared starting with targetSDK 30, and we need to use specific strings / cannot use @string/xxx notation -->
<package android:name="app.organicmaps"/>
<package android:name="com.mapswithme.maps"/>
</queries>
</manifest>

View file

@ -24,15 +24,17 @@ package app.organicmaps.api;
public class Const
{
// Common
/* Common */
static final String API_SCHEME = "om://";
static final String AUTHORITY = "app.organicmaps.api";
static final String EXTRA_PREFIX = AUTHORITY + ".extra";
// Request extras
/* Request extras */
public static final String EXTRA_TITLE = EXTRA_PREFIX + ".TITLE";
public static final String EXTRA_PICK_POINT = EXTRA_PREFIX + ".PICK_POINT";
// Response extras
/* Response extras */
/* Point part-by-part*/
public static final String EXTRA_POINT_NAME = EXTRA_PREFIX + ".POINT_NAME";
public static final String EXTRA_POINT_LAT = EXTRA_PREFIX + ".POINT_LAT";
public static final String EXTRA_POINT_LON = EXTRA_PREFIX + ".POINT_LON";

View file

@ -1,55 +0,0 @@
/*
Copyright (c) 2022, Organic Maps . All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. Redistributions in binary form must
reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the
distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
package app.organicmaps.api;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.NonNull;
public class CrosshairRequest
{
private String mAppName;
public CrosshairRequest setAppName(String appName)
{
mAppName = appName;
return this;
}
public @NonNull
Intent toIntent()
{
final StringBuilder builder = new StringBuilder(Const.API_SCHEME);
builder.append("crosshair?");
// title
if (mAppName != null)
builder.append("appname").append("=").append(Uri.encode(mAppName)).append("&");
final Uri uri = Uri.parse(builder.toString());
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(Const.EXTRA_PICK_POINT, true);
return intent;
}
}

View file

@ -35,40 +35,36 @@ import java.util.Locale;
public class MapRequest
{
private List<Point> mPoints = new ArrayList<>();
private String mAppName;
private String mTitle;
private double mZoomLevel;
// pick point mode
private boolean mPickPointMode;
public @NonNull MapRequest
setAppName(String appName)
public MapRequest setTitle(String title)
{
mAppName = appName;
mTitle = title;
return this;
}
public @NonNull
MapRequest addPoint(Point point)
public MapRequest addPoint(Point point)
{
mPoints.add(point);
return this;
}
public @NonNull
MapRequest setPoints(Collection<Point> points)
public MapRequest setPoints(Collection<Point> points)
{
mPoints = new ArrayList<>(points);
return this;
}
public @NonNull
MapRequest setZoomLevel(double zoomLevel)
public MapRequest setZoomLevel(double zoomLevel)
{
mZoomLevel = zoomLevel;
return this;
}
public @NonNull MapRequest setPickPointMode(boolean pickPointMode)
public MapRequest setPickPointMode(boolean pickPointMode)
{
mPickPointMode = pickPointMode;
return this;
@ -81,8 +77,8 @@ public class MapRequest
builder.append("map?");
// title
if (mAppName != null)
builder.append("appname").append("=").append(Uri.encode(mAppName)).append("&");
if (mTitle != null)
builder.append("appname").append("=").append(Uri.encode(mTitle)).append("&");
// zoom
if (mZoomLevel != 0.0)
builder.append("z").append("=").append(mZoomLevel).append("&");
@ -104,6 +100,8 @@ public class MapRequest
final Uri uri = Uri.parse(builder.toString());
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
if (mTitle != null)
intent.putExtra(Const.EXTRA_TITLE, mTitle);
if (mPickPointMode)
intent.putExtra(Const.EXTRA_PICK_POINT, true);
return intent;

View file

@ -1,60 +0,0 @@
package app.organicmaps.api;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import java.util.ArrayList;
public class OrganicMapsApi {
static final String PACKAGE_NAME_RELEASE = "app.organicmaps";
static final String PACKAGE_NAME_DEBUG = "app.organicmaps.debug";
static final String PACKAGE_NAME_BETA = "app.organicmaps.beta";
private OrganicMapsApi() {
// utility class
}
public static void showPointOnMap(final Activity activity, final double lat, final double lon, final String name) {
final ArrayList<Point> points = new ArrayList<>(1);
points.add(new Point(lat, lon, name));
showPointsOnMap(activity, name, points);
}
public static void showPointsOnMap(final Activity activity, final String name, final ArrayList<Point> points) {
final Intent intent = new MapRequest()
.setPoints(points)
.setAppName(name)
.toIntent();
sendRequest(activity, intent);
};
public static void sendRequest(final Activity caller, final Intent intent) {
if (canHandleOrganicMapsIntents(caller)) {
caller.startActivity(intent);
} else {
new DownloadDialog(caller).show();
}
}
/**
* Detects if any handler for OrganicMaps intents is installed on the device
*/
public static boolean canHandleOrganicMapsIntents(final Context context) {
final ComponentName c = new MapRequest().toIntent().resolveActivity(context.getPackageManager());
return c != null;
}
/**
* Detects if one of the specific OrganicMaps packages is installed
*/
public static boolean isOrganicMapsPackageInstalled(final Context context) {
final PackageManager pm = context.getPackageManager();
return (pm.getLaunchIntentForPackage(PACKAGE_NAME_RELEASE) != null
|| pm.getLaunchIntentForPackage(PACKAGE_NAME_BETA) != null
|| pm.getLaunchIntentForPackage(PACKAGE_NAME_DEBUG) != null);
}
}

View file

@ -3,13 +3,13 @@ plugins {
}
android {
namespace 'app.organicmaps.api.sample.capitals'
compileSdk project.targetSdkVersion
defaultConfig {
applicationId "app.organicmaps.api.sample.capitals"
minSdk project.minSdkVersion
targetSdk project.targetSdkVersion
buildToolsVersion project.buildToolsVersion
versionCode 1
versionName "1.0"
}
@ -26,12 +26,8 @@ android {
}
}
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation project(path: ':lib')
}

View file

@ -21,7 +21,8 @@
OF SUCH DAMAGE.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest package="app.organicmaps.api.sample.capitals"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"

View file

@ -1,4 +1,4 @@
/*
/******************************************************************************
Copyright (c) 2022, Organic Maps . All rights reserved.
Copyright (c) 2013, MapsWithMe GmbH. All rights reserved.
@ -20,7 +20,7 @@
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
******************************************************************************/
package app.organicmaps.api.sample.capitals;
import android.app.ListActivity;
@ -72,7 +72,7 @@ public class CapitalsListActivity extends ListActivity
final String title = cities.length == 1 ? cities[0].getName() : "Capitals of the World";
final Intent intent = new MapRequest()
.setPoints(points)
.setAppName(title)
.setTitle(title)
.toIntent();
this.startActivityForResult(intent, REQ_CODE_CITY);
}

View file

@ -1,4 +1,4 @@
/*
/******************************************************************************
Copyright (c) 2022, Organic Maps . All rights reserved.
Copyright (c) 2013, MapsWithMe GmbH. All rights reserved.
@ -20,7 +20,7 @@
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
******************************************************************************/
package app.organicmaps.api.sample.capitals;
import app.organicmaps.api.Point;

View file

@ -1,5 +1,5 @@
/*
Copyright (c) 2022-2023, Organic Maps . All rights reserved.
/******************************************************************************
Copyright (c) 2022, Organic Maps . All rights reserved.
Copyright (c) 2013, MapsWithMe GmbH. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@ -20,7 +20,7 @@
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
******************************************************************************/
package app.organicmaps.api.sample.capitals;
import android.app.Activity;
@ -57,21 +57,21 @@ public class CityDetailsActivity extends Activity
super.onCreate(savedInstanceState);
setContentView(R.layout.city_details_activity);
mName = findViewById(R.id.name);
mAltNames = findViewById(R.id.altNames);
mCountry = findViewById(R.id.cCode);
mName = (TextView) findViewById(R.id.name);
mAltNames = (TextView) findViewById(R.id.altNames);
mCountry = (TextView) findViewById(R.id.cCode);
mLat = findViewById(R.id.lat);
mLon = findViewById(R.id.lon);
mElev = findViewById(R.id.elevation);
mLat = (TextView) findViewById(R.id.lat);
mLon = (TextView) findViewById(R.id.lon);
mElev = (TextView) findViewById(R.id.elevation);
mPopulation = findViewById(R.id.population);
mTimeZone = findViewById(R.id.timeZone);
mPopulation = (TextView) findViewById(R.id.population);
mTimeZone = (TextView) findViewById(R.id.timeZone);
findViewById(R.id.showOnMap).setOnClickListener(v -> {
final Intent intent = new MapRequest()
.addPoint(mCity.toPoint())
.setAppName(getString(R.string.app_name))
.setTitle(getString(R.string.app_name))
.toIntent();
startActivityForResult(intent, REQ_CODE_CITY);
});

View file

@ -3,13 +3,13 @@ plugins {
}
android {
namespace 'app.organicmaps.api.sample.pick_point'
compileSdk project.targetSdkVersion
defaultConfig {
applicationId "app.organicmaps.api.sample.pick_point"
minSdk project.minSdkVersion
targetSdk project.targetSdkVersion
buildToolsVersion project.buildToolsVersion
versionCode 1
versionName "1.0"
}
@ -26,11 +26,7 @@ android {
}
}
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
}
dependencies {
implementation 'com.google.android.material:material:1.12.0'
implementation 'com.google.android.material:material:1.6.1'
implementation project(path: ':lib')
}

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest package="app.organicmaps.api.sample.pick_point"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"

View file

@ -31,8 +31,8 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import app.organicmaps.api.CrosshairRequest;
import app.organicmaps.api.DownloadDialog;
import app.organicmaps.api.MapRequest;
import app.organicmaps.api.PickPointResponse;
import app.organicmaps.api.Point;
@ -48,10 +48,12 @@ public class MainActivity extends AppCompatActivity
new ActivityResultContracts.StartActivityForResult(),
result -> onPointSelected(result.getResultCode(), result.getData()));
findViewById(R.id.pick_point).setOnClickListener(v -> {
final Intent request = new CrosshairRequest().setAppName(getString(R.string.app_name))
final Intent request = new MapRequest()
.setTitle(getString(R.string.app_name))
.setPickPointMode(true)
.toIntent();
if (getApplicationContext().getPackageManager().resolveActivity(request, 0) == null)
{
new DownloadDialog(this).show();