Android:自动selectdebugging/发布Maps api key?

OBSOLETED:这个老问题是指过时的Google Maps v1 API。 使用v2 API时,您可以在一个Google API Console条目中使用多个证书指纹。 API密钥不再存储在清单或代码中。


是否可以自动检测哪个证书用于签名APK? 我想同时在应用程序中debugging和发布地图证书,并将有效的证书传递给MapView构造函数。

有了这样的设置,我不会在发布应用程序时犯错 – 我在模拟器和我的设备上使用debugging证书,然后在发送应用程序到市场之前签署发行版。

我正在考虑检测我的特定设备或debugging器是否连接,但这并不完美。 也许一些文件标记需要debugging证书? 有没有更好的办法?

有一种新的方法可以确定它是SDK Tools,Revision 17中的debugging版本还是发布版本 。 摘自新function概述:

Builds现在生成一个名为BuildConfig的类,其中包含一个根据您的构buildtypes自动设置的DEBUG常量。 您可以检查代码中的( BuildConfig.DEBUG )常量以运行仅debuggingfunction。

所以现在你可以简单地写下这样的东西:

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

更新:我遇到了ADT中的错误:导出应用程序包后,有时BuildConfig.DEBUGtrue 。 这里介绍: http : //code.google.com/p/android/issues/detail?id=27940

对API密钥有同样的麻烦。 这里有一个完整的解决scheme,基于上面的链接和Bijarni的例子 (它不知道怎么工作),我现在使用这个方法:

 // Define the debug signature hash (Android default debug cert). Code from sigs[i].hashCode() protected final static int DEBUG_SIGNATURE_HASH = <your hash value>; // 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; } 

你必须找出你的debugging签名的hashValue()一次,只需输出sigs [i] .hashCode()。

然后,我不想dynamic添加MapView,而是使用xml文件。 你不能在代码中设置api键属性,并使用xml布局,所以我使用这个简单的方法(尽pipe复制xml布局并不那么美丽):

在我的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); } 

通过检查应用程序信息上的debugging标志而不是签名哈希,可以更容易地确定它是否为debugging版本。

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

一旦finddebugging版本,您可以使用不同的资源来显示地图,或者在应用程序内创build地图视图并添加到布局。

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

我已经通过将其存储在local.properties一个属性,将api密钥的可怕失误整合到构build过程和源代码控制中。 我不得不将以下内容添加到build.xml

 <property name="mapviewxml" value="res/layout/mapview.xml" /> <target name="-pre-build"> <fail unless="mapsApiKey">You need to add mapsApiKey=... to local.properties</fail> <copy file="mapview.xml.tpl" tofile="${mapviewxml}" overwrite="true"> <filterchain> <replacetokens> <token key="apiKey" value="${mapsApiKey}"/> </replacetokens> </filterchain> </copy> </target> 

现在,我必须在我的项目根目录下创buildmapview.xml.tpl (它不能去res/layout因为它会破坏构build过程):

 <?xml version="1.0" encoding="utf-8"?> <com.google.android.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="@apiKey@" /> 

在预编译过程中,模板被复制到正确的位置,@ apiKey @被真正的密钥replace。 不幸的是,在这个阶段,我还没有find区分debugging和发布版本的方法,所以要编译发布版本,我只是将发行版apiKey添加到ant参数中:

 ant -DmapsApiKey=.... release 

这种方法与SCM很好地集成(我不需要检查密钥)并且可以接受构build过程。

如果你仍然感兴趣,我只是在博客上讨论另一种方法。 通过对Android构build脚本的简单更改,您可以切换Map API键以及所有其他所需的发布更改。 我喜欢的是没有任何与debugging有关的内容进入到发行版中,您可以保持XML布局与以前一样。

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

我认为在Google API的控制台中创build一个包含释放键和debugging键(两个都映射到同一个包)的控制台的条目非常好,而且更简单一些,不必担心是否正在debugging或编译发行版本。 这里概述了解决scheme

这里的所有答案都显得过时了,如果你使用的是android studio,那么gradle就是要走的路

在你的build.gradle中使用不同的键

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

并在你的AndroidManifest.xml中

 <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="@string/google_maps_api_key"/> 

资源

如果你想保存一些密码来进行debugging和释放,那么你应该遵循这个

我已经结束与SD卡上的特殊文件 – 如果存在,使用debugging密钥; 丢失 – 使用释放一个。 它工作。

编辑:看到新的接受的答案,它效果更好

我不知道这是否有助于任何人,但我已经合并了一些其他的build议来产生以下的MapViewActivity。

在这个例子中,只有在debugging版本和文件存在的情况下才会使用R.layout.map_dbg(把这个文件添加到你的.gitignore中)。

这种方法的优点是:

  1. 你不需要写一个ant目标(如果你使用eclipse,那么这个目标很好)
  2. 正确的释放键总是在map.xml中(希望debugging键不会被误检入)
  3. 释放键始终用于发布版本
  4. 可以使用多个debugging密钥

这种方法的缺点是:

  1. 每次更新map.xml时都需要记住更新map_dbg.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; } } 

我已经设置了一个简单的ant目标,用debugging密钥或释放密钥replaceapikey。 这是非常简单的,并保持代码不需要的逻辑。

 <target name="apikey"> <!-- Location of target layout file --> <first id="first"> <fileset dir="." includes="res/layout/kondi_training_templates.xml" /> </first> <property name="layout-file" value="${toString:first}"/> <echo>template-file: ${template-file}</echo> <replaceregexp file="${template-file}" match="android:apiKey=.*" replace='android:apiKey="${mapview.apikey}"' byline="true" /> </target> 

在地图V2它易于使用Android Studio Gradle工具发送单独的键。 我已经实现了一个简单的方法。 请在这里查看链接。