diff --git a/android/app/src/main/java/app/organicmaps/MapFragment.java b/android/app/src/main/java/app/organicmaps/MapFragment.java
deleted file mode 100644
index 7bfa884d5..000000000
--- a/android/app/src/main/java/app/organicmaps/MapFragment.java
+++ /dev/null
@@ -1,210 +0,0 @@
-package app.organicmaps;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-import android.view.ViewGroup;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.content.res.ConfigurationHelper;
-import app.organicmaps.base.BaseMwmFragment;
-import app.organicmaps.sdk.Map;
-import app.organicmaps.sdk.MapRenderingListener;
-import app.organicmaps.sdk.display.DisplayType;
-import app.organicmaps.sdk.util.log.Logger;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-public class MapFragment extends BaseMwmFragment implements View.OnTouchListener, SurfaceHolder.Callback
-{
- private static final String TAG = MapFragment.class.getSimpleName();
-
- @NonNull
- private final Map mMap = new Map(DisplayType.Device);
-
- public void updateCompassOffset(int offsetX, int offsetY)
- {
- mMap.updateCompassOffset(requireContext(), offsetX, offsetY, true);
- }
-
- public void updateBottomWidgetsOffset(int offsetX, int offsetY)
- {
- mMap.updateBottomWidgetsOffset(requireContext(), offsetX, offsetY);
- }
-
- public void updateMyPositionRoutingOffset(int offsetY)
- {
- mMap.updateMyPositionRoutingOffset(offsetY);
- }
-
- public void destroySurface(boolean activityIsChangingConfigurations)
- {
- mMap.onSurfaceDestroyed(activityIsChangingConfigurations, isAdded());
- }
-
- public boolean isContextCreated()
- {
- return mMap.isContextCreated();
- }
-
- @Override
- public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder)
- {
- Logger.d(TAG);
- int densityDpi;
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
- densityDpi = ConfigurationHelper.getDensityDpi(requireContext().getResources());
- else
- densityDpi = getDensityDpiOld();
-
- mMap.onSurfaceCreated(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(), densityDpi);
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height)
- {
- Logger.d(TAG);
- mMap.onSurfaceChanged(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(),
- surfaceHolder.isCreating());
- }
-
- @Override
- public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder)
- {
- Logger.d(TAG);
- mMap.onSurfaceDestroyed(requireActivity().isChangingConfigurations(), true);
- }
-
- @Override
- public void onAttach(Context context)
- {
- Logger.d(TAG);
- super.onAttach(context);
-
- mMap.setLocationHelper(MwmApplication.from(requireContext()).getLocationHelper());
- mMap.setMapRenderingListener((MapRenderingListener) context);
- mMap.setCallbackUnsupported(this::reportUnsupported);
- }
-
- @Override
- public void onDetach()
- {
- Logger.d(TAG);
- super.onDetach();
- mMap.setMapRenderingListener(null);
- mMap.setCallbackUnsupported(null);
- }
-
- @Override
- public void onCreate(Bundle b)
- {
- Logger.d(TAG);
- super.onCreate(b);
- setRetainInstance(true);
- boolean launchByDeepLink = false;
- Bundle args = getArguments();
- if (args != null)
- launchByDeepLink = args.getBoolean(Map.ARG_LAUNCH_BY_DEEP_LINK);
- mMap.onCreate(launchByDeepLink);
- }
-
- @Override
- public void onStart()
- {
- Logger.d(TAG);
- super.onStart();
- mMap.onStart();
- }
-
- @Override
- public void onStop()
- {
- Logger.d(TAG);
- super.onStop();
- mMap.onStop();
- }
-
- @Override
- public void onPause()
- {
- Logger.d(TAG);
- super.onPause();
- mMap.onPause(requireContext());
- }
-
- @Override
- public void onResume()
- {
- Logger.d(TAG);
- super.onResume();
- mMap.onResume();
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
- {
- Logger.d(TAG);
- final View view = inflater.inflate(R.layout.fragment_map, container, false);
- final SurfaceView mSurfaceView = view.findViewById(R.id.map_surfaceview);
- mSurfaceView.getHolder().addCallback(this);
- return view;
- }
-
- @Override
- public boolean onTouch(View view, MotionEvent event)
- {
- int action = event.getActionMasked();
- int pointerIndex = event.getActionIndex();
- switch (action)
- {
- case MotionEvent.ACTION_POINTER_UP -> action = Map.NATIVE_ACTION_UP;
- case MotionEvent.ACTION_UP ->
- {
- action = Map.NATIVE_ACTION_UP;
- pointerIndex = 0;
- }
- case MotionEvent.ACTION_POINTER_DOWN -> action = Map.NATIVE_ACTION_DOWN;
- case MotionEvent.ACTION_DOWN ->
- {
- action = Map.NATIVE_ACTION_DOWN;
- pointerIndex = 0;
- }
- case MotionEvent.ACTION_MOVE ->
- {
- action = Map.NATIVE_ACTION_MOVE;
- pointerIndex = Map.INVALID_POINTER_MASK;
- }
- case MotionEvent.ACTION_CANCEL -> action = Map.NATIVE_ACTION_CANCEL;
- }
- Map.onTouch(action, event, pointerIndex);
- return true;
- }
-
- public void notifyOnSurfaceDestroyed(@NonNull Runnable task)
- {
- mMap.onSurfaceDestroyed(false, true);
- task.run();
- }
-
- private void reportUnsupported()
- {
- new MaterialAlertDialogBuilder(requireContext(), R.style.MwmTheme_AlertDialog)
- .setMessage(R.string.unsupported_phone)
- .setCancelable(false)
- .setPositiveButton(R.string.close, (dlg, which) -> requireActivity().moveTaskToBack(true))
- .show();
- }
-
- private int getDensityDpiOld()
- {
- final DisplayMetrics metrics = new DisplayMetrics();
- requireActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
- return metrics.densityDpi;
- }
-}
diff --git a/android/app/src/main/java/app/organicmaps/MwmActivity.java b/android/app/src/main/java/app/organicmaps/MwmActivity.java
index 55f603462..bed77cabd 100644
--- a/android/app/src/main/java/app/organicmaps/MwmActivity.java
+++ b/android/app/src/main/java/app/organicmaps/MwmActivity.java
@@ -84,6 +84,7 @@ import app.organicmaps.routing.RoutingPlanInplaceController;
import app.organicmaps.sdk.ChoosePositionMode;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map;
+import app.organicmaps.sdk.MapController;
import app.organicmaps.sdk.MapRenderingListener;
import app.organicmaps.sdk.PlacePageActivationListener;
import app.organicmaps.sdk.Router;
@@ -137,10 +138,10 @@ import java.util.ArrayList;
import java.util.Objects;
public class MwmActivity extends BaseMwmFragmentActivity
- implements PlacePageActivationListener, View.OnTouchListener, MapRenderingListener, RoutingController.Container,
- LocationListener, SensorListener, LocationState.ModeChangeListener,
- RoutingPlanInplaceController.RoutingPlanListener, RoutingBottomMenuListener,
- BookmarkManager.BookmarksLoadingListener, FloatingSearchToolbarController.SearchToolbarListener,
+ implements PlacePageActivationListener, MapRenderingListener, RoutingController.Container, LocationListener,
+ SensorListener, LocationState.ModeChangeListener, RoutingPlanInplaceController.RoutingPlanListener,
+ RoutingBottomMenuListener, BookmarkManager.BookmarksLoadingListener,
+ FloatingSearchToolbarController.SearchToolbarListener,
MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader,
PlacePageController.PlacePageRouteSettingsListener, MapButtonsController.MapButtonClickListener,
DisplayChangedListener
@@ -170,8 +171,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
private static final String POWER_SAVE_DISCLAIMER_SHOWN = "POWER_SAVE_DISCLAIMER_SHOWN";
- @Nullable
- private MapFragment mMapFragment;
+ @SuppressWarnings("NotNullFieldNotInitialized")
+ @NonNull
+ private MapController mMapController;
private View mPointChooser;
private MaterialToolbar mPointChooserToolbar;
@@ -459,7 +461,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
mRemoveDisplayListener = false;
startActivity(new Intent(this, MapPlaceholderActivity.class));
- Objects.requireNonNull(mMapFragment).notifyOnSurfaceDestroyed(onTaskFinishedCallback);
+ mMapController.setOnDestroyListener(onTaskFinishedCallback);
finish();
}
@@ -536,7 +538,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
updateViewsInsets();
if (getIntent().getBooleanExtra(EXTRA_UPDATE_THEME, false))
- ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
+ ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
/*
* onRenderingInitializationFinished() hook is not called when MwmActivity is recreated with the already
@@ -604,7 +606,10 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void initViews(boolean isLaunchByDeeplink)
{
- initMap(isLaunchByDeeplink);
+ mMapController = new MapController(findViewById(R.id.map), MwmApplication.from(this).getLocationHelper(), this,
+ this::reportUnsupported, isLaunchByDeeplink);
+ getLifecycle().addObserver(mMapController);
+
initNavigationButtons();
if (!mIsTabletLayout)
@@ -737,29 +742,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
finish();
}
- private void initMap(boolean isLaunchByDeepLink)
- {
- final FragmentManager manager = getSupportFragmentManager();
- mMapFragment = (MapFragment) manager.findFragmentByTag(MapFragment.class.getName());
- if (mMapFragment == null)
- {
- Bundle args = new Bundle();
- args.putBoolean(Map.ARG_LAUNCH_BY_DEEP_LINK, isLaunchByDeepLink);
- final FragmentFactory factory = manager.getFragmentFactory();
- mMapFragment = (MapFragment) factory.instantiate(getClassLoader(), MapFragment.class.getName());
- mMapFragment.setArguments(args);
- manager.beginTransaction()
- .replace(R.id.map_fragment_container, mMapFragment, MapFragment.class.getName())
- .commit();
- }
-
- View container = findViewById(R.id.map_fragment_container);
- if (container != null)
- {
- container.setOnTouchListener(this);
- }
- }
-
private void initNavigationButtons()
{
prepareNavigationButtons();
@@ -1188,7 +1170,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
setIntent(intent);
super.onNewIntent(intent);
- if (isMapRendererActive())
+ if (mMapController.isRenderingActive())
processIntent();
if (intent.getAction() != null && intent.getAction().equals(TrackRecordingService.STOP_TRACK_RECORDING))
{
@@ -1198,17 +1180,12 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
}
- private boolean isMapRendererActive()
- {
- return mMapFragment != null && Map.isEngineCreated() && mMapFragment.isContextCreated();
- }
-
@CallSuper
@Override
protected void onResume()
{
super.onResume();
- ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
+ ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
refreshSearchToolbar();
setFullscreen(isFullscreen());
makeNavigationBarTransparentInLightMode();
@@ -1226,15 +1203,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
MwmApplication.from(this).getSensorHelper().addListener(this);
}
- @Override
- public void recreate()
- {
- // Explicitly destroy surface before activity recreation.
- if (mMapFragment != null)
- mMapFragment.destroySurface(true);
- super.recreate();
- }
-
@Override
protected void onResumeFragments()
{
@@ -1436,12 +1404,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
return super.onGenericMotionEvent(event);
}
- @Override
- public boolean onTouch(View view, MotionEvent event)
- {
- return mMapFragment != null && mMapFragment.onTouch(view, event);
- }
-
public void customOnNavigateUp()
{
if (removeCurrentFragment(true))
@@ -1457,10 +1419,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
void updateCompassOffset(int offsetY, int offsetX)
{
- if (mMapFragment == null || !mMapFragment.isAdded())
- return;
-
- mMapFragment.updateCompassOffset(offsetX, offsetY);
+ mMapController.updateCompassOffset(offsetX, offsetY);
final double north = MwmApplication.from(this).getSensorHelper().getSavedNorth();
if (!Double.isNaN(north))
@@ -1479,9 +1438,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void updateBottomWidgetsOffset(int offsetX)
{
- if (mMapFragment == null || !mMapFragment.isAdded())
- return;
-
int offsetY = mNavBarHeight;
final Float bottomButtonHeight = mMapButtonsViewModel.getBottomButtonsHeight().getValue();
if (bottomButtonHeight != null)
@@ -1496,8 +1452,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (mDisplayManager.isDeviceDisplayUsed())
{
- mMapFragment.updateBottomWidgetsOffset(offsetX, offsetY);
- mMapFragment.updateMyPositionRoutingOffset(offsetY);
+ mMapController.updateBottomWidgetsOffset(offsetX, offsetY);
+ mMapController.updateMyPositionRoutingOffset(offsetY);
}
}
@@ -1715,7 +1671,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onNavigationCancelled()
{
closeFloatingToolbarsAndPanels(true);
- ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
+ ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
if (mRoutingPlanInplaceController == null)
return;
@@ -1731,7 +1687,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onNavigationStarted()
{
closeFloatingToolbarsAndPanels(true);
- ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
+ ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.navigation);
refreshLightStatusBar();
@@ -1767,7 +1723,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onResetToPlanningState()
{
closeFloatingToolbarsAndPanels(true);
- ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
+ ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
NavigationService.stopService(this);
mMapButtonsViewModel.setSearchOption(null);
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.planning);
@@ -2596,4 +2552,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
window.setNavigationBarContrastEnforced(false);
}
}
+
+ private void reportUnsupported()
+ {
+ new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
+ .setMessage(R.string.unsupported_phone)
+ .setCancelable(false)
+ .setPositiveButton(R.string.close, (dlg, which) -> this.moveTaskToBack(true))
+ .show();
+ }
}
diff --git a/android/app/src/main/java/app/organicmaps/car/SurfaceRenderer.java b/android/app/src/main/java/app/organicmaps/car/SurfaceRenderer.java
index 810dff898..da4d36806 100644
--- a/android/app/src/main/java/app/organicmaps/car/SurfaceRenderer.java
+++ b/android/app/src/main/java/app/organicmaps/car/SurfaceRenderer.java
@@ -8,19 +8,16 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.car.app.AppManager;
import androidx.car.app.CarContext;
-import androidx.car.app.CarToast;
import androidx.car.app.SurfaceCallback;
import androidx.car.app.SurfaceContainer;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.MwmApplication;
-import app.organicmaps.R;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.MapRenderingListener;
import app.organicmaps.sdk.settings.UnitLocale;
-import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger;
public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallback, MapRenderingListener
@@ -96,7 +93,7 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
mSurface.release();
mSurface = null;
}
- mMap.onSurfaceDestroyed(false, true);
+ mMap.onSurfaceDestroyed(false);
}
@Override
@@ -112,7 +109,6 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
{
Logger.d(TAG);
mMap.onStart();
- mMap.setCallbackUnsupported(this::reportUnsupported);
}
@Override
@@ -121,14 +117,14 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
Logger.d(TAG);
mMap.onResume();
if (MwmApplication.from(mCarContext).getDisplayManager().isCarDisplayUsed())
- UiThread.runLater(() -> mMap.updateMyPositionRoutingOffset(0));
+ mMap.updateMyPositionRoutingOffset(0);
}
@Override
public void onPause(@NonNull LifecycleOwner owner)
{
Logger.d(TAG);
- mMap.onPause(mCarContext);
+ mMap.onPause();
}
@Override
@@ -199,7 +195,8 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
}
mCarContext.getCarService(AppManager.class).setSurfaceCallback(null);
- mMap.onSurfaceDestroyed(false, true);
+ mMap.onPause();
+ mMap.onSurfaceDestroyed(false);
mMap.onStop();
mMap.setCallbackUnsupported(null);
mMap.setMapRenderingListener(null);
@@ -217,9 +214,8 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
mCarContext.getCarService(AppManager.class).setSurfaceCallback(this);
mMap.onStart();
- mMap.setCallbackUnsupported(this::reportUnsupported);
mMap.setMapRenderingListener(this);
- UiThread.runLater(() -> mMap.updateMyPositionRoutingOffset(0));
+ mMap.updateMyPositionRoutingOffset(0);
mIsRunning = true;
}
@@ -229,13 +225,6 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
return mIsRunning;
}
- private void reportUnsupported()
- {
- String message = mCarContext.getString(R.string.unsupported_phone);
- Logger.e(TAG, message);
- CarToast.makeText(mCarContext, message, CarToast.LENGTH_LONG).show();
- }
-
@Override
public void onRenderingCreated()
{
diff --git a/android/app/src/main/res/layout/activity_map.xml b/android/app/src/main/res/layout/activity_map.xml
index abe4998ff..e03f573cb 100644
--- a/android/app/src/main/res/layout/activity_map.xml
+++ b/android/app/src/main/res/layout/activity_map.xml
@@ -9,8 +9,8 @@
android:id="@+id/map_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
-
-
\ No newline at end of file
diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/Map.java b/android/sdk/src/main/java/app/organicmaps/sdk/Map.java
index a60c3976e..d9bf89f1d 100644
--- a/android/sdk/src/main/java/app/organicmaps/sdk/Map.java
+++ b/android/sdk/src/main/java/app/organicmaps/sdk/Map.java
@@ -21,7 +21,6 @@ public final class Map
void report();
}
- public static final String ARG_LAUNCH_BY_DEEP_LINK = "launch_by_deep_link";
private static final String TAG = Map.class.getSimpleName();
// Should correspond to android::MultiTouchAction from Framework.cpp
@@ -220,11 +219,10 @@ public final class Map
mMapRenderingListener.onRenderingRestored();
}
- public void onSurfaceDestroyed(boolean activityIsChangingConfigurations, boolean isAdded)
+ public void onSurfaceDestroyed(boolean activityIsChangingConfigurations)
{
- Logger.d(TAG, "mSurfaceCreated = " + mSurfaceCreated + ", mSurfaceAttached = " + mSurfaceAttached
- + ", isAdded = " + isAdded);
- if (!mSurfaceCreated || !mSurfaceAttached || !isAdded)
+ Logger.d(TAG, "mSurfaceCreated = " + mSurfaceCreated + ", mSurfaceAttached = " + mSurfaceAttached);
+ if (!mSurfaceCreated || !mSurfaceAttached)
return;
nativeDetachSurface(!activityIsChangingConfigurations);
@@ -261,7 +259,7 @@ public final class Map
nativeSetRenderingInitializationFinishedListener(null);
}
- public void onPause(final Context context)
+ public void onPause()
{
mUiThemeOnPause = Config.UiTheme.getCurrent();
diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/MapController.java b/android/sdk/src/main/java/app/organicmaps/sdk/MapController.java
new file mode 100644
index 000000000..d38673314
--- /dev/null
+++ b/android/sdk/src/main/java/app/organicmaps/sdk/MapController.java
@@ -0,0 +1,102 @@
+package app.organicmaps.sdk;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import app.organicmaps.sdk.location.LocationHelper;
+import app.organicmaps.sdk.util.log.Logger;
+
+public class MapController implements DefaultLifecycleObserver
+{
+ private static final String TAG = MapController.class.getSimpleName();
+
+ private final MapView mMapView;
+ private final Map mMap;
+
+ @Nullable
+ private Runnable mOnSurfaceDestroyedListener = null;
+
+ public MapController(@NonNull MapView mapView, @NonNull LocationHelper locationHelper,
+ @NonNull MapRenderingListener mapRenderingListener,
+ @NonNull Map.CallbackUnsupported callbackUnsupported, boolean launchByDeepLink)
+ {
+ mMapView = mapView;
+ mMap = mMapView.getMap();
+ mMap.onCreate(launchByDeepLink);
+ mMap.setLocationHelper(locationHelper);
+ mMap.setMapRenderingListener(mapRenderingListener);
+ mMap.setCallbackUnsupported(callbackUnsupported);
+ }
+
+ public MapView getView()
+ {
+ return mMapView;
+ }
+
+ public boolean isRenderingActive()
+ {
+ return Map.isEngineCreated() && mMap.isContextCreated();
+ }
+
+ public void updateCompassOffset(int offsetX, int offsetY)
+ {
+ mMap.updateCompassOffset(mMapView.getContext(), offsetX, offsetY, true);
+ }
+
+ public void updateBottomWidgetsOffset(int offsetX, int offsetY)
+ {
+ mMap.updateBottomWidgetsOffset(mMapView.getContext(), offsetX, offsetY);
+ }
+
+ public void updateMyPositionRoutingOffset(int offsetY)
+ {
+ mMap.updateMyPositionRoutingOffset(offsetY);
+ }
+
+ public void setOnDestroyListener(@NonNull Runnable task)
+ {
+ mOnSurfaceDestroyedListener = task;
+ }
+
+ @Override
+ public void onStart(@NonNull LifecycleOwner owner)
+ {
+ Logger.d(TAG);
+ mMap.onStart();
+ }
+
+ @Override
+ public void onResume(@NonNull LifecycleOwner owner)
+ {
+ Logger.d(TAG);
+ mMap.onResume();
+ }
+
+ @Override
+ public void onPause(@NonNull LifecycleOwner owner)
+ {
+ Logger.d(TAG);
+ mMap.onPause();
+ }
+
+ @Override
+ public void onStop(@NonNull LifecycleOwner owner)
+ {
+ Logger.d(TAG);
+ mMap.onStop();
+ }
+
+ @Override
+ public void onDestroy(@NonNull LifecycleOwner owner)
+ {
+ Logger.d(TAG);
+ mMap.setMapRenderingListener(null);
+ mMap.setCallbackUnsupported(null);
+ if (mOnSurfaceDestroyedListener != null)
+ {
+ mOnSurfaceDestroyedListener.run();
+ mOnSurfaceDestroyedListener = null;
+ }
+ }
+}
diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/MapView.java b/android/sdk/src/main/java/app/organicmaps/sdk/MapView.java
new file mode 100644
index 000000000..7f89c299a
--- /dev/null
+++ b/android/sdk/src/main/java/app/organicmaps/sdk/MapView.java
@@ -0,0 +1,177 @@
+package app.organicmaps.sdk;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import androidx.annotation.NonNull;
+import androidx.core.content.res.ConfigurationHelper;
+import app.organicmaps.sdk.display.DisplayType;
+import app.organicmaps.sdk.util.Utils;
+import app.organicmaps.sdk.util.log.Logger;
+
+public class MapView extends SurfaceView
+{
+ private static final String TAG = MapView.class.getSimpleName();
+
+ private class SurfaceHolderCallback implements SurfaceHolder.Callback
+ {
+ @Override
+ public void surfaceCreated(@NonNull SurfaceHolder holder)
+ {
+ Logger.d(TAG);
+ mMap.onSurfaceCreated(MapView.this.getContext(), holder.getSurface(), holder.getSurfaceFrame(),
+ ConfigurationHelper.getDensityDpi(MapView.this.getResources()));
+ }
+
+ @Override
+ public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height)
+ {
+ Logger.d(TAG);
+ mMap.onSurfaceChanged(MapView.this.getContext(), holder.getSurface(), holder.getSurfaceFrame(),
+ holder.isCreating());
+ }
+
+ @Override
+ public void surfaceDestroyed(@NonNull SurfaceHolder holder)
+ {
+ Logger.d(TAG);
+ mMap.onSurfaceDestroyed(isHostActivityChangingConfigurations());
+ }
+ }
+
+ @NonNull
+ private final Map mMap;
+
+ public MapView(Context context)
+ {
+ this(context, null);
+ }
+
+ public MapView(Context context, AttributeSet attrs)
+ {
+ this(context, attrs, 0);
+ }
+
+ public MapView(Context context, AttributeSet attrs, int defStyleAttr)
+ {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public MapView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
+ {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mMap = new Map(DisplayType.Device);
+ super.getHolder().addCallback(new SurfaceHolderCallback());
+ }
+
+ public final void onDraw(@NonNull Canvas canvas)
+ {
+ super.onDraw(canvas);
+ if (isInEditMode())
+ drawMapPreview(canvas);
+ }
+
+ @Override
+ public boolean onTouchEvent(@NonNull MotionEvent event)
+ {
+ int action = event.getActionMasked();
+ int pointerIndex = event.getActionIndex();
+ switch (action)
+ {
+ case MotionEvent.ACTION_POINTER_UP -> action = Map.NATIVE_ACTION_UP;
+ case MotionEvent.ACTION_UP ->
+ {
+ action = Map.NATIVE_ACTION_UP;
+ pointerIndex = 0;
+ }
+ case MotionEvent.ACTION_POINTER_DOWN -> action = Map.NATIVE_ACTION_DOWN;
+ case MotionEvent.ACTION_DOWN ->
+ {
+ action = Map.NATIVE_ACTION_DOWN;
+ pointerIndex = 0;
+ }
+ case MotionEvent.ACTION_MOVE ->
+ {
+ action = Map.NATIVE_ACTION_MOVE;
+ pointerIndex = Map.INVALID_POINTER_MASK;
+ }
+ case MotionEvent.ACTION_CANCEL -> action = Map.NATIVE_ACTION_CANCEL;
+ }
+ Map.onTouch(action, event, pointerIndex);
+ performClick();
+ return true;
+ }
+
+ @Override
+ public boolean performClick()
+ {
+ super.performClick();
+ return false;
+ }
+
+ @Override
+ public final SurfaceHolder getHolder()
+ {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @NonNull
+ Map getMap()
+ {
+ return mMap;
+ }
+
+ /// The function is called only in the design mode of Android Studio.
+ private void drawMapPreview(@NonNull Canvas canvas)
+ {
+ final int w = getWidth();
+ final int h = getHeight();
+
+ // Background
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setStyle(Paint.Style.FILL);
+ if (Utils.isDarkMode(getContext()))
+ paint.setColor(Color.rgb(30, 30, 30));
+ else
+ paint.setColor(Color.rgb(245, 242, 230));
+ canvas.drawRect(0, 0, w, h, paint);
+
+ // Grid lines (lat/lon)
+ paint.setColor(Color.LTGRAY);
+ paint.setStrokeWidth(2f);
+ final int step = Math.min(w, h) / 6;
+ for (int i = 0; i < Math.max(w, h); i += step)
+ {
+ if (i < w)
+ canvas.drawLine(i, 0, i, h, paint);
+ if (i < h)
+ canvas.drawLine(0, i, w, i, paint);
+ }
+ }
+
+ private boolean isHostActivityChangingConfigurations()
+ {
+ Activity activity = findActivity(getContext());
+ return activity != null && activity.isChangingConfigurations();
+ }
+
+ private static Activity findActivity(Context context)
+ {
+ while (context instanceof ContextWrapper)
+ {
+ if (context instanceof Activity)
+ {
+ return (Activity) context;
+ }
+ context = ((ContextWrapper) context).getBaseContext();
+ }
+ return null;
+ }
+}
diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/util/Utils.java b/android/sdk/src/main/java/app/organicmaps/sdk/util/Utils.java
index 2f5cfdbad..eefef19f7 100644
--- a/android/sdk/src/main/java/app/organicmaps/sdk/util/Utils.java
+++ b/android/sdk/src/main/java/app/organicmaps/sdk/util/Utils.java
@@ -6,6 +6,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.text.TextUtils;
@@ -346,4 +347,10 @@ public class Utils
{
return context.getResources().getDimensionPixelSize(id);
}
+
+ public static boolean isDarkMode(@NonNull Context context)
+ {
+ return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ }
}