Uso de Google MapView v2 en Live Wallpaper

He estado tratando de resolver esto por un tiempo ahora. Me gustaría usar un MapView v2 con mi fondo de pantalla en vivo, hasta ahora mis resultados son una pantalla en negro con un logotipo de google en la parte inferior.

Resultados

Mi manifiesto tiene permisos necesarios:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> 

Y metadatos:

  <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="@string/google_maps_key" /> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> 

Y también intenté cambiar la aceleración de hardware como se sugiere en algunas otras preguntas relacionadas con MapView:

 android:hardwareAccelerated="false" 

También puedo confirmar que la clave Api de mapas es correcta, ya que tengo un MapFragment que hace correctamente (no en el servicio wallaper sino en una actividad de prueba):

MapFragment

WallpaperService.Engine código:

 private class ENGINE extends Engine implements OnMapReadyCallback, GoogleMap.SnapshotReadyCallback { private final String LOG_TAG = ENGINE.class.getSimpleName(); private int width = 0; private int height = 0; private SurfaceHolder holder; private boolean visible; private Bitmap bitmap; private final Handler handler = new Handler(); private final Runnable drawRunner = new Runnable() { @Override public void run() { draw(); } }; MapView mapView; GoogleMap map; private static final int FPS = 5000; @Override public void onCreate(SurfaceHolder surfaceHolder) { super.onCreate(surfaceHolder); this.holder = surfaceHolder; this.width = getDesiredMinimumWidth(); this.height = getDesiredMinimumHeight(); int margin = 100; Rect rect = new Rect(); rect.set(margin, margin, width, height); mapView = new MapView(getApplicationContext()); mapView.onCreate(new Bundle()); // could this be the problem? // since onCreate(null) has exact same result int widthSpec = View.MeasureSpec.makeMeasureSpec(rect.width(), View.MeasureSpec.EXACTLY); int heightSpec = View.MeasureSpec.makeMeasureSpec(rect.height(), View.MeasureSpec.EXACTLY); mapView.measure(widthSpec, heightSpec); mapView.layout(0, 0, rect.width(), rect.height()); Log.d(LOG_TAG, "Width: " + mapView.getMeasuredWidth()); Log.d(LOG_TAG, "Height: " + mapView.getMeasuredHeight()); mapView.onResume(); try { MapsInitializer.initialize(getApplicationContext()); } catch (Exception e) { e.printStackTrace(); } mapView.getMapAsync(this); } public ENGINE() { } @Override public void onVisibilityChanged(boolean visible) { this.visible = visible; if (visible) { handler.post(drawRunner); mapView.onResume(); } else { handler.removeCallbacks(drawRunner); mapView.onPause(); } } @Override public void onDestroy() { super.onDestroy(); mapView.onDestroy(); handler.removeCallbacks(drawRunner); } private void draw() { final Canvas canvas = holder.lockCanvas(); try { if (canvas != null) { if (mapView != null) { mapView.draw(canvas); Log.d(LOG_TAG, "Drawing Map view on the canvas"); } else { Paint paint = new Paint(); paint.setColor(getColor(R.color.colorAccent)); paint.setStyle(Paint.Style.FILL); canvas.drawPaint(paint); } } } finally { if (canvas != null) holder.unlockCanvasAndPost(canvas); } handler.removeCallbacks(drawRunner); if (visible) { handler.postDelayed(drawRunner, FPS); } } @Override public void onSnapshotReady(Bitmap bitmap) { // never reaches here this.bitmap = bitmap; Log.d(LOG_TAG, "Bitmap ready"); } @Override public void onMapReady(GoogleMap googleMap) { this.map = googleMap; //this.map.setMyLocationEnabled(true); this.map.getUiSettings().setZoomControlsEnabled(true); this.map.getUiSettings().setMyLocationButtonEnabled(true); this.map.getUiSettings().setCompassEnabled(true); this.map.getUiSettings().setRotateGesturesEnabled(false); this.map.getUiSettings().setZoomGesturesEnabled(false); Log.d(LOG_TAG, "Map is ready"); double latitude = 56.875300; double longitude = -76.783658; LatLng marker = new LatLng(latitude, longitude); this.map.addMarker(new MarkerOptions().position(marker).title("Marker Title")); this.map.snapshot(this); // I tried using map's snapshot to render it, however this callback never returns a value } } 

Logcat no muestra ningún error ni sugerencias sobre cuál podría ser el problema

 07-14 10:26:39.213 3167-3167/removed.for.privacy I/Google Maps Android API: Google Play services package version: 11055440 07-14 10:26:39.398 3167-3195/removed.for.privacy D/OpenGLRenderer: endAllActiveAnimators on 0x75f689e800 (RippleDrawable) with handle 0x75f65bede0 07-14 10:27:02.772 3167-3167/removed.for.privacy I/Google Maps Android API: Google Play services package version: 11055440 07-14 10:27:02.838 3167-3167/removed.for.privacy D/ENGINE : Width: 980 07-14 10:27:02.838 3167-3167/removed.for.privacy D/ENGINE : Height: 1820 07-14 10:27:02.867 3167-3167/removed.for.privacy D/ENGINE : Map is ready 07-14 10:27:02.885 3167-3195/removed.for.privacy D/OpenGLRenderer: endAllActiveAnimators on 0x75f689ec00 (RippleDrawable) with handle 0x75e6820020 07-14 10:27:02.900 3167-3167/removed.for.privacy D/ENGINE : Drawing Map view on the canvas 07-14 10:27:07.955 3167-3167/removed.for.privacy D/ENGINE : Drawing Map view on the canvas 

Entiendo que WallpaperService no está diseñado para ser utilizado con elementos de interfaz de usuario normales, sin embargo, es posible utilizarlos y lo hice con éxito con TextViews y tal. ¿Es una limitación puesta en el MapView a propósito y estoy golpeando a un caballo muerto? Gracias

De todos modos, puede utilizar Google Static Maps API para obtener la imagen de papel tapiz (por ejemplo, como en esta solicitud: https://maps.googleapis.com/maps/api/staticmap?center=0,0&zoom=1&scale=1&size=300×500&maptype=roadmap&format = Png & visual_refresh = true ), entonces, sólo muéstrelo en el fondo de pantalla (y recargar y actualizar la pantalla por temporizador o acción, si es necesario).

Si está intentando tomar una imagen de su mapa, puede utilizar el siguiente método. Al definir la variable "path" puede guardar la imagen y reutilizarla en otro lugar. Alternativa: puede guardar el mapa de bits internamente y reutilizarlo también.

 public void savePhoto(){ mMap.snapshot(new GoogleMap.SnapshotReadyCallback() { @Override public void onSnapshotReady(Bitmap bitmap) { FileOutputStream out = null; try { out = new FileOutputStream(new File(path), true); bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); } catch (Exception e) {e.printStackTrace();} finally { try {if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();} saveForm(isArea, datum, path); } } }); } 

Es muy importante llamar a este método del método OnMapLoadedCallback como:

 mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { @Override public void onMapLoaded() {savePhoto();} }); 
  • ¿Puedo obtener el código fuente de la aplicación Google Maps de Android?
  • Android: abre la intención del mapa con direcciones con dos puntos
  • Obtener límites de mapa con Android Google Maps
  • GetMap () devuelve null en Android con Google Maps API v2
  • Android Google Map InfoWindow punto de anclaje después de la rotación del marcador
  • DeslizamientoDirector sobre GoogleMap
  • Google maps api para la página de registro de android
  • Android obtener y analizar Google Directions
  • Android animateCamera GoogleMap.CancelableCallback Uso
  • Android Google Maps no se muestra en firmado apk V2
  • ¿Por qué Android LocationManager tiene un gran retraso antes de que las actualizaciones de ubicación se inicien si la precisión del ajuste
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.