Compare commits
13 commits
alex-fixes
...
master
Author | SHA1 | Date | |
---|---|---|---|
879daa0ef0 | |||
|
464cff7c02 | ||
bbcf902d5c | |||
619243f528 | |||
ac6f13ecf9 | |||
|
5cca3797ec | ||
|
9113776e22 | ||
|
1619b32afb | ||
|
f3a87782f0 | ||
363d7f07d9 | |||
|
dcd09663de | ||
|
dff6e1decd | ||
7774cbb246 |
31
README.md
|
@ -14,6 +14,8 @@ 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.
|
||||
|
@ -30,9 +32,8 @@ You don't need any additional permissions in your AndroidManifest.xml to use API
|
|||
## Classes Overview and HOW TO
|
||||
Core classes you will work with are:
|
||||
|
||||
* [app.organicmaps.api.Api][linkApiClass] - static class with methods such as `showPointOnMap(Activity, double, double, String)` etc.
|
||||
* [app.organicmaps.api.Point][linkPointClass] - model of POI, includes lat, lon, name, id, and style data.
|
||||
* [app.organicmaps.api.Response][linkRespClass] - helps you to extract response from Organic Maps by applying `Response.extractFromIntent(Intent)` to Intent. Contains Point data.
|
||||
* [app.organicmaps.api.PickPointResponse][linkRespClass] - helps you to extract response from Organic Maps by applying `Response.extractFromIntent(Intent)` to Intent. Contains Point data.
|
||||
|
||||
### Show Points on the Map
|
||||
|
||||
|
@ -74,7 +75,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 PentingIntent that Organic Maps will send back to
|
||||
distinguish it later, and PendingIntent 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
|
||||
|
@ -124,13 +125,12 @@ your application when user press "More Info" button :
|
|||
|
||||
## FAQ
|
||||
|
||||
#### 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.
|
||||
|
||||
#### Which versions of Organic Maps support API calls?
|
||||
All versions since 2.4.0 and above support API calls.
|
||||
|
||||
All versions since 2022-07-26 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.
|
||||
|
||||

