diff --git a/android/src/com/mapswithme/maps/DownloadResourcesLegacyActivity.java b/android/src/com/mapswithme/maps/DownloadResourcesLegacyActivity.java index a53a9b9d33..e111a3f7fd 100644 --- a/android/src/com/mapswithme/maps/DownloadResourcesLegacyActivity.java +++ b/android/src/com/mapswithme/maps/DownloadResourcesLegacyActivity.java @@ -46,6 +46,8 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity imp private static final String ERROR_LOADING_DIALOG_TAG = "error_loading_dialog"; private static final int ERROR_LOADING_DIALOG_REQ_CODE = 234; + private static final int REQ_CODE_API_RESULT = 10; + public static final String EXTRA_COUNTRY = "country"; // Error codes, should match the same codes in JNI @@ -394,13 +396,28 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity imp intent.putExtra(MwmActivity.EXTRA_TASK, mMapTaskToForward); intent.putExtra(MwmActivity.EXTRA_LAUNCH_BY_DEEP_LINK, true); mMapTaskToForward = null; + + // Wait for the result from MwmActivity for API callers + startActivityForResult(intent, REQ_CODE_API_RESULT); + return; } startActivity(intent); - finish(); } + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + switch (requestCode) + { + case REQ_CODE_API_RESULT: + setResult(resultCode, data); + finish(); + default: + super.onActivityResult(requestCode, resultCode, data); + } + } + private void finishFilesDownload(int result) { if (result == ERR_NO_MORE_FILES) diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index b86ee05e23..378f7d2a7b 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -78,7 +78,6 @@ import com.mapswithme.maps.search.SearchFragment; import com.mapswithme.maps.settings.DrivingOptionsActivity; import com.mapswithme.maps.settings.RoadType; import com.mapswithme.maps.settings.SettingsActivity; -import com.mapswithme.maps.settings.StoragePathManager; import com.mapswithme.maps.settings.UnitLocale; import com.mapswithme.maps.sound.TtsPlayer; import com.mapswithme.maps.widget.menu.MainMenu; @@ -158,6 +157,13 @@ public class MwmActivity extends BaseMwmFragmentActivity @SuppressWarnings("NullableProblems") @NonNull private View mPositionChooser; + enum PositionChooserMode { + NONE, + EDITOR, + API + }; + @NonNull + private PositionChooserMode mPositionChooserMode = PositionChooserMode.NONE; private RoutingPlanInplaceController mRoutingPlanInplaceController; @@ -499,15 +505,34 @@ public class MwmActivity extends BaseMwmFragmentActivity final Toolbar toolbar = mPositionChooser.findViewById(R.id.toolbar_position_chooser); UiUtils.extendViewWithStatusBar(toolbar); UiUtils.showHomeUpButton(toolbar); - toolbar.setNavigationOnClickListener(v -> closePositionChooser()); + toolbar.setNavigationOnClickListener(v -> { + closePositionChooser(); + if (mPositionChooserMode == PositionChooserMode.API) + finish(); + }); mPositionChooser.findViewById(R.id.done).setOnClickListener( v -> { + switch (mPositionChooserMode) + { + case API: + Intent apiResult = new Intent(); + double[] center = Framework.nativeGetScreenRectCenter(); + apiResult.putExtra("lat", center[0]); + apiResult.putExtra("lon", center[1]); + setResult(Activity.RESULT_OK, apiResult); + finish(); + break; + case EDITOR: + if (Framework.nativeIsDownloadedMapAtScreenCenter()) + startActivity(new Intent(MwmActivity.this, FeatureCategoryActivity.class)); + else + DialogUtils.showAlertDialog(MwmActivity.this, R.string.message_invalid_feature_position); + break; + case NONE: + throw new IllegalStateException("Unexpected mPositionChooserMode"); + } closePositionChooser(); - if (Framework.nativeIsDownloadedMapAtScreenCenter()) - startActivity(new Intent(MwmActivity.this, FeatureCategoryActivity.class)); - else - DialogUtils.showAlertDialog(MwmActivity.this, R.string.message_invalid_feature_position); }); UiUtils.hide(mPositionChooser); } @@ -536,8 +561,19 @@ public class MwmActivity extends BaseMwmFragmentActivity mSearchController.show(); } - public void showPositionChooser(boolean isBusiness, boolean applyPosition) + public void showPositionChooserForAPI() { + showPositionChooser(PositionChooserMode.API, false, false); + } + + public void showPositionChooserForEditor(boolean isBusiness, boolean applyPosition) + { + showPositionChooser(PositionChooserMode.EDITOR, isBusiness, applyPosition); + } + + private void showPositionChooser(PositionChooserMode mode, boolean isBusiness, boolean applyPosition) + { + mPositionChooserMode = mode; closeFloatingToolbarsAndPanels(false); UiUtils.show(mPositionChooser); setFullscreen(true); @@ -549,6 +585,9 @@ public class MwmActivity extends BaseMwmFragmentActivity UiUtils.hide(mPositionChooser); Framework.nativeTurnOffChoosePositionMode(); setFullscreen(false); + if (mPositionChooserMode == PositionChooserMode.API) + finish(); + mPositionChooserMode = PositionChooserMode.NONE; } private void initMap(boolean isLaunchByDeepLink) @@ -2022,7 +2061,7 @@ public class MwmActivity extends BaseMwmFragmentActivity public void onAddPlaceOptionSelected() { closeFloatingPanels(); - showPositionChooser(false, false); + showPositionChooserForEditor(false, false); } public void onDownloadMapsOptionSelected() diff --git a/android/src/com/mapswithme/maps/SplashActivity.java b/android/src/com/mapswithme/maps/SplashActivity.java index fc091b66dc..de21eed4cc 100644 --- a/android/src/com/mapswithme/maps/SplashActivity.java +++ b/android/src/com/mapswithme/maps/SplashActivity.java @@ -10,7 +10,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; import com.mapswithme.maps.base.BaseActivity; import com.mapswithme.maps.base.BaseActivityDelegate; @@ -24,11 +23,13 @@ import com.mapswithme.util.concurrency.UiThread; import java.io.IOException; -public class SplashActivity extends AppCompatActivity implements BaseActivity +public class SplashActivity extends Activity implements BaseActivity { private static final String EXTRA_ACTIVITY_TO_START = "extra_activity_to_start"; public static final String EXTRA_INITIAL_INTENT = "extra_initial_intent"; private static final int REQUEST_PERMISSIONS = 1; + private static final int REQ_CODE_API_RESULT = 10; + private static final long DELAY = 100; private boolean mCanceled = false; @@ -190,12 +191,31 @@ public class SplashActivity extends AppCompatActivity implements BaseActivity input.getParcelableExtra(EXTRA_INITIAL_INTENT) : input; result.putExtra(EXTRA_INITIAL_INTENT, initialIntent); + if (!initialIntent.hasCategory(Intent.CATEGORY_LAUNCHER)) + { + // Wait for the result from MwmActivity for API callers + startActivityForResult(result, REQ_CODE_API_RESULT); + return; + } } Counters.setFirstStartDialogSeen(this); startActivity(result); finish(); } + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + switch (requestCode) + { + case REQ_CODE_API_RESULT: + // Propagate the result to API callers + setResult(resultCode, data); + finish(); + default: + super.onActivityResult(requestCode, resultCode, data); + } + } + @Override @NonNull public Activity get() diff --git a/android/src/com/mapswithme/maps/api/ParsingResult.java b/android/src/com/mapswithme/maps/api/ParsingResult.java index 6f44493be9..12b8329614 100644 --- a/android/src/com/mapswithme/maps/api/ParsingResult.java +++ b/android/src/com/mapswithme/maps/api/ParsingResult.java @@ -8,8 +8,7 @@ import java.lang.annotation.RetentionPolicy; public class ParsingResult { @Retention(RetentionPolicy.SOURCE) - @IntDef({ TYPE_INCORRECT, TYPE_MAP, TYPE_ROUTE, TYPE_SEARCH, TYPE_LEAD, TYPE_CATALOGUE, - TYPE_CATALOGUE_PATH, TYPE_SUBSCRIPTION}) + @IntDef({ TYPE_INCORRECT, TYPE_MAP, TYPE_ROUTE, TYPE_SEARCH, TYPE_LOCATION}) public @interface UrlType {} // Represents url_scheme::ParsedMapApi::UrlType from c++ part. @@ -17,10 +16,11 @@ public class ParsingResult public static final int TYPE_MAP = 1; public static final int TYPE_ROUTE = 2; public static final int TYPE_SEARCH = 3; - public static final int TYPE_LEAD = 4; - public static final int TYPE_CATALOGUE = 5; - public static final int TYPE_CATALOGUE_PATH = 6; - public static final int TYPE_SUBSCRIPTION = 7; + //public static final int TYPE_LEAD = 4; + //public static final int TYPE_CATALOGUE = 5; + //public static final int TYPE_CATALOGUE_PATH = 6; + //public static final int TYPE_SUBSCRIPTION = 7; + public static final int TYPE_LOCATION = 8; private final int mUrlType; private final boolean mSuccess; diff --git a/android/src/com/mapswithme/maps/intent/Factory.java b/android/src/com/mapswithme/maps/intent/Factory.java index 5f35a0af37..e403f19f89 100644 --- a/android/src/com/mapswithme/maps/intent/Factory.java +++ b/android/src/com/mapswithme/maps/intent/Factory.java @@ -2,11 +2,9 @@ package com.mapswithme.maps.intent; import android.content.ContentResolver; import android.content.Intent; -import android.location.Location; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -31,15 +29,10 @@ import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.maps.routing.RoutingController; import com.mapswithme.maps.search.SearchActivity; import com.mapswithme.maps.search.SearchEngine; -import com.mapswithme.util.CrashlyticsUtils; import com.mapswithme.util.KeyValue; import com.mapswithme.util.StorageUtils; -import com.mapswithme.util.StringUtils; -import com.mapswithme.util.UTM; import com.mapswithme.util.Utils; import com.mapswithme.util.concurrency.ThreadPool; -import com.mapswithme.util.log.Logger; -import com.mapswithme.util.log.LoggerFactory; import java.io.File; import java.util.List; @@ -326,9 +319,6 @@ public class Factory switch (result.getUrlType()) { case ParsingResult.TYPE_INCORRECT: - case ParsingResult.TYPE_CATALOGUE: - case ParsingResult.TYPE_CATALOGUE_PATH: - case ParsingResult.TYPE_SUBSCRIPTION: return false; case ParsingResult.TYPE_MAP: @@ -358,8 +348,9 @@ public class Factory } SearchActivity.start(target, request.mQuery, request.mLocale, request.mIsSearchOnMap); return true; - case ParsingResult.TYPE_LEAD: - return true; + case ParsingResult.TYPE_LOCATION: + target.showPositionChooserForAPI(); + return true; } return false; diff --git a/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java b/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java index a4573f4058..0fd7742e22 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java +++ b/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java @@ -1272,12 +1272,12 @@ public class PlacePageView extends NestedScrollViewClickFixed private void addOrganisation() { - getActivity().showPositionChooser(true, false); + getActivity().showPositionChooserForEditor(true, false); } private void addPlace() { - getActivity().showPositionChooser(false, true); + getActivity().showPositionChooserForEditor(false, true); } @Override diff --git a/api/example/android/.gitignore b/api/example/android/.gitignore new file mode 100644 index 0000000000..aa724b7707 --- /dev/null +++ b/api/example/android/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/api/example/android/app/.gitignore b/api/example/android/app/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/api/example/android/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/api/example/android/app/build.gradle b/api/example/android/app/build.gradle new file mode 100644 index 0000000000..0c20ceba96 --- /dev/null +++ b/api/example/android/app/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdk 31 + + defaultConfig { + applicationId "app.organicmaps.api.example" + minSdk 21 + targetSdk 31 + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding true + } +} + +dependencies { + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' +} \ No newline at end of file diff --git a/api/example/android/app/proguard-rules.pro b/api/example/android/app/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/api/example/android/app/proguard-rules.pro @@ -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 \ No newline at end of file diff --git a/api/example/android/app/src/main/AndroidManifest.xml b/api/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..41bf1aea45 --- /dev/null +++ b/api/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/api/example/android/app/src/main/ic_launcher-playstore.png b/api/example/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000..bbee5a53e7 Binary files /dev/null and b/api/example/android/app/src/main/ic_launcher-playstore.png differ diff --git a/api/example/android/app/src/main/java/app/organicmaps/api/example/MainActivity.java b/api/example/android/app/src/main/java/app/organicmaps/api/example/MainActivity.java new file mode 100644 index 0000000000..a4f851e917 --- /dev/null +++ b/api/example/android/app/src/main/java/app/organicmaps/api/example/MainActivity.java @@ -0,0 +1,59 @@ +package app.organicmaps.api.example; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.widget.Toast; + +import app.organicmaps.api.example.databinding.ActivityMainBinding; + +import java.util.Locale; + +public class MainActivity extends Activity +{ + private ActivityMainBinding binding; + + private static final int REQ_CODE_LOCATION = 1; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + binding.locationTest.setOnClickListener(view -> { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("om://location")); + startActivityForResult(intent, REQ_CODE_LOCATION); + }); + } + + protected void onActivityResult(int requestCode, + int resultCode, + Intent data) + { + switch (requestCode) + { + case REQ_CODE_LOCATION: + if (resultCode == RESULT_CANCELED) + { + Toast.makeText(this, "Cancelled", Toast.LENGTH_SHORT).show(); + return; + } + else if (resultCode != RESULT_OK) + { + throw new AssertionError("Unsupported resultCode: " + resultCode); + } + + double lat = data.getDoubleExtra("lat", 0.0); + double lon = data.getDoubleExtra("lon", 0.0); + String message = String.format(Locale.ENGLISH, "Result: lat=%.4f lon=%.4f", lat, lon); + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + break; + default: + super.onActivityResult(requestCode, resultCode, data); + } + } +} \ No newline at end of file diff --git a/api/example/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/api/example/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000000..d98c1df227 --- /dev/null +++ b/api/example/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/api/example/android/app/src/main/res/layout/activity_main.xml b/api/example/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000000..e5cace6681 --- /dev/null +++ b/api/example/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,29 @@ + + + +