diff options
author | Dmitry Kunin <dkunin@mapswith.me> | 2013-05-24 17:54:25 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 01:55:24 +0300 |
commit | 8069be60b78d9d76840b8f2c54c4b920f9a4422c (patch) | |
tree | 37c48e71a67fba69eab90e7a52cd4f7b3bfcf36e /api/android | |
parent | 12cf70fadba7db2ce88e0f009a5e33e2c69ee86d (diff) |
[android] Library code.
[android] Files clean up.
[android] res folder should not be empty.
[android] res folder should exist.
[android] library refactoring.
[android] Point is parsed from parts.
[android] Codereview fixes.
[android] Points encoding to url.
Diffstat (limited to 'api/android')
-rw-r--r-- | api/android/lib/AndroidManifest.xml | 5 | ||||
-rw-r--r-- | api/android/lib/build.xml | 92 | ||||
-rw-r--r-- | api/android/lib/proguard-project.txt | 20 | ||||
-rw-r--r-- | api/android/lib/project.properties | 15 | ||||
-rw-r--r-- | api/android/lib/src/com/mapswithme/maps/api/Const.java | 37 | ||||
-rw-r--r-- | api/android/lib/src/com/mapswithme/maps/api/MWMPoint.java | 77 | ||||
-rw-r--r-- | api/android/lib/src/com/mapswithme/maps/api/MWMResponse.java | 42 | ||||
-rw-r--r-- | api/android/lib/src/com/mapswithme/maps/api/MWMResponseHandler.java | 9 | ||||
-rw-r--r-- | api/android/lib/src/com/mapswithme/maps/api/MWMResponseReciever.java | 28 | ||||
-rw-r--r-- | api/android/lib/src/com/mapswithme/maps/api/MapsWithMeApi.java | 129 |
10 files changed, 454 insertions, 0 deletions
diff --git a/api/android/lib/AndroidManifest.xml b/api/android/lib/AndroidManifest.xml new file mode 100644 index 0000000000..ed54f28c03 --- /dev/null +++ b/api/android/lib/AndroidManifest.xml @@ -0,0 +1,5 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.mapwithme.maps.api" + android:versionCode="1" + android:versionName="1.0" > +</manifest>
\ No newline at end of file diff --git a/api/android/lib/build.xml b/api/android/lib/build.xml new file mode 100644 index 0000000000..dbb259504a --- /dev/null +++ b/api/android/lib/build.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="MwmApi" default="help"> + + <!-- The local.properties file is created and updated by the 'android' tool. + It contains the path to the SDK. It should *NOT* be checked into + Version Control Systems. --> + <property file="local.properties" /> + + <!-- The ant.properties file can be created by you. It is only edited by the + 'android' tool to add properties to it. + This is the place to change some Ant specific build properties. + Here are some properties you may want to change/update: + + source.dir + The name of the source directory. Default is 'src'. + out.dir + The name of the output directory. Default is 'bin'. + + For other overridable properties, look at the beginning of the rules + files in the SDK, at tools/ant/build.xml + + Properties related to the SDK location or the project target should + be updated using the 'android' tool with the 'update' action. + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. + + --> + <property file="ant.properties" /> + + <!-- if sdk.dir was not set from one of the property file, then + get it from the ANDROID_HOME env var. + This must be done before we load project.properties since + the proguard config can use sdk.dir --> + <property environment="env" /> + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> + <isset property="env.ANDROID_HOME" /> + </condition> + + <!-- The project.properties file is created and updated by the 'android' + tool, as well as ADT. + + This contains project specific properties such as project target, and library + dependencies. Lower level build properties are stored in ant.properties + (or in .classpath for Eclipse projects). + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. --> + <loadproperties srcFile="project.properties" /> + + <!-- quick check on sdk.dir --> + <fail + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." + unless="sdk.dir" + /> + + <!-- + Import per project custom build rules if present at the root of the project. + This is the place to put custom intermediary targets such as: + -pre-build + -pre-compile + -post-compile (This is typically used for code obfuscation. + Compiled code location: ${out.classes.absolute.dir} + If this is not done in place, override ${out.dex.input.absolute.dir}) + -post-package + -post-build + -pre-clean + --> + <import file="custom_rules.xml" optional="true" /> + + <!-- Import the actual build file. + + To customize existing targets, there are two options: + - Customize only one target: + - copy/paste the target into this file, *before* the + <import> task. + - customize it to your needs. + - Customize the whole content of build.xml + - copy/paste the content of the rules files (minus the top node) + into this file, replacing the <import> task. + - customize to your needs. + + *********************** + ****** IMPORTANT ****** + *********************** + In all cases you must update the value of version-tag below to read 'custom' instead of an integer, + in order to avoid having your file be overridden by tools such as "android update project" + --> + <!-- version-tag: 1 --> + <import file="${sdk.dir}/tools/ant/build.xml" /> + +</project> diff --git a/api/android/lib/proguard-project.txt b/api/android/lib/proguard-project.txt new file mode 100644 index 0000000000..f2fe1559a2 --- /dev/null +++ b/api/android/lib/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# 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 *; +#} diff --git a/api/android/lib/project.properties b/api/android/lib/project.properties new file mode 100644 index 0000000000..484dab0753 --- /dev/null +++ b/api/android/lib/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-17 +android.library=true diff --git a/api/android/lib/src/com/mapswithme/maps/api/Const.java b/api/android/lib/src/com/mapswithme/maps/api/Const.java new file mode 100644 index 0000000000..b9f6195fc4 --- /dev/null +++ b/api/android/lib/src/com/mapswithme/maps/api/Const.java @@ -0,0 +1,37 @@ + +package com.mapswithme.maps.api; + +public class Const +{ + /* Codes */ + // status + public static final int STATUS_OK = 0; + public static final int STATUS_CANCEL = 1; + + + /* 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_CALLMEBACK_MODE = AUTHORITY + ".callmeback_mode"; + public static final String EXTRA_CALLBACK_ACTION = AUTHORITY + ".callback"; + public static final String EXTRA_API_VERSION = AUTHORITY + ".version"; + public static final String EXTRA_CALLER_APP_INFO = AUTHORITY + ".caller_app_info"; + + + /* Response extras */ + public static final String EXTRA_MWM_RESPONSE_STATUS = AUTHORITY + ".status"; + /* Point part-by-part*/ + public static final String EXTRA_MWM_RESPONSE_HAS_POINT = AUTHORITY + ".has_point"; + public static final String EXTRA_MWM_RESPONSE_POINT_NAME = AUTHORITY + ".point_name"; + public static final String EXTRA_MWM_RESPONSE_POINT_LAT = AUTHORITY + ".point_lat"; + public static final String EXTRA_MWM_RESPONSE_POINT_LON = AUTHORITY + ".point_lon"; + public static final String EXTRA_MWM_RESPONSE_POINT_ID = AUTHORITY + ".point_id"; + + + static final int API_VERSION = 1; + static final String CALLBACK_PREFIX = "mapswithme.client."; + static final String ACTION_MWM_REQUEST = AUTHORITY + ".request"; + + private Const() {} +} diff --git a/api/android/lib/src/com/mapswithme/maps/api/MWMPoint.java b/api/android/lib/src/com/mapswithme/maps/api/MWMPoint.java new file mode 100644 index 0000000000..2715035d87 --- /dev/null +++ b/api/android/lib/src/com/mapswithme/maps/api/MWMPoint.java @@ -0,0 +1,77 @@ +package com.mapswithme.maps.api; + +import java.io.Serializable; + +// TODO add javadoc for public interface +public final class MWMPoint implements Serializable +{ + private static final long serialVersionUID = 1L; + + final private double mLat; + final private double mLon; + final private String mName; + private String mId; + + public MWMPoint(double lat, double lon, String name) + { + this(lat, lon, name, null); + } + + public MWMPoint(double lat, double lon, String name, String id) + { + this.mLat = lat; + this.mLon = lon; + this.mName = name; + this.mId = id; + } + + public double getLat() { return mLat; } + public double getLon() { return mLon; } + public String getName() { return mName; } + public String getId() { return mId; } + + public void setId(String id) { mId = id; } + + @Override + public String toString() + { + return "MWMPoint [mLat=" + mLat + ", mLon=" + mLon + ", mName=" + mName + ", mId=" + mId + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(mLat); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(mLon); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + ((mName == null) ? 0 : mName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final MWMPoint other = (MWMPoint) obj; + if (Double.doubleToLongBits(mLat) != Double.doubleToLongBits(other.mLat)) + return false; + if (Double.doubleToLongBits(mLon) != Double.doubleToLongBits(other.mLon)) + return false; + if (mName == null) + { + if (other.mName != null) + return false; + } else if (!mName.equals(other.mName)) + return false; + return true; + } +} diff --git a/api/android/lib/src/com/mapswithme/maps/api/MWMResponse.java b/api/android/lib/src/com/mapswithme/maps/api/MWMResponse.java new file mode 100644 index 0000000000..3fe8410f61 --- /dev/null +++ b/api/android/lib/src/com/mapswithme/maps/api/MWMResponse.java @@ -0,0 +1,42 @@ +package com.mapswithme.maps.api; + +import android.content.Context; +import android.content.Intent; + +// TODO add javadoc for public interface +public class MWMResponse +{ + private int mStatus; + private MWMPoint mPoint; + + public boolean isCanceled() { return Const.STATUS_CANCEL == mStatus; } + public boolean isSuccessful() { return Const.STATUS_OK == mStatus; } + + public MWMPoint getPoint() { return mPoint; } + public boolean hasPoint() { return mPoint != null; } + + @Override + public String toString() + { + return "MWMResponse [mStatus=" + mStatus + ", mSelectedPoint=" + mPoint + "]"; + } + + static MWMResponse extractFromIntent(Context context, Intent intent) + { + final MWMResponse response = new MWMResponse(); + // parse status + response.mStatus = intent.getIntExtra(Const.EXTRA_MWM_RESPONSE_STATUS, Const.STATUS_OK); + // parse point + if (intent.getBooleanExtra(Const.EXTRA_MWM_RESPONSE_HAS_POINT, false)) + { + final double lat = intent.getDoubleExtra(Const.EXTRA_MWM_RESPONSE_POINT_LAT, 0); + final double lon = intent.getDoubleExtra(Const.EXTRA_MWM_RESPONSE_POINT_LON, 0); + final String name = intent.getStringExtra(Const.EXTRA_MWM_RESPONSE_POINT_NAME); + final String id = intent.getStringExtra(Const.EXTRA_MWM_RESPONSE_POINT_ID); + response.mPoint = new MWMPoint(lat, lon, name, id); + } + return response; + } + + private MWMResponse() {} +} diff --git a/api/android/lib/src/com/mapswithme/maps/api/MWMResponseHandler.java b/api/android/lib/src/com/mapswithme/maps/api/MWMResponseHandler.java new file mode 100644 index 0000000000..e938619705 --- /dev/null +++ b/api/android/lib/src/com/mapswithme/maps/api/MWMResponseHandler.java @@ -0,0 +1,9 @@ +package com.mapswithme.maps.api; + +import android.content.Context; + +// TODO add javadoc +public interface MWMResponseHandler +{ + public void onResponse(Context context, MWMResponse response); +} diff --git a/api/android/lib/src/com/mapswithme/maps/api/MWMResponseReciever.java b/api/android/lib/src/com/mapswithme/maps/api/MWMResponseReciever.java new file mode 100644 index 0000000000..8ec37a2cdb --- /dev/null +++ b/api/android/lib/src/com/mapswithme/maps/api/MWMResponseReciever.java @@ -0,0 +1,28 @@ + +package com.mapswithme.maps.api; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + + +// TODO add javadoc with example +public final class MWMResponseReciever extends BroadcastReceiver +{ + // I believe this it not the best approach + // But we leave it to keep things simple + static MWMResponseHandler sResponseHandler; + + @Override + final public void onReceive(Context context, Intent intent) + { + if ( MapsWithMeApi.getCallbackAction(context).equals(intent.getAction()) + && sResponseHandler != null) + { + sResponseHandler.onResponse(context, MWMResponse.extractFromIntent(context, intent)); + // clean up handler to avoid context-leak + sResponseHandler = null; + } + } + +} diff --git a/api/android/lib/src/com/mapswithme/maps/api/MapsWithMeApi.java b/api/android/lib/src/com/mapswithme/maps/api/MapsWithMeApi.java new file mode 100644 index 0000000000..7f8e680718 --- /dev/null +++ b/api/android/lib/src/com/mapswithme/maps/api/MapsWithMeApi.java @@ -0,0 +1,129 @@ + +package com.mapswithme.maps.api; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.net.Uri; +import android.widget.Toast; + +import java.util.Locale; + +//TODO add javadoc for public interface +public final class MapsWithMeApi +{ + + public static void showPointsOnMap(Activity caller, MWMPoint... points) + { + showPointsOnMap(caller, null, null, points); + } + + public static void showPointOnMap(Activity caller, double lat, double lon, String name, String id) + { + showPointsOnMap(caller, (String)null, (MWMResponseHandler)null, new MWMPoint(lat, lon, name)); + } + + public static void showPointsOnMap(Activity caller, String title, MWMPoint... points) + { + showPointsOnMap(caller, title, null, points); + } + + public static void showPointsOnMap(Activity caller, String title, MWMResponseHandler responseHandler, MWMPoint... points) + { + final Intent mwmIntent = new Intent(Const.ACTION_MWM_REQUEST); + mwmIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + + mwmIntent.putExtra(Const.EXTRA_URL, createMwmUrl(caller, title, points).toString()); + mwmIntent.putExtra(Const.EXTRA_TITLE, title); + mwmIntent.putExtra(Const.EXTRA_CALLMEBACK_MODE, responseHandler != null); + + addCommonExtras(caller, mwmIntent); + + MWMResponseReciever.sResponseHandler = responseHandler; + if (responseHandler != null) + { + // detect if it is registered + // throw if not + final Intent callbackIntentStub = new Intent(getCallbackAction(caller)); + final boolean recieverEnabled = caller.getPackageManager().queryBroadcastReceivers(callbackIntentStub, 0).size() > 0; + if (!recieverEnabled) + throw new IllegalStateException(String.format( + "BroadcastReciever with intent-filter for action \"%s\" must be added to manifest.", getCallbackAction(caller))); + } + + if (isMapsWithMeInstalled(caller)) + { + // Match activity for intent + // TODO specify DEFAULT for Pro version. + final ActivityInfo aInfo = caller.getPackageManager().resolveActivity(mwmIntent, 0).activityInfo; + mwmIntent.setClassName(aInfo.packageName, aInfo.name); + caller.startActivity(mwmIntent); + } + //TODO this is temporally solution, add dialog + else + Toast.makeText(caller, "MapsWithMe is not installed.", Toast.LENGTH_LONG).show(); + } + + public static boolean isMapsWithMeInstalled(Context context) + { + final Intent intent = new Intent(Const.ACTION_MWM_REQUEST); + return context.getPackageManager().resolveActivity(intent, 0) != null; + } + + + static StringBuilder createMwmUrl(Context context, String title, MWMPoint ... points) + { + StringBuilder urlBuilder = new StringBuilder("mapswithme://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); + + // points + for (MWMPoint 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, "u", point.getId()); + } + } + + return urlBuilder; + } + + 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); + intent.putExtra(Const.EXTRA_CALLBACK_ACTION, getCallbackAction(context)); + + 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; + } +} |