|
||||
|
@ -142,9 +142,12 @@ Nothing serious. API library will show simple dialog with gentle offer to downlo
|
|||
-------------------------------------------------------------------------------
|
||||
## API Code License
|
||||
|
||||
Copyright (c) 2022, Organic Maps OÜ.
|
||||
Copyright (c) 2024, 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:
|
||||
|
@ -155,11 +158,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]: http://developer.android.com/reference/android/app/PendingIntent.html "PendingIntent"
|
||||
[linkPIntent]: https://developer.android.com/reference/android/app/PendingIntent.html "PendingIntent"
|
||||
[linkRepo]: https://github.com/organicmaps/api-android "GitHub Repository"
|
||||
[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/Response.java "Response.java"
|
||||
[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"
|
||||
[linkSampleSource]: https://github.com/organicmaps/api-android/tree/master/sample-app-capitals "Api Source Code"
|
||||
|
|
12
build.gradle
|
@ -1,9 +1,15 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '7.2.1' apply false
|
||||
id 'com.android.library' version '7.2.1' apply false
|
||||
id 'com.android.application' version '8.5.1' apply false
|
||||
id 'com.android.library' version '8.5.1' apply false
|
||||
}
|
||||
|
||||
project.ext {
|
||||
minSdkVersion = 21
|
||||
targetSdkVersion = 34
|
||||
javaVersion = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
}
|
||||
|
|
5
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,5 @@
|
|||
#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
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -3,13 +3,13 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdk 32
|
||||
namespace 'app.organicmaps.api'
|
||||
compileSdk project.targetSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk 21
|
||||
targetSdk 32
|
||||
minSdk project.minSdkVersion
|
||||
targetSdk project.targetSdkVersion
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,16 @@ android {
|
|||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility project.javaVersion
|
||||
targetCompatibility project.javaVersion
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
|
||||
}
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.4.2'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
}
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="app.organicmaps.api"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest 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>
|
|
@ -1,154 +0,0 @@
|
|||
/******************************************************************************
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
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:
|
||||
|
||||
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.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
|
||||
public final class Api
|
||||
{
|
||||
|
||||
/**
|
||||
* Most detailed level, buildings and trees are seen.
|
||||
*/
|
||||
public static final double ZOOM_MAX = 19;
|
||||
/**
|
||||
* Least detailed level, continents are seen.
|
||||
*/
|
||||
public static final double ZOOM_MIN = 1;
|
||||
|
||||
public static void showOrganicMapsUrl(Activity caller, PendingIntent pendingIntent, double zoomLevel, String url)
|
||||
{
|
||||
final Uri uri = Uri.parse(url);
|
||||
final String[] latlon = uri.getQueryParameter("ll").split(",");
|
||||
final double lat = Double.parseDouble(latlon[0]);
|
||||
final double lon = Double.parseDouble(latlon[1]);
|
||||
final String name = uri.getQueryParameter("n");
|
||||
final String id = uri.getQueryParameter("id");
|
||||
|
||||
showPointsOnMap(caller, name, zoomLevel, pendingIntent, new Point(lat, lon, name, id));
|
||||
}
|
||||
|
||||
public static void sendRequest(Activity caller, Request request)
|
||||
{
|
||||
final Intent mwmIntent = request.toIntent(caller);
|
||||
|
||||
if (isOrganicMapsInstalled(caller))
|
||||
{
|
||||
caller.startActivity(mwmIntent);
|
||||
}
|
||||
else
|
||||
(new DownloadDialog(caller)).show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows single point on the map.
|
||||
*
|
||||
* @param caller
|
||||
* @param lat
|
||||
* @param lon
|
||||
* @param name
|
||||
*/
|
||||
public static void showPointOnMap(Activity caller, double lat, double lon, String name)
|
||||
{
|
||||
showPointsOnMap(caller, null, (PendingIntent) null, new Point(lat, lon, name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows single point on the map using specified zoom level in range from
|
||||
* {@link Api#ZOOM_MIN} to {@link Api#ZOOM_MAX}.
|
||||
*
|
||||
* @param caller
|
||||
* @param lat
|
||||
* @param lon
|
||||
* @param name
|
||||
* @param zoomLevel
|
||||
*/
|
||||
public static void showPointOnMap(Activity caller, double lat, double lon, String name, double zoomLevel)
|
||||
{
|
||||
showPointsOnMap(caller, null, zoomLevel, null, new Point(lat, lon, name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows set of points on the map.
|
||||
*
|
||||
* @param caller
|
||||
* @param title
|
||||
* @param points
|
||||
*/
|
||||
public static void showPointsOnMap(Activity caller, String title, Point... points)
|
||||
{
|
||||
showPointsOnMap(caller, title, null, points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows set of points on the maps and allows OrganicMapsApplication to send
|
||||
* {@link PendingIntent} provided by client application.
|
||||
*
|
||||
* @param caller
|
||||
* @param title
|
||||
* @param pendingIntent
|
||||
* @param points
|
||||
*/
|
||||
public static void showPointsOnMap(Activity caller, String title, PendingIntent pendingIntent, Point... points)
|
||||
{
|
||||
showPointsOnMap(caller, title, -1, pendingIntent, points);
|
||||
}
|
||||
|
||||
private static void showPointsOnMap(Activity caller, String title, double zoomLevel, PendingIntent pendingIntent,
|
||||
Point... points)
|
||||
{
|
||||
final Request request = new Request()
|
||||
.setTitle(title)
|
||||
.setZoomLevel(zoomLevel)
|
||||
.setPendingIntent(pendingIntent)
|
||||
.setPoints(points);
|
||||
sendRequest(caller, request);
|
||||
}
|
||||
|
||||
public static void pickPoint(Activity caller, String title, PendingIntent pi)
|
||||
{
|
||||
final Request request = new Request()
|
||||
.setTitle(title)
|
||||
.setPickPointMode(true)
|
||||
.setPendingIntent(pi);
|
||||
sendRequest(caller, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if Organic Maps is installed on the device.
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean isOrganicMapsInstalled(Context context)
|
||||
{
|
||||
final Intent intent = new Intent(Const.ACTION_OM_REQUEST);
|
||||
return context.getPackageManager().resolveActivity(intent, 0) != null;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
/******************************************************************************
|
||||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
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:
|
||||
|
@ -20,37 +19,25 @@
|
|||
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;
|
||||
|
||||
public class Const
|
||||
{
|
||||
// Common
|
||||
static final String API_SCHEME = "om://";
|
||||
static final String AUTHORITY = "app.organicmaps.api";
|
||||
static final String EXTRA_PREFIX = AUTHORITY + ".extra";
|
||||
|
||||
/* Request extras */
|
||||
static final String AUTHORITY = "com.mapswithme.maps.api";
|
||||
public static final String EXTRA_URL = AUTHORITY + ".url";
|
||||
public static final String EXTRA_TITLE = AUTHORITY + ".title";
|
||||
public static final String EXTRA_API_VERSION = AUTHORITY + ".version";
|
||||
public static final String EXTRA_CALLER_APP_INFO = AUTHORITY + ".caller_app_info";
|
||||
public static final String EXTRA_HAS_PENDING_INTENT = AUTHORITY + ".has_pen_intent";
|
||||
public static final String EXTRA_CALLER_PENDING_INTENT = AUTHORITY + ".pending_intent";
|
||||
public static final String EXTRA_RETURN_ON_BALLOON_CLICK = AUTHORITY + ".return_on_balloon_click";
|
||||
public static final String EXTRA_PICK_POINT = AUTHORITY + ".pick_point";
|
||||
public static final String EXTRA_CUSTOM_BUTTON_NAME = AUTHORITY + ".custom_button_name";
|
||||
// Request extras
|
||||
public static final String EXTRA_PICK_POINT = EXTRA_PREFIX + ".PICK_POINT";
|
||||
|
||||
|
||||
/* Response extras */
|
||||
/* Point part-by-part*/
|
||||
public static final String EXTRA_OM_RESPONSE_POINT_NAME = AUTHORITY + ".point_name";
|
||||
public static final String EXTRA_OM_RESPONSE_POINT_LAT = AUTHORITY + ".point_lat";
|
||||
public static final String EXTRA_OM_RESPONSE_POINT_LON = AUTHORITY + ".point_lon";
|
||||
public static final String EXTRA_OM_RESPONSE_POINT_ID = AUTHORITY + ".point_id";
|
||||
public static final String EXTRA_OM_RESPONSE_ZOOM = AUTHORITY + ".zoom_level";
|
||||
|
||||
|
||||
public static final String ACTION_OM_REQUEST = AUTHORITY + ".request";
|
||||
static final int API_VERSION = 2;
|
||||
static final String CALLBACK_PREFIX = "mapswithme.client.";
|
||||
// Response extras
|
||||
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";
|
||||
public static final String EXTRA_POINT_ID = EXTRA_PREFIX + ".POINT_ID";
|
||||
public static final String EXTRA_ZOOM_LEVEL = EXTRA_PREFIX + ".ZOOM_LEVEL";
|
||||
|
||||
private Const() {}
|
||||
}
|
||||
|
|
55
lib/src/main/java/app/organicmaps/api/CrosshairRequest.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. 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;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/******************************************************************************
|
||||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
Copyright (c) 2013, MapsWithMe GmbH. All rights reserved.
|
||||
|
||||
|
@ -20,7 +20,8 @@
|
|||
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.app.Activity;
|
||||
|
|
111
lib/src/main/java/app/organicmaps/api/MapRequest.java
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class MapRequest
|
||||
{
|
||||
private List<Point> mPoints = new ArrayList<>();
|
||||
private String mAppName;
|
||||
private double mZoomLevel;
|
||||
// pick point mode
|
||||
private boolean mPickPointMode;
|
||||
|
||||
public @NonNull MapRequest
|
||||
setAppName(String appName)
|
||||
{
|
||||
mAppName = appName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
MapRequest addPoint(Point point)
|
||||
{
|
||||
mPoints.add(point);
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
MapRequest setPoints(Collection<Point> points)
|
||||
{
|
||||
mPoints = new ArrayList<>(points);
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
MapRequest setZoomLevel(double zoomLevel)
|
||||
{
|
||||
mZoomLevel = zoomLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull MapRequest setPickPointMode(boolean pickPointMode)
|
||||
{
|
||||
mPickPointMode = pickPointMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
Intent toIntent()
|
||||
{
|
||||
final StringBuilder builder = new StringBuilder(Const.API_SCHEME);
|
||||
builder.append("map?");
|
||||
|
||||
// title
|
||||
if (mAppName != null)
|
||||
builder.append("appname").append("=").append(Uri.encode(mAppName)).append("&");
|
||||
// zoom
|
||||
if (mZoomLevel != 0.0)
|
||||
builder.append("z").append("=").append(mZoomLevel).append("&");
|
||||
|
||||
// points
|
||||
for (final Point point : mPoints)
|
||||
{
|
||||
if (point != null)
|
||||
{
|
||||
builder.append("ll=").append(String.format(Locale.US, "%f,%f&", point.getLat(), point.getLon()));
|
||||
if (point.getName() != null)
|
||||
builder.append("n").append("=").append(Uri.encode(point.getName())).append("&");
|
||||
if (point.getId() != null)
|
||||
builder.append("id").append("=").append(Uri.encode(point.getId())).append("&");
|
||||
if (point.getStyle() != null)
|
||||
builder.append("s").append("=").append(Uri.encode(point.getStyle().getName())).append("&");
|
||||
}
|
||||
}
|
||||
|
||||
final Uri uri = Uri.parse(builder.toString());
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
if (mPickPointMode)
|
||||
intent.putExtra(Const.EXTRA_PICK_POINT, true);
|
||||
return intent;
|
||||
}
|
||||
}
|
60
lib/src/main/java/app/organicmaps/api/OrganicMapsApi.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
/******************************************************************************
|
||||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
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:
|
||||
|
@ -20,59 +19,57 @@
|
|||
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.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class Response
|
||||
public class PickPointResponse
|
||||
{
|
||||
private final static double INVALID_LL = Double.MIN_VALUE;
|
||||
private Point mPoint;
|
||||
private double mZoomLevel;
|
||||
|
||||
private Response() {}
|
||||
private PickPointResponse() {}
|
||||
|
||||
/**
|
||||
* Factory method to extract response data from intent.
|
||||
* Factory method to extract response from intent.
|
||||
*
|
||||
* @param context
|
||||
* @param intent
|
||||
* @return
|
||||
* @param intent an intent to extra data from
|
||||
* @return PointResponse
|
||||
*/
|
||||
public static Response extractFromIntent(Context context, Intent intent)
|
||||
public static PickPointResponse extractFromIntent(final Intent intent)
|
||||
{
|
||||
final Response response = new Response();
|
||||
// parse point
|
||||
final double lat = intent.getDoubleExtra(Const.EXTRA_OM_RESPONSE_POINT_LAT, INVALID_LL);
|
||||
final double lon = intent.getDoubleExtra(Const.EXTRA_OM_RESPONSE_POINT_LON, INVALID_LL);
|
||||
final String name = intent.getStringExtra(Const.EXTRA_OM_RESPONSE_POINT_NAME);
|
||||
final String id = intent.getStringExtra(Const.EXTRA_OM_RESPONSE_POINT_ID);
|
||||
|
||||
// parse additional info
|
||||
response.mZoomLevel = intent.getDoubleExtra(Const.EXTRA_OM_RESPONSE_ZOOM, 9);
|
||||
|
||||
if (lat != INVALID_LL && lon != INVALID_LL)
|
||||
response.mPoint = new Point(lat, lon, name, id);
|
||||
else
|
||||
response.mPoint = null;
|
||||
|
||||
final PickPointResponse response = new PickPointResponse();
|
||||
final Bundle extras = intent.getExtras();
|
||||
final double lat = extras.getDouble(Const.EXTRA_POINT_LAT);
|
||||
final double lon = extras.getDouble(Const.EXTRA_POINT_LON);
|
||||
final String name = extras.getString(Const.EXTRA_POINT_NAME);
|
||||
final String id = extras.getString(Const.EXTRA_POINT_ID);
|
||||
response.mPoint = new Point(lat, lon, name, id);
|
||||
response.mZoomLevel = extras.getDouble(Const.EXTRA_ZOOM_LEVEL);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return point, for which user requested more information in Organic Maps application.
|
||||
* @return selected point
|
||||
*/
|
||||
public Point getPoint() {return mPoint;}
|
||||
public Point getPoint()
|
||||
{
|
||||
return mPoint;
|
||||
}
|
||||
|
||||
public boolean hasPoint() {return mPoint != null;}
|
||||
|
||||
public double getZoomLevel() {return mZoomLevel;}
|
||||
/**
|
||||
* @return current zoom level
|
||||
*/
|
||||
public double getZoomLevel()
|
||||
{
|
||||
return mZoomLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Response [SelectedPoint=" + mPoint + "]";
|
||||
return "PointResponse [Point=" + mPoint + "]";
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/******************************************************************************
|
||||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
Copyright (c) 2013, MapsWithMe GmbH. All rights reserved.
|
||||
|
||||
|
@ -20,10 +20,13 @@
|
|||
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 androidx.annotation.NonNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* POI wrapper object.
|
||||
|
@ -53,15 +56,6 @@ public final class Point implements Serializable
|
|||
this.mId = id;
|
||||
}
|
||||
|
||||
public Point(double lat, double lon, String name, String id, Style style)
|
||||
{
|
||||
this.mLat = lat;
|
||||
this.mLon = lon;
|
||||
this.mName = name;
|
||||
this.mId = id;
|
||||
this.mStyle = style;
|
||||
}
|
||||
|
||||
public double getLat() {return mLat;}
|
||||
|
||||
public double getLon() {return mLon;}
|
||||
|
@ -74,7 +68,7 @@ public final class Point implements Serializable
|
|||
* Sets string ID for this point. Internally it is not used to distinguish point,
|
||||
* it's purpose to help clients code to associate point with domain objects of their application.
|
||||
*
|
||||
* @param id
|
||||
* @param id point id
|
||||
*/
|
||||
public void setId(String id) {mId = id;}
|
||||
|
||||
|
@ -90,9 +84,8 @@ public final class Point implements Serializable
|
|||
this.mStyle = style;
|
||||
}
|
||||
|
||||
public String getStyleForUrl() {return (mStyle == null) ? null : mStyle.getName();}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String toString()
|
||||
{
|
||||
return "OMPoint [lat=" + mLat +
|
||||
|
@ -135,9 +128,10 @@ public final class Point implements Serializable
|
|||
if (Double.doubleToLongBits(mLon) != Double.doubleToLongBits(other.mLon))
|
||||
return false;
|
||||
|
||||
return mName == null ? other.mName == null : mName.equals(other.mName);
|
||||
return Objects.equals(mName, other.mName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Supported styles for Organic Maps. Each appears as a small flag of the appropriate colour.
|
||||
*/
|
||||
|
@ -171,7 +165,7 @@ public final class Point implements Serializable
|
|||
/**
|
||||
* @return name as it should appear in the MAPS.ME URL.
|
||||
*/
|
||||
private String getName()
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
/******************************************************************************
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
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:
|
||||
|
||||
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.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class Request
|
||||
{
|
||||
|
||||
// **
|
||||
private List<Point> mPoints = new ArrayList<>();
|
||||
private PendingIntent mPendingIntent;
|
||||
private String mTitle;
|
||||
private double mZoomLevel = 1;
|
||||
private boolean mReturnOnBalloonClick;
|
||||
private boolean mPickPoint = false;
|
||||
private String mCustomButtonName = "";
|
||||
// **
|
||||
|
||||
private static StringBuilder createMwmUrl(Context context, String title, double zoomLevel, List<Point> points)
|
||||
{
|
||||
final StringBuilder urlBuilder = new StringBuilder("om://map?");
|
||||
// version
|
||||
urlBuilder.append("v=").append(Const.API_VERSION).append("&");
|
||||
// back url, always not null
|
||||
urlBuilder.append("backurl=").append(getCallbackAction(context)).append("&");
|
||||
// title
|
||||
appendIfNotNull(urlBuilder, "appname", title);
|
||||
// zoom
|
||||
appendIfNotNull(urlBuilder, "z", isValidZoomLevel(zoomLevel) ? String.valueOf(zoomLevel) : null);
|
||||
|
||||
// points
|
||||
for (final Point point : points)
|
||||
{
|
||||
if (point != null)
|
||||
{
|
||||
urlBuilder.append("ll=").append(String.format(Locale.US, "%f,%f&", point.getLat(), point.getLon()));
|
||||
|
||||
appendIfNotNull(urlBuilder, "n", point.getName());
|
||||
appendIfNotNull(urlBuilder, "id", point.getId());
|
||||
appendIfNotNull(urlBuilder, "s", point.getStyleForUrl());
|
||||
}
|
||||
}
|
||||
|
||||
return urlBuilder;
|
||||
}
|
||||
|
||||
private static String getCallbackAction(Context context)
|
||||
{
|
||||
return Const.CALLBACK_PREFIX + context.getPackageName();
|
||||
}
|
||||
|
||||
private static Intent addCommonExtras(Context context, Intent intent)
|
||||
{
|
||||
intent.putExtra(Const.EXTRA_CALLER_APP_INFO, context.getApplicationInfo());
|
||||
intent.putExtra(Const.EXTRA_API_VERSION, Const.API_VERSION);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
private static StringBuilder appendIfNotNull(StringBuilder builder, String key, String value)
|
||||
{
|
||||
if (value != null)
|
||||
builder.append(key).append("=").append(Uri.encode(value)).append("&");
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static boolean isValidZoomLevel(double zoom)
|
||||
{
|
||||
return zoom >= Api.ZOOM_MIN && zoom <= Api.ZOOM_MAX;
|
||||
}
|
||||
|
||||
public Request setCustomButtonName(String buttonName)
|
||||
{
|
||||
mCustomButtonName = buttonName != null ? buttonName : "";
|
||||
return this;
|
||||
}
|
||||
|
||||
public Request setTitle(String title)
|
||||
{
|
||||
mTitle = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Request setPickPointMode(boolean pickPoint)
|
||||
{
|
||||
mPickPoint = pickPoint;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Request addPoint(Point point)
|
||||
{
|
||||
mPoints.add(point);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Request addPoint(double lat, double lon, String name, String id)
|
||||
{
|
||||
return addPoint(new Point(lat, lon, name, id));
|
||||
}
|
||||
|
||||
public Request setPoints(Collection<Point> points)
|
||||
{
|
||||
mPoints = new ArrayList<Point>(points);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Below are utilities from OrganicMapsApi because we are not "Feature Envy"
|
||||
|
||||
public Request setReturnOnBalloonClick(boolean doReturn)
|
||||
{
|
||||
mReturnOnBalloonClick = doReturn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Request setZoomLevel(double zoomLevel)
|
||||
{
|
||||
mZoomLevel = zoomLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Request setPendingIntent(PendingIntent pi)
|
||||
{
|
||||
mPendingIntent = pi;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Intent toIntent(Context context)
|
||||
{
|
||||
final Intent mwmIntent = new Intent(Const.ACTION_OM_REQUEST);
|
||||
|
||||
// url
|
||||
final String mwmUrl = createMwmUrl(context, mTitle, mZoomLevel, mPoints).toString();
|
||||
mwmIntent.putExtra(Const.EXTRA_URL, mwmUrl);
|
||||
// title
|
||||
mwmIntent.putExtra(Const.EXTRA_TITLE, mTitle);
|
||||
// more
|
||||
mwmIntent.putExtra(Const.EXTRA_RETURN_ON_BALLOON_CLICK, mReturnOnBalloonClick);
|
||||
// pick point
|
||||
mwmIntent.putExtra(Const.EXTRA_PICK_POINT, mPickPoint);
|
||||
// custom button name
|
||||
mwmIntent.putExtra(Const.EXTRA_CUSTOM_BUTTON_NAME, mCustomButtonName);
|
||||
|
||||
final boolean hasIntent = mPendingIntent != null;
|
||||
mwmIntent.putExtra(Const.EXTRA_HAS_PENDING_INTENT, hasIntent);
|
||||
if (hasIntent)
|
||||
mwmIntent.putExtra(Const.EXTRA_CALLER_PENDING_INTENT, mPendingIntent);
|
||||
|
||||
addCommonExtras(context, mwmIntent);
|
||||
|
||||
return mwmIntent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Hidden This method is internal only.
|
||||
* Used for compatibility.
|
||||
*/
|
||||
Request setPoints(Point[] points)
|
||||
{
|
||||
return setPoints(Arrays.asList(points));
|
||||
}
|
||||
|
||||
}
|
|
@ -3,16 +3,15 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdk 32
|
||||
namespace 'app.organicmaps.api.sample.capitals'
|
||||
compileSdk project.targetSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
applicationId "app.organicmaps.api.sample.capitals"
|
||||
minSdk 21
|
||||
targetSdk 32
|
||||
minSdk project.minSdkVersion
|
||||
targetSdk project.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -22,14 +21,17 @@ android {
|
|||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility project.javaVersion
|
||||
targetCompatibility project.javaVersion
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
|
||||
}
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.4.2'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation project(path: ':lib')
|
||||
}
|
|
@ -21,8 +21,7 @@
|
|||
OF SUCH DAMAGE.
|
||||
-->
|
||||
|
||||
<manifest package="app.organicmaps.api.sample.capitals"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/******************************************************************************
|
||||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
Copyright (c) 2013, MapsWithMe GmbH. All rights reserved.
|
||||
|
||||
|
@ -20,24 +20,28 @@
|
|||
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;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import app.organicmaps.api.Point;
|
||||
import app.organicmaps.api.Api;
|
||||
import app.organicmaps.api.MapRequest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CapitalsListActivity extends ListActivity
|
||||
{
|
||||
private static final int REQ_CODE_CITY = 1;
|
||||
|
||||
CityAdapter mCityAdapter;
|
||||
|
||||
@Override
|
||||
|
@ -61,12 +65,27 @@ public class CapitalsListActivity extends ListActivity
|
|||
|
||||
private void showCityOnOMMap(City ... cities)
|
||||
{
|
||||
Point[] points = new Point[cities.length];
|
||||
for (int i = 0; i < cities.length; i++)
|
||||
points[i] = cities[i].toPoint();
|
||||
final ArrayList<Point> points = new ArrayList<>(cities.length);
|
||||
for (City city : cities)
|
||||
points.add(city.toPoint());
|
||||
|
||||
final String title = cities.length == 1 ? cities[0].getName() : "Capitals of the World";
|
||||
Api.showPointsOnMap(this, title, CityDetailsActivity.getPendingIntent(this), points);
|
||||
final Intent intent = new MapRequest()
|
||||
.setPoints(points)
|
||||
.setAppName(title)
|
||||
.toIntent();
|
||||
this.startActivityForResult(intent, REQ_CODE_CITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode != REQ_CODE_CITY || resultCode != RESULT_OK)
|
||||
return;
|
||||
|
||||
final Intent intent = new Intent(this, CityDetailsActivity.class);
|
||||
intent.putExtra(CityDetailsActivity.EXTRA_POINT, data);
|
||||
}
|
||||
|
||||
private static class CityAdapter extends ArrayAdapter<City>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/******************************************************************************
|
||||
/*
|
||||
Copyright (c) 2022, Organic Maps OÜ. 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;
|
||||
|
@ -55,9 +55,8 @@ public class City
|
|||
this.altNames = altNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return name; }
|
||||
public Point toPoint() { return new Point(lat, lon, name, id); }
|
||||
public String toString() { return name; }
|
||||
public Point toPoint() { return new Point(lat, lon, name, id); }
|
||||
|
||||
public String getId() { return id; }
|
||||
public String getName() { return name; }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/******************************************************************************
|
||||
Copyright (c) 2022, Organic Maps OÜ. All rights reserved.
|
||||
/*
|
||||
Copyright (c) 2022-2023, Organic Maps OÜ. All rights reserved.
|
||||
Copyright (c) 2013, MapsWithMe GmbH. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -20,25 +20,24 @@
|
|||
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;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import app.organicmaps.api.Response;
|
||||
import app.organicmaps.api.Api;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import app.organicmaps.api.PickPointResponse;
|
||||
import app.organicmaps.api.Point;
|
||||
import app.organicmaps.api.MapRequest;
|
||||
|
||||
public class CityDetailsActivity extends Activity
|
||||
{
|
||||
public static String EXTRA_FROM_ORGANICMAPS = "from-organicmaps";
|
||||
|
||||
private static final int REQ_CODE_CITY = 1;
|
||||
public static String EXTRA_POINT = "point";
|
||||
private TextView mName;
|
||||
private TextView mAltNames;
|
||||
private TextView mCountry;
|
||||
|
@ -52,72 +51,65 @@ public class CityDetailsActivity extends Activity
|
|||
|
||||
private City mCity;
|
||||
|
||||
public static PendingIntent getPendingIntent(Context context)
|
||||
{
|
||||
final Intent i = new Intent(context, CityDetailsActivity.class);
|
||||
i.putExtra(EXTRA_FROM_ORGANICMAPS, true);
|
||||
return PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_IMMUTABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.city_details_activity);
|
||||
|
||||
mName = (TextView) findViewById(R.id.name);
|
||||
mAltNames = (TextView) findViewById(R.id.altNames);
|
||||
mCountry = (TextView) findViewById(R.id.cCode);
|
||||
mName = findViewById(R.id.name);
|
||||
mAltNames = findViewById(R.id.altNames);
|
||||
mCountry = findViewById(R.id.cCode);
|
||||
|
||||
mLat = (TextView) findViewById(R.id.lat);
|
||||
mLon = (TextView) findViewById(R.id.lon);
|
||||
mElev = (TextView) findViewById(R.id.elevation);
|
||||
mLat = findViewById(R.id.lat);
|
||||
mLon = findViewById(R.id.lon);
|
||||
mElev = findViewById(R.id.elevation);
|
||||
|
||||
mPopulation = (TextView) findViewById(R.id.population);
|
||||
mTimeZone = (TextView) findViewById(R.id.timeZone);
|
||||
mPopulation = findViewById(R.id.population);
|
||||
mTimeZone = findViewById(R.id.timeZone);
|
||||
|
||||
findViewById(R.id.showOnMap).setOnClickListener(new OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
Api.showPointsOnMap(CityDetailsActivity.this,mCity.getName(),
|
||||
CityDetailsActivity.getPendingIntent(CityDetailsActivity.this),mCity.toPoint());
|
||||
}
|
||||
findViewById(R.id.showOnMap).setOnClickListener(v -> {
|
||||
final Intent intent = new MapRequest()
|
||||
.addPoint(mCity.toPoint())
|
||||
.setAppName(getString(R.string.app_name))
|
||||
.toIntent();
|
||||
startActivityForResult(intent, REQ_CODE_CITY);
|
||||
});
|
||||
|
||||
handleIntent(getIntent());
|
||||
final Intent data = getIntent().getParcelableExtra(EXTRA_POINT);
|
||||
handleResponse(data);
|
||||
}
|
||||
|
||||
private void handleResponse(final @NonNull Intent data)
|
||||
{
|
||||
final PickPointResponse response = PickPointResponse.extractFromIntent(data);
|
||||
final Point point = response.getPoint();
|
||||
mCity = City.fromPoint(point);
|
||||
|
||||
if (mCity != null)
|
||||
{
|
||||
mName.setText(mCity.getName());
|
||||
mAltNames.setText(mCity.getAltNames());
|
||||
mCountry.setText(mCity.getCountryCode());
|
||||
|
||||
mLat.setText(String.valueOf(mCity.getLat()));
|
||||
mLon.setText(String.valueOf(mCity.getLon()));
|
||||
final String level = mCity.getElevation() != -9999 ? String.valueOf(mCity.getElevation()) : "No Data";
|
||||
mElev.setText(level);
|
||||
|
||||
final String population = mCity.getPopulation() != -1 ? String.valueOf(mCity.getPopulation()) : "No Data";
|
||||
mPopulation.setText(population);
|
||||
mTimeZone.setText(mCity.getTimeZone());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent)
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
super.onNewIntent(intent);
|
||||
handleIntent(intent);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode != REQ_CODE_CITY || resultCode != RESULT_OK)
|
||||
return;
|
||||
|
||||
handleResponse(data);
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent)
|
||||
{
|
||||
if (intent.getBooleanExtra(EXTRA_FROM_ORGANICMAPS, false))
|
||||
{
|
||||
final Response response = Response.extractFromIntent(this, intent);
|
||||
mCity = City.fromPoint(response.getPoint());
|
||||
|
||||
if (mCity != null)
|
||||
{
|
||||
mName.setText(mCity.getName());
|
||||
mAltNames.setText(mCity.getAltNames());
|
||||
mCountry.setText(mCity.getCountryCode());
|
||||
|
||||
mLat.setText(mCity.getLat() + "");
|
||||
mLon.setText(mCity.getLon() + "");
|
||||
final String evel = mCity.getElevation() != -9999 ? String.valueOf(mCity.getElevation()) : "No Data";
|
||||
mElev.setText(evel);
|
||||
|
||||
final String popul = mCity.getPopulation() != -1 ? String.valueOf(mCity.getPopulation()) : "No Data";
|
||||
mPopulation.setText(popul);
|
||||
mTimeZone.setText(mCity.getTimeZone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,5 +12,6 @@
|
|||
<string name="population">Population:</string>
|
||||
<string name="time_zone">Time Zone:</string>
|
||||
<string name="elevation">Elevation:</string>
|
||||
<string name="cancelled">Cancelled</string>
|
||||
|
||||
</resources>
|
||||
|
|
1
sample-pick-point/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
36
sample-pick-point/build.gradle
Normal file
|
@ -0,0 +1,36 @@
|
|||
plugins {
|
||||
id 'com.android.application'
|
||||
}
|
||||
|
||||
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
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility project.javaVersion
|
||||
targetCompatibility project.javaVersion
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
implementation project(path: ':lib')
|
||||
}
|
21
sample-pick-point/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
21
sample-pick-point/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/Theme.AppCompat"
|
||||
android:supportsRtl="true">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,83 @@
|
|||
/******************************************************************************
|
||||
Copyright (c) 2022, Organic Maps OÜ. 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.sample.pick_point;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
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.PickPointResponse;
|
||||
import app.organicmaps.api.Point;
|
||||
|
||||
public class MainActivity extends AppCompatActivity
|
||||
{
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
final ActivityResultLauncher<Intent> pickPoint = registerForActivityResult(
|
||||
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))
|
||||
.toIntent();
|
||||
if (getApplicationContext().getPackageManager().resolveActivity(request, 0) == null)
|
||||
{
|
||||
new DownloadDialog(this).show();
|
||||
return;
|
||||
}
|
||||
|
||||
pickPoint.launch(request);
|
||||
});
|
||||
}
|
||||
|
||||
protected void onPointSelected(int resultCode, Intent data)
|
||||
{
|
||||
if (resultCode == RESULT_CANCELED)
|
||||
{
|
||||
Toast.makeText(this, getString(R.string.cancelled), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
else if (resultCode != RESULT_OK)
|
||||
{
|
||||
throw new AssertionError("Unsupported resultCode: " + resultCode);
|
||||
}
|
||||
|
||||
final PickPointResponse response = PickPointResponse.extractFromIntent(data);
|
||||
final Point point = response.getPoint();
|
||||
|
||||
final String message = getString(R.string.result, point.getLat(), point.getLon(), point.getId(), point.getName(), response.getZoomLevel());
|
||||
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<vector xmlns:aapt="http://schemas.android.com/aapt"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
16
sample-pick-point/src/main/res/layout/activity_main.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<Button
|
||||
android:id="@+id/pick_point"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pick_point" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
BIN
sample-pick-point/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
BIN
sample-pick-point/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 982 B |
After Width: | Height: | Size: 1.7 KiB |
BIN
sample-pick-point/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.8 KiB |
BIN
sample-pick-point/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
BIN
sample-pick-point/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 7.6 KiB |
6
sample-pick-point/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<resources>
|
||||
<string name="app_name">Pick Point Sample</string>
|
||||
<string name="pick_point">Pick Point</string>
|
||||
<string name="result">Result: lat=%1$.4f lon=%2$.4f id=%3$s name=%4$s zoomLevel=%5$.2f</string>
|
||||
<string name="cancelled">Cancelled</string>
|
||||
</resources>
|
|
@ -14,4 +14,5 @@ dependencyResolutionManagement {
|
|||
}
|
||||
rootProject.name = "Organic Maps API"
|
||||
include ':sample-app-capitals'
|
||||
include ':sample-pick-point'
|
||||
include ':lib'
|
||||
|
|