Android: ¿elige automáticamente la clave de API de depuración / liberación?

OBSOLETADO: esta vieja pregunta se refiere a la API obsoleta de Google Maps v1. Al usar la API v2, puede usar múltiples huellas dactilares de certificados en una entrada de la Consola API de Google . La clave API ya no se almacena en Manifiesto ni en el código.


¿Es posible detectar automáticamente qué certificado se utilizó para firmar APK? Me gustaría tener certificados de depuración y liberación de Mapas en la aplicación y pasar uno válido al constructor de MapView.

Con tal configuración no cometeré ningún error mientras lanzo la aplicación: estoy usando un certificado de depuración en el emulador y mi dispositivo, luego firmo con la versión uno antes de enviar la aplicación a Market.

Estaba pensando en detectar mi dispositivo en particular o si el depurador está conectado, pero no es perfecto. Tal vez alguna necesidad de marcado de archivos para el certificado de depuración? ¿Hay alguna forma mejor?

Hay una nueva forma de determinar si es una comstackción de depuración o versión uno en SDK Tools, Revisión 17 . Un extracto de la nueva descripción de las características:

Las comstackciones ahora generan una clase llamada BuildConfig que contiene una constante DEBUG que se establece automáticamente de acuerdo con su tipo de comstackción. Puede verificar la constante ( BuildConfig.DEBUG ) en su código para ejecutar funciones de solo depuración.

Así que ahora puedes simplemente escribir algo como esto:

