Android: автоматически выберите ключ API debug / release Maps?
OBSOLETED: этот старый вопрос относится к устаревшему API Google Maps v1. При использовании V2 API вы можете использовать несколько отпечатков пальцев сертификата в одном консоль Google API запись. Ключ API больше не хранится в Манифесте или коде.
можно ли автоматически определить, какой сертификат использовался для подписания APK? Я хотел бы иметь сертификаты debug и release Maps в приложении и передать действительный в MapView конструктор.
с такой настройкой я не ошибусь при выпуске приложения - я использую сертификат отладки на эмуляторе и моем устройстве, а затем подписываю с выпуском один перед отправкой приложения на рынок.
Я думал об обнаружении моего конкретного устройства или о том, подключен ли отладчик, но он не идеален. Может быть, какая-то маркировка файла нужна для сертификата отладки? Есть ли лучший способ?
11 ответов
существует новый способ определить, является ли это отладочной сборкой или выпуском в SDK Tools, редакция 17. Отрывок из обзора новых функций:
сборки теперь генерируют класс под названием BuildConfig содержащий DEBUG константа, которая автоматически устанавливается в соответствии с типом сборки. Вы можете проверить (BuildConfig.DEBUG) константа в коде для запуска функций только отладки.
Итак, теперь вы можете просто написать что-то вроде этого:
if (BuildConfig.DEBUG)
{
//Your debug code goes here
}
else
{
//Your release code goes here
}
обновление: я столкнулся с ошибкой в ADT: иногда BuildConfig.DEBUG
is true
после того, как пакет документов на экспорт. Описание здесь: http://code.google.com/p/android/issues/detail?id=27940
были те же проблемы с ключом API. Вот полное решение, основанное на приведенной выше ссылке и пример из 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 e.g. 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;
}
вы должны узнать hashValue() вашей отладочной подписи один раз, просто выведите sigs[i].hashCode ().
затем я не хотел динамически добавлять MapView, а скорее использовать xml-файл. Вы не можете установить атрибут ключа api в коде и использовать XML-макет, поэтому я использую этот простой метод (хотя копирование 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);
}
гораздо проще определить, является ли это отладочной сборкой, проверив флаг отладки в информации о приложении, чем хэш подписи.
public boolean isDebugBuild() throws Exception
{
PackageManager pm = _context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(_context.getPackageName(), 0);
return ((pi.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
}
Как только отладочная сборка найдена, вы можете использовать другой ресурс для отображения карты или создать mapview в приложении и добавить в макет.
if(isDebugBuild())
{
_mapView = new MapView(this, getString(R.string.debugmapskey));
}
else
{
_mapView = new MapView(this, getString(R.string.releasemapskey));
}
Я работал вокруг ужасной неправильной интеграции ключей api в процесс сборки и управления версиями, сделав его свойством, хранящимся в local.properties
. Я должен был добавить следующее к 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>
теперь, конечно, я должен был создать mapview.xml.tpl
в моих проектах root (он не может перейти в res/layout
потому что это нарушит процесс сборки):
<?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@ заменяется реальным ключом. К сожалению, я не нашел способа различать сборки debug и release на этом этапе, поэтому для компиляции для release я просто добавляю релиз apiKey к параметрам ant:
ant -DmapsApiKey=.... release
этот подход хорошо интегрируется с SCM (мне не нужно проверять ключи) и приемлемо с процессом сборки.
Если вы все еще заинтересованы, я просто написал в блоге о другом способе сделать это. С простым изменением скрипта сборки Android вы можете переключить ключ API карты, а также все другие необходимые изменения выпуска. Что мне нравится в этом, так это то, что ничего отладочного не входит в выпуск, и вы можете сохранить макеты XML так, как они были раньше.
http://blog.cuttleworks.com/2011/02/android-dev-prod-builds/
Я думаю, что создание записи в консоли Google API, которая включает в себя как ваш ключ выпуска, так и ключ отладки (оба сопоставления с одним и тем же пакетом), отлично работает и является гораздо более простым способом не беспокоиться о том, отлаживаете ли вы или компилируете версию выпуска. Решение изложено здесь
все ответы здесь кажутся устаревшими, если вы используете Android studio, то gradle-это путь
используйте разные ключи в своей сборке.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"/>
и если вы хотите сохранить некоторые пароли для отладки и выпуска по-разному, то вы должны следовать этой
Я закончил со специальным файлом на SD-карте - если есть, используйте ключ отладки; отсутствует-используйте выпуск один. И это работает.
EDIT: см. новый принятый ответ, он работает лучше
Я не знаю, помогает ли это кому-нибудь, но я объединил некоторые другие предложения здесь, чтобы создать следующую MapViewActivity.
в этом примере R. layout.map_dbg используется, только если это отладочная сборка и файл существует (добавьте этот файл в свой .gitignore).
преимущества этого подхода:
- вам не нужно писать цель муравья (хорошо, если вы используете eclipse)
- правильный ключ выпуска всегда находится на карте.XML (надеюсь, ключ отладки не будет проверен по ошибке)
- ключ выпуска всегда используется для сборки выпуска
- можно использовать несколько ключей отладки
недостатками этого подхода являются :
-
вы должны помнить, чтобы обновить map_dbg.xml каждый раз карта.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, которая заменяет apikey либо ключом отладки, либо ключом выпуска. Это очень просто и сохраняет код свободным от нежелательной логики.
<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>
В Map V2 его легко отправить отдельные ключи с помощью Android Studio Gradle tool. Я реализовал простой способ для этого. пожалуйста, проверьте ссылку здесь.