From 6ca799033527e552b069ced02e173a01fdaf0df1 Mon Sep 17 00:00:00 2001 From: "alex.so.3" Date: Mon, 28 Sep 2026 01:39:25 +0200 Subject: [PATCH] Fall back to OpenStreetMap when the build has no Google Maps key The map screen threw at start without MAPS_API_KEY; OSM needs no key, so it now stands in for Google in both the map and the history screen. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016xeHfDLMuUeusX9PEgNEmY --- .../opentagviewer/HistoryViewActivity.java | 2 +- .../android/opentagviewer/MapsActivity.java | 11 +++++++--- .../ui/maps/MapProviderFactory.java | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/dev/wander/android/opentagviewer/HistoryViewActivity.java b/app/src/main/java/dev/wander/android/opentagviewer/HistoryViewActivity.java index f078b0d4..26e998ef 100644 --- a/app/src/main/java/dev/wander/android/opentagviewer/HistoryViewActivity.java +++ b/app/src/main/java/dev/wander/android/opentagviewer/HistoryViewActivity.java @@ -216,7 +216,7 @@ protected void onCreate(Bundle savedInstanceState) { // Obtain the SupportMapFragment and get notified when the map is ready to be used. // 根据用户设置创建地图提供商 String mapProviderType = this.userSettings.getMapProvider(); - this.mapProvider = MapProviderFactory.create(mapProviderType); + this.mapProvider = MapProviderFactory.create(MapProviderFactory.effectiveProvider(this, mapProviderType)); // 初始化地图 this.mapProvider.initialize(this, R.id.history_map, this); diff --git a/app/src/main/java/dev/wander/android/opentagviewer/MapsActivity.java b/app/src/main/java/dev/wander/android/opentagviewer/MapsActivity.java index 0d740daf..6b68d09a 100644 --- a/app/src/main/java/dev/wander/android/opentagviewer/MapsActivity.java +++ b/app/src/main/java/dev/wander/android/opentagviewer/MapsActivity.java @@ -560,6 +560,9 @@ protected void onCreate(Bundle savedInstanceState) { // 根据用户设置创建地图提供商 String mapProviderType = this.userSettings.getMapProvider(); + // A build without a Google Maps key (secrets.properties) still has a map: OpenStreetMap + // needs no key, so it stands in for Google rather than the app refusing to start. + mapProviderType = MapProviderFactory.effectiveProvider(this, mapProviderType); // **Before the new provider touches it.** Changing provider calls recreate(), and the // FragmentManager restores Google's map fragment into this container while a plain view @@ -1751,7 +1754,8 @@ public void onClickMoreForDevice(View view) { deviceInfoActivityLauncher.launch(deviceInfoIntent); } - private void checkApiKey() { + /** Whether this build carries a Google Maps key; without one the map falls back to OSM. */ + private boolean checkApiKey() { try { ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA); Bundle bundle = Objects.requireNonNull(appInfo.metaData); @@ -1759,9 +1763,10 @@ private void checkApiKey() { String apiKey = bundle.getString("com.google.android.geo.API_KEY"); if (apiKey == null || apiKey.isBlank() || apiKey.equals("DEFAULT_API_KEY")) { - Toast.makeText(this, "API Key was not set in secrets.properties", LENGTH_SHORT).show(); - throw new RuntimeException("API Key was not set in secrets.properties"); + Log.w(TAG, "No Google Maps API key in secrets.properties; using OpenStreetMap"); + return false; } + return true; } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Package name not found.", e); throw new RuntimeException("Error getting package info", e); diff --git a/app/src/main/java/dev/wander/android/opentagviewer/ui/maps/MapProviderFactory.java b/app/src/main/java/dev/wander/android/opentagviewer/ui/maps/MapProviderFactory.java index 5710357c..3f3a0227 100644 --- a/app/src/main/java/dev/wander/android/opentagviewer/ui/maps/MapProviderFactory.java +++ b/app/src/main/java/dev/wander/android/opentagviewer/ui/maps/MapProviderFactory.java @@ -47,6 +47,28 @@ public static void reset() { replacement = null; } + /** + * The provider to actually use: Google Maps needs the key from secrets.properties, and a + * build without one gets OpenStreetMap (which needs none) instead of a map that cannot load. + */ + public static String effectiveProvider(final android.content.Context context, final String providerType) { + if (providerType != null && !PROVIDER_GOOGLE.equals(providerType)) { + return providerType; + } + try { + final android.os.Bundle meta = context.getPackageManager().getApplicationInfo( + context.getPackageName(), android.content.pm.PackageManager.GET_META_DATA).metaData; + final String key = meta == null ? null : meta.getString("com.google.android.geo.API_KEY"); + if (key == null || key.isBlank() || key.equals("DEFAULT_API_KEY")) { + return PROVIDER_OSM; + } + } catch (final Exception e) { + Log.w(TAG, "Could not read the Maps API key; using OpenStreetMap", e); + return PROVIDER_OSM; + } + return providerType; + } + public static IMapProvider create(String providerType) { if (replacement != null) { Log.d(TAG, "Creating a substituted map provider");