[android] Get rid of MapFragment

Signed-off-by: Andrei Shkrob <github@shkrob.dev>
This commit is contained in:
Andrei Shkrob
2025-09-12 09:46:30 +02:00
committed by x7z4w
parent 30f624a070
commit 9912d19302
9 changed files with 329 additions and 308 deletions

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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()
{

View File

@@ -9,8 +9,8 @@
android:id="@+id/map_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/map_fragment_container"
<app.organicmaps.sdk.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.view.SurfaceView
android:id="@+id/map_surfaceview"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"/>