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();} }); 
  • Google Maps open-source-attribution es increíblemente grande y bloquea el hilo principal
  • Cómo hacer Google hacer en el centro cuando se utiliza doble Pulsar y pellizcar para acercar el androide?
  • Android studio v0.3.2, gradle, google maps v2.0 No encontró la clase "com.google.android.gms.maps.MapFragment
  • Restringir resultados de autocompletar por setBoundsBias
  • Como llegar "Bus Service No" usando google api
  • Código postal / código postal de android lugar objeto
  • MapView onCreate lanza NullPointerException en dispositivos LG
  • cómo borrar todas las superposiciones de mapa o marcadores de google map en android?
  • Error al inflar fragmento de clase para SupportMapFragment
  • Área de clic del marcador de mapa de Google
  • Agregar objeto 3D para asignar y desplazar alrededor de él
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.