if (BuildConfig.DEBUG) { //Your debug code goes here } else { //Your release code goes here } 

ACTUALIZACIÓN: He encontrado un error en ADT: a veces BuildConfig.DEBUG es true después de exportar el paquete de la aplicación. La descripción está aquí: http://code.google.com/p/android/issues/detail?id=27940

Tuvo la misma molestia con la clave API. Aquí hay una solución completa, basada en el enlace de arriba y ejemplo de Bijarni (que de alguna manera no funcionó para mí), uso ahora este método:

 // Define the debug signature hash (Android default debug cert). Code from sigs[i].hashCode() protected final static int DEBUG_SIGNATURE_HASH = ; // Checks if this apk was built using the debug certificate // Used eg for Google Maps API key determination (from: http://whereblogger.klaki.net/2009/10/choosing-android-maps-api-key-at-run.html) public static Boolean isDebugBuild(Context context) { if (_isDebugBuild == null) { try { _isDebugBuild = false; Signature [] sigs = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures; for (int i = 0; i < sigs.length; i++) { if (sigs[i].hashCode() == DEBUG_SIGNATURE_HASH) { Log.d(TAG, "This is a debug build!"); _isDebugBuild = true; break; } } } catch (NameNotFoundException e) { e.printStackTrace(); } } return _isDebugBuild; } 

Debe encontrar el hashValue () de su firma de depuración una vez, simplemente generar sigs [i] .hashCode ().

Entonces, no quería agregar dinámicamente MapView, sino usar el archivo xml. No puede establecer el atributo de clave api en el código y usar un diseño xml, por lo que utilizo este método simple (aunque copiar el diseño xml no es tan hermoso):

En mi MapActivity:

  public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Select the proper xml layout file which includes the matching Google API Key if (isDebugBuild(this)) { setContentView(R.layout.map_activity_debug); } else { setContentView(R.layout.map_activity_release); } 

Una manera mucho más fácil de determinar si se trata de una comstackción de depuración es verificar el indicador de depuración en la información de la aplicación que el hash de la firma.

 public boolean isDebugBuild() throws Exception { PackageManager pm = _context.getPackageManager(); PackageInfo pi = pm.getPackageInfo(_context.getPackageName(), 0); return ((pi.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0); } 

Una vez que se encuentra la comstackción de depuración, puede usar un recurso diferente para mostrar el mapa o crear la vista de mapa dentro de la aplicación y agregarla a un diseño.

  if(isDebugBuild()) { _mapView = new MapView(this, getString(R.string.debugmapskey)); } else { _mapView = new MapView(this, getString(R.string.releasemapskey)); } 

He trabajado en torno a la espantosa integración errónea de las claves api en el proceso de comstackción y el control de la fuente al convertirla en una propiedad almacenada en local.properties . Tuve que agregar lo siguiente a build.xml :

   You need to add mapsApiKey=... to local.properties         

Ahora, por supuesto, tuve que crear mapview.xml.tpl en mi raíz de proyectos (no puede ir a res/layout porque romperá el proceso de comstackción):

 < ?xml version="1.0" encoding="utf-8"?>  

Durante la precomstackción, la plantilla se copia en el lugar correcto y @apiKey @ se reemplaza por la clave real. Lamentablemente, no he encontrado una manera de distinguir entre comstackciones de depuración y lanzamiento en esta fase, así que para comstackr para el lanzamiento, simplemente agrego la clave api de lanzamiento a los parámetros de ant:

 ant -DmapsApiKey=.... release 

Este enfoque se integra bien con SCM (no es necesario que verifique las claves) y de manera aceptable con el proceso de comstackción.

Si todavía estás interesado, acabo de escribir en mi blog sobre otra forma de hacer esto. Con un simple cambio en la secuencia de comandos de comstackción de Android, puede cambiar la clave de Map API, así como todos los demás cambios de versión necesarios. Lo que me gusta de esto es que no hay nada relacionado con la depuración en el lanzamiento, y puede mantener los diseños XML tal como estaban antes.

http://blog.cuttleworks.com/2011/02/android-dev-prod-builds/

Creo que crear una entrada en la consola de la API de Google que incluya tanto su clave de liberación como su clave de depuración (ambas asignadas al mismo paquete) funciona muy bien y es una forma mucho más simple de no tener que preocuparse de si está depurando o comstackndo versión de lanzamiento. La solución se resume aquí

Todas las respuestas aquí parecen obsoletas, si estás usando android studio, entonces gradle es el camino a seguir

Utiliza diferentes claves en tu build.gradle

 android { .. .. ... buildTypes { debug { resValue "string", "google_maps_api_key", "[YOUR DEV KEY]" } release { resValue "string", "google_maps_api_key", "[YOUR PROD KEY]" } } } 

Y en su AndroidManifest.xml

  

fuente

Y si quiere guardar algunas contraseñas para depuración y liberación de forma diferente, entonces debe seguir este

Terminé con el archivo especial en la tarjeta SD; si está presente, use la clave de depuración; faltante: use la versión uno. Y funciona.

EDITAR: ver nueva respuesta aceptada, funciona mejor

No sé si esto ayuda a alguien pero he combinado algunas de las otras sugerencias aquí para producir la siguiente MapViewActivity.

En este ejemplo R.layout.map_dbg solo se usa si se trata de una comstackción de depuración y el archivo existe (agregue este archivo a su .gitignore).

Las ventajas de este enfoque son:

  1. no necesitas escribir un objective ant (bueno si usas eclipse)
  2. la clave de liberación correcta siempre está en map.xml (con suerte una clave de depuración no se registrará por error)
  3. la clave de liberación siempre se usa para una versión de lanzamiento
  4. se pueden usar múltiples claves de depuración

Las desventajas de este enfoque son:

  1. debe recordar actualizar map_dbg.xml cada vez que se actualice map.xml

     public class MapViewActivity extends MapActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // // copy the map.xml to map_dbg.xml and update the api key. // int id = getLayoutId("map_dbg"); if(id ==0) id = R.layout.map; setContentView(id); } int getLayoutId(String name) { return isDebugBuild() ? getResources().getIdentifier(name, "layout", getPackageName()) : 0; } public boolean isDebugBuild() { boolean dbg = false; try { PackageManager pm = getPackageManager(); PackageInfo pi = pm.getPackageInfo(getPackageName(), 0); dbg = ((pi.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0); } catch (Exception e) { } return dbg; } } 

Configuré un objective ant sencillo que reemplaza el apikey con una clave de depuración o una clave de liberación. Esto es realmente simple y mantiene el código libre de lógica no deseada.

       template-file: ${template-file}   

En Map V2 Es fácil enviar claves separadas con la herramienta Android Studio Gradle. He implementado una manera fácil para eso. por favor revisa el enlace aquí .