Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package org.microg.gms.maps.mapbox

import android.content.Context
import android.location.Location
import android.os.Bundle
import android.os.Parcel
import android.util.Log
import android.view.View
import android.widget.FrameLayout
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.dynamic.ObjectWrapper
import com.google.android.gms.maps.internal.*
import com.google.android.gms.maps.model.*
import com.google.android.gms.maps.model.internal.*
import org.microg.gms.maps.mapbox.model.AbstractMarker

class DummyMarkerImpl(private val id: String, options: MarkerOptions) : IMarkerDelegate.Stub() {
private var position = options.position
override fun remove() {}
override fun getId(): String = id
override fun setPosition(pos: LatLng?) { position = pos ?: position }
override fun getPosition(): LatLng = position
override fun setTitle(title: String?) {}
override fun getTitle(): String? = null
override fun setSnippet(snippet: String?) {}
override fun getSnippet(): String? = null
override fun setDraggable(drag: Boolean) {}
override fun isDraggable(): Boolean = false
override fun showInfoWindow() {}
override fun hideInfoWindow() {}
override fun isInfoWindowShown(): Boolean = false
override fun setVisible(visible: Boolean) {}
override fun isVisible(): Boolean = true
override fun equalsRemote(other: IMarkerDelegate?): Boolean = other?.id == id
override fun hashCodeRemote(): Int = id.hashCode()
override fun setIcon(obj: IObjectWrapper?) {}
override fun setAnchor(x: Float, y: Float) {}
override fun setFlat(flat: Boolean) {}
override fun isFlat(): Boolean = false
override fun setRotation(rotation: Float) {}
override fun getRotation(): Float = 0f
override fun setInfoWindowAnchor(x: Float, y: Float) {}
override fun setAlpha(alpha: Float) {}
override fun getAlpha(): Float = 1f
override fun setZIndex(zIndex: Float) {}
override fun getZIndex(): Float = 0f
override fun setTag(obj: IObjectWrapper?) {}
override fun getTag(): IObjectWrapper = ObjectWrapper.wrap(null)
}

class DummyGoogleMapImpl(context: Context) : AbstractGoogleMap(context) {
val view: View = FrameLayout(mapContext)
private var markerId = 0

override fun getCameraPosition(): CameraPosition = CameraPosition(LatLng(0.0, 0.0), 0f, 0f, 0f)
override fun getMaxZoomLevel(): Float = 20f
override fun getMinZoomLevel(): Float = 0f
override fun moveCamera(cameraUpdate: IObjectWrapper?) {}
override fun animateCamera(cameraUpdate: IObjectWrapper?) {}
override fun animateCameraWithCallback(cameraUpdate: IObjectWrapper?, callback: ICancelableCallback?) { callback?.onFinish() }
override fun animateCameraWithDurationAndCallback(cameraUpdate: IObjectWrapper?, duration: Int, callback: ICancelableCallback?) { callback?.onFinish() }
override fun stopAnimation() {}
override fun setMapStyle(options: MapStyleOptions?): Boolean = true
override fun setMinZoomPreference(minZoom: Float) {}
override fun setMaxZoomPreference(maxZoom: Float) {}
override fun resetMinMaxZoomPreference() {}
override fun setLatLngBoundsForCameraTarget(bounds: LatLngBounds?) {}
override fun addPolyline(options: PolylineOptions): IPolylineDelegate? = null
override fun addPolygon(options: PolygonOptions): IPolygonDelegate? = null
override fun addMarker(options: MarkerOptions): IMarkerDelegate = DummyMarkerImpl("m${markerId++}", options)
override fun addGroundOverlay(options: GroundOverlayOptions): IGroundOverlayDelegate? = null
override fun addTileOverlay(options: TileOverlayOptions): ITileOverlayDelegate? = null
override fun addCircle(options: CircleOptions): ICircleDelegate? = null
override fun clear() {}
override fun getMapType(): Int = 0
override fun setMapType(type: Int) {}
override fun setWatermarkEnabled(watermark: Boolean) {}
override fun isMyLocationEnabled(): Boolean = false
override fun setMyLocationEnabled(myLocation: Boolean) {}
override fun setLocationSource(locationSource: ILocationSourceDelegate?) {}
override fun getMyLocation(): Location? = null
override fun onLocationUpdate(location: Location) {}
override fun setContentDescription(desc: String?) {}
override fun getUiSettings(): IUiSettingsDelegate = UiSettingsCache()
override fun getProjection(): IProjectionDelegate = DummyProjection()
override fun setOnCameraChangeListener(listener: IOnCameraChangeListener?) {}
override fun setOnMarkerDragListener(listener: IOnMarkerDragListener?) {}
override fun snapshot(callback: ISnapshotReadyCallback, bitmap: IObjectWrapper?) { callback.onBitmapWrappedReady(ObjectWrapper.wrap(null)) }
override fun snapshotForTest(callback: ISnapshotReadyCallback?) {}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {}
override fun setOnMapLoadedCallback(callback: IOnMapLoadedCallback?) { callback?.onMapLoaded() }
override fun setCameraMoveStartedListener(listener: IOnCameraMoveStartedListener?) {}
override fun setCameraMoveListener(listener: IOnCameraMoveListener?) {}
override fun setCameraMoveCanceledListener(listener: IOnCameraMoveCanceledListener?) {}
override fun setCameraIdleListener(listener: IOnCameraIdleListener?) {}
override fun onCreate(savedInstanceState: Bundle?) {}
override fun onResume() {}
override fun onPause() {}
override fun onDestroy() {}
override fun onStart() {}
override fun onStop() {}
override fun onLowMemory() {}
override fun onSaveInstanceState(outState: Bundle) {}
override fun showInfoWindow(marker: AbstractMarker): Boolean = false
fun getMapAsync(callback: IOnMapReadyCallback) { callback.onMapReady(this) }
override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean =
if (super.onTransact(code, data, reply, flags)) true else { Log.d("GmsMapDummy", "onTransact [unknown]: $code, $data, $flags"); false }
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ class GoogleMapImpl(context: Context, var options: GoogleMapOptions) : AbstractG
BitmapDescriptorFactoryImpl.initialize(mapContext.resources, context.resources)
LibraryLoader.setLibraryLoader(MultiArchLoader(mapContext, context))
runOnMainLooper {
Mapbox.getInstance(mapContext, BuildConfig.MAPBOX_KEY, WellKnownTileServer.Mapbox)
if (hasAnyMapKey()) {
Mapbox.getInstance(mapContext, BuildConfig.MAPBOX_KEY, WellKnownTileServer.Mapbox)
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ class LiteGoogleMapImpl(context: Context, var options: GoogleMapOptions) : Abstr
override fun onCreate(savedInstanceState: Bundle?) {
if (!created) {

Mapbox.getInstance(mapContext, BuildConfig.MAPBOX_KEY, WellKnownTileServer.Mapbox)
if (hasAnyMapKey()) {
Mapbox.getInstance(mapContext, BuildConfig.MAPBOX_KEY, WellKnownTileServer.Mapbox)
}

if (savedInstanceState?.containsKey(BUNDLE_CAMERA_POSITION) == true) {
cameraPosition = savedInstanceState.getParcelable(BUNDLE_CAMERA_POSITION)!!
Expand All @@ -230,6 +232,10 @@ class LiteGoogleMapImpl(context: Context, var options: GoogleMapOptions) : Abstr

@UiThread
private fun updateSnapshot() {
if (!hasAnyMapKey()) {
Log.d(TAG, "Skipping snapshot update as no API keys are provided")
return
}

val cameraPosition = cameraPosition
val dpi = dpiFactor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
if (options == null) {
options = GoogleMapOptions()
}
if (options?.liteMode == true) {
if (!hasAnyMapKey()) {
map = DummyGoogleMapImpl(activity)
} else if (options?.liteMode == true) {
map = LiteGoogleMapImpl(activity, options ?: GoogleMapOptions())
} else {
map = GoogleMapImpl(activity, options ?: GoogleMapOptions())
Expand All @@ -66,7 +68,9 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
}
Log.d(TAG, "onCreateView: ${options?.camera?.target}")
if (map == null) {
map = if (options?.liteMode == true) {
map = if (!hasAnyMapKey()) {
DummyGoogleMapImpl(activity)
} else if (options?.liteMode == true) {
LiteGoogleMapImpl(activity, options ?: GoogleMapOptions())
} else {
GoogleMapImpl(activity, options ?: GoogleMapOptions())
Expand All @@ -78,6 +82,7 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
val view = when (this) {
is GoogleMapImpl -> this.view
is LiteGoogleMapImpl -> this.view
is DummyGoogleMapImpl -> this.view
else -> null
}

Expand All @@ -99,6 +104,7 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
override fun getMapAsync(callback: IOnMapReadyCallback) = map?.let {
if (it is GoogleMapImpl) it.getMapAsync(callback)
else if (it is LiteGoogleMapImpl) it.getMapAsync(callback)
else if (it is DummyGoogleMapImpl) it.getMapAsync(callback)
} ?: Unit

override fun onDestroyView() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ class MapViewImpl(private val context: Context, options: GoogleMapOptions?) : IM

override fun onCreate(savedInstanceState: Bundle?) {
Log.d(TAG, "onCreate: ${options?.camera?.target}")
map = if (options.liteMode) {
map = if (!hasAnyMapKey()) {
DummyGoogleMapImpl(context)
} else if (options.liteMode) {
LiteGoogleMapImpl(context, options)
} else {
GoogleMapImpl(context, options)
Expand Down Expand Up @@ -62,6 +64,7 @@ class MapViewImpl(private val context: Context, options: GoogleMapOptions?) : IM
when (it) {
is GoogleMapImpl -> it.view
is LiteGoogleMapImpl -> it.view
is DummyGoogleMapImpl -> it.view
else -> null
}
}
Expand All @@ -71,6 +74,7 @@ class MapViewImpl(private val context: Context, options: GoogleMapOptions?) : IM
when (it) {
is GoogleMapImpl -> it.getMapAsync(callback)
is LiteGoogleMapImpl -> it.getMapAsync(callback)
is DummyGoogleMapImpl -> it.getMapAsync(callback)
else -> null
}
} ?: Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,23 @@ const val KEY_LAYER_PAINT = "paint"
const val KEY_SOURCE_URL = "url"
const val KEY_SOURCE_TILES = "tiles"

fun hasAnyMapKey(): Boolean {
val mapboxKey = BuildConfig.MAPBOX_KEY
val stadiaKey = BuildConfig.STADIA_KEY
return !(mapboxKey.isNullOrEmpty() || mapboxKey == "null" || mapboxKey == "YOUR_KEY_HERE") ||
!(stadiaKey.isNullOrEmpty() || stadiaKey == "null" || stadiaKey == "YOUR_KEY_HERE")
}

fun getStyle(
context: MapContext, mapType: Int, styleOptions: MapStyleOptions?, styleFromFileWorkaround: Boolean = false
): Style.Builder {
if (!hasAnyMapKey()) {
return Style.Builder().fromJson("{\"version\": 8, \"sources\": {}, \"layers\": []}")
}

val styleJson = JSONObject(
context.assets.open(
if (BuildConfig.STADIA_KEY.isNotEmpty()) when (mapType) {
if (BuildConfig.STADIA_KEY.isNotEmpty() && BuildConfig.STADIA_KEY != "null" && BuildConfig.STADIA_KEY != "YOUR_KEY_HERE") when (mapType) {
GoogleMap.MAP_TYPE_SATELLITE, GoogleMap.MAP_TYPE_HYBRID -> "style-microg-satellite-stadia.json"
GoogleMap.MAP_TYPE_TERRAIN -> "style-stadia-outdoors.json"
//MAP_TYPE_NONE, MAP_TYPE_NORMAL,
Expand All @@ -60,7 +69,7 @@ fun getStyle(
)

// Inject API key
if (BuildConfig.STADIA_KEY.isNotEmpty()) {
if (BuildConfig.STADIA_KEY.isNotEmpty() && BuildConfig.STADIA_KEY != "null" && BuildConfig.STADIA_KEY != "YOUR_KEY_HERE") {
val sourceArray = styleJson.getJSONObject(KEY_SOURCES)
for (key in sourceArray.keys()) {
val sourceObject = sourceArray.getJSONObject(key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,76 +21,78 @@
import android.content.res.Resources;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Keep;
import android.util.Log;

import com.google.android.gms.dynamic.IObjectWrapper;
import com.google.android.gms.dynamic.ObjectWrapper;
import com.google.android.gms.maps.GoogleMapOptions;
import com.google.android.gms.maps.StreetViewPanoramaOptions;
import com.google.android.gms.maps.model.internal.IBitmapDescriptorFactoryDelegate;

import org.microg.gms.maps.vtm.MapFragmentImpl;
import org.microg.gms.maps.vtm.MapViewImpl;
import org.microg.gms.maps.vtm.ResourcesContainer;
import org.microg.gms.maps.vtm.StreetViewPanoramaFragmentImpl;
import org.microg.gms.maps.vtm.StreetViewPanoramaViewImpl;
import org.microg.gms.maps.vtm.bitmap.BitmapDescriptorFactoryImpl;
import org.microg.gms.maps.vtm.camera.CameraUpdateFactoryImpl;
import org.microg.gms.maps.mapbox.CameraUpdateFactoryImpl;
import org.microg.gms.maps.mapbox.MapFragmentImpl;
import org.microg.gms.maps.mapbox.MapViewImpl;
import org.microg.gms.maps.mapbox.StylesKt;
import org.microg.gms.maps.mapbox.StreetViewPanoramaFragmentImpl;
import org.microg.gms.maps.mapbox.StreetViewPanoramaViewImpl;
import org.microg.gms.maps.mapbox.model.BitmapDescriptorFactoryImpl;

@Keep
public class CreatorImpl extends ICreator.Stub {
private static final String TAG = "GmsMapCreator";

@Override
public void init(IObjectWrapper resources) throws RemoteException {
public void init(IObjectWrapper resources) {
initV2(resources, 0);
}

@Override
public IMapFragmentDelegate newMapFragmentDelegate(IObjectWrapper activity) throws RemoteException {
return new MapFragmentImpl((Activity) ObjectWrapper.unwrap(activity));
public IMapFragmentDelegate newMapFragmentDelegate(IObjectWrapper activity) {
return new MapFragmentImpl(ObjectWrapper.unwrapTyped(activity, Activity.class));
}

@Override
public IMapViewDelegate newMapViewDelegate(IObjectWrapper context, GoogleMapOptions options) throws RemoteException {
return new MapViewImpl((Context) ObjectWrapper.unwrap(context), options);
public IMapViewDelegate newMapViewDelegate(IObjectWrapper context, GoogleMapOptions options) {
return new MapViewImpl(ObjectWrapper.unwrapTyped(context, Context.class), options);
}

@Override
public ICameraUpdateFactoryDelegate newCameraUpdateFactoryDelegate() throws RemoteException {
return CameraUpdateFactoryImpl.get();
public ICameraUpdateFactoryDelegate newCameraUpdateFactoryDelegate() {
return new CameraUpdateFactoryImpl();
}

@Override
public IBitmapDescriptorFactoryDelegate newBitmapDescriptorFactoryDelegate() throws RemoteException {
return new BitmapDescriptorFactoryImpl();
public IBitmapDescriptorFactoryDelegate newBitmapDescriptorFactoryDelegate() {
return BitmapDescriptorFactoryImpl.INSTANCE;
}

@Override
public void initV2(IObjectWrapper resources, int flags) throws RemoteException {
ResourcesContainer.set((Resources) ObjectWrapper.unwrap(resources));
public void initV2(IObjectWrapper resources, int flags) {
BitmapDescriptorFactoryImpl.INSTANCE.initialize(ObjectWrapper.unwrapTyped(resources, Resources.class), null);
//ResourcesContainer.set((Resources) ObjectWrapper.unwrap(resources));
Log.d(TAG, "initV2 " + flags);
}

@Override
public IStreetViewPanoramaViewDelegate newStreetViewPanoramaViewDelegate(IObjectWrapper context, StreetViewPanoramaOptions options) {
return new StreetViewPanoramaViewImpl((Activity) ObjectWrapper.unwrap(context));
return new StreetViewPanoramaViewImpl(ObjectWrapper.unwrapTyped(context, Context.class));
}

@Override
public IStreetViewPanoramaFragmentDelegate newStreetViewPanoramaFragmentDelegate(IObjectWrapper activity) {
return new StreetViewPanoramaFragmentImpl((Activity) ObjectWrapper.unwrap(activity));
return new StreetViewPanoramaFragmentImpl(ObjectWrapper.unwrapTyped(activity, Activity.class));
}

@Override
public int getRendererType() throws RemoteException {
return 1;
if (!StylesKt.hasAnyMapKey()) return 0;
return 2;
}

@Override
public void logInitialization(IObjectWrapper context, int preferredRenderer) throws RemoteException {
Log.d(TAG, "VTM-based Map initialized (preferred renderer was " + preferredRenderer + ")");
Log.d(TAG, "Mapbox-based Map initialized (preferred renderer was " + preferredRenderer + ")");
}

@Override
Expand Down