2010-06-12 3 views
40

OBSOLETED: этот старый вопрос относится к устаревшему API Google Maps v1. При использовании API v2 вы можете использовать несколько отпечатков сертификата в одной записи Google API Console. API-ключ больше не сохраняется в манифесте или коде.Android: автоматически выбирает debug/release Maps api key?


Можно ли автоматически определить, какой сертификат используется для подписи APK? Я хотел бы отлаживать и выпускать сертификаты Карты в приложении и передавать их в конструктор MapView.

С такой настройкой я не ошибусь при выпуске приложения - я использую сертификат отладки на эмуляторе и моем устройстве, а затем подписываюсь с выпуском до отправки приложения на рынок.

Я думал о обнаружении своего устройства или подключен ли отладчик, но он не идеален. Может быть, для проверки отладки требуется некоторая маркировка файлов? Есть ли лучший способ?

+0

Возможно, вы найдете ответ [здесь] (http://stackoverflow.com/questions/1743683/distinguishing-development-mode-and-release-mode-environment-settings-on-android/3204444#3204444) подходящий также. –

+0

Для карты Api V2, Как использовать клавиши динамически. проверьте мой ответ http://stackoverflow.com/a/40462174/1348522 –

ответ

45

Существует новый способ определить это отладочная сборка или выпуск в SDK Tools, Revision 17. Отрывок из новых функций Обзор:

Сборки Теперь создать класс под названием BuildConfig, содержащий DEBUG константу, которая автоматически устанавливается в соответствии с типом сборки. Вы можете проверить константу (BuildConfig.DEBUG) в своем коде для запуска функций только для отладки.

Итак, теперь вы можете просто написать что-то вроде этого:

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

UPDATE: я столкнулся ошибка в АДТ: иногда BuildConfig.DEBUG является true после экспорта пакета прикладных программ. Описание находится здесь: http://code.google.com/p/android/issues/detail?id=27940

+0

Да, теперь это выглядит правильно. Я буду двигаться, как только я получу rev 17, просто давая ему несколько дней, прежде чем загружать сначала. – Ifor

+0

Изменение принятого ответа на SDK rev 17 доступно, в некоторых случаях другие высокопринятые ответы могут быть по-прежнему ценными. – tomash

+0

Просто хотел заменить предыдущий код обнаружения отладки на этот, но упомянутая ошибка по-прежнему на данный момент, похоже, существует. – Bachi

1

Я получил специальный файл на SD-карте - если есть, используйте клавишу отладки; отсутствует - используйте выпуск один. И это работает.

EDIT: увидеть новый обслуживаемый ответ, он работает лучше

25

Если бы тот же хлопот с ключом API. Вот полное решение, основанное на вышеуказанной ссылке и example from 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; 
} 

Вы должны узнать отладочных ЭЦП в значение хэш() один раз, просто output 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); 
    } 
+4

Одно замечание - мне не нравятся ваши два макета, так как он требует одновременного изменения двух файлов, вместо этого я создаю MapView через 'new MapView (это, isDebug? keyDebug: keyRelease); 'и добавление его в текущий макет. – tomash

+1

Да, у меня тоже было динамическое создание, но так как макет карты не изменился, и я хотел, чтобы все макеты в одном месте (определение xml) и не смешивались, я вышвырнул выше. Оба отлично работают. – Bachi

+4

У вас всегда может быть 3 файла макета, а у 2 вы включаете только два в свою фактическую реализацию выше и ниже MapView. – Blundell

3

Я работал над ужасной неверной интеграцией ключей 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 в моем корне проектов (он не может пойти в 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="@[email protected]" 
    /> 

Во время предварительной компиляции шаблон копируется в нужное место, а @ apiKey @ заменяется реальным ключом. К сожалению, я не нашел способ различать отладки и выпуска строит на этом этапе, так компилировать для освобождения, я просто добавить apiKey отпускания муравья параметров:

ant -DmapsApiKey=.... release 

Этот подход хорошо интегрируется с SCM (I не нужно проверять ключи) и приемлемо с процессом сборки.

3

Если вам все еще интересно, я просто написал о другом способе сделать это.С простым изменением сценария сборки Android вы можете переключить ключ API карты, а также все другие необходимые изменения выпуска. Что мне нравится в этом, так это то, что в релиз не входит связанное с отладкой, и вы можете хранить макеты XML так, как раньше.

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

+0

Я думаю, что вы имеете в виду: http://blog.cuttleworks.com/2011/02/android-dev-prod-builds/ –

+0

Спасибо Энди, я обновил ответ. (Мне действительно нужно исправить недостающее перенаправление) – Gromix

10

Гораздо более простой способ определить, является ли это отладки сборки, проверяя флаг отладки на информации приложений, чем хэш подписи.

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)); 
    } 
+0

Это хорошее решение, если вы всегда устанавливаете андроид: debuggable = true при разработке и андроид: debuggable = false, если нет. Однако я обнаружил, что отключу отладку только в самом конце разработки и тестирования, но часто отправляет ранее подписанные .apks клиенту. Следовательно, ключ подписи работает лучше для меня в этом случае. – Bachi

+3

Привет, Bachi, Из редакции SDK Tools 8, http://developer.android.com/sdk/tools-notes.html (Общие замечания), вам не нужно добавлять флаг отладки в AndroidManifest, инструменты автоматически устанавливают их на основе выпуска или развития. – Suriya

+0

Я думаю, что ревизия 16 перестает это делать ... Я столкнулся с проблемами с этим в своем последнем приложении, и мне пришлось изменить мой подход к этому: http://stackoverflow.com/questions/8480763/is-there-a- way-to-define-is-an-android-application-is-signed-for-product – TacB0sS

1

Я не знаю, помогает ли это кому-либо, но я объединил некоторые другие предложения здесь, чтобы создать следующую MapViewActivity.

В этом примере R.layout.map_dbg используется, только если это сборка отладки и файл существует (добавьте этот файл в свой .gitignore).

Преимущества этого подхода являются:

  1. вам не нужно писать муравей цели (хорошо, если вы используете затмение)
  2. ключ правильный релиз всегда в map.xml (надеюсь, отладочный ключ не будет проверяться по ошибке)
  3. ключ релиза всегда используются для сборки выпуска
  4. нескольких ключей отладки можно использовать

К недостаткам этого подхода являются:

  1. вам нужно помнить, чтобы обновить map_dbg.xml каждый раз 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; 
        } 
    
    } 
    
0

У меня установлена ​​простая цель муравья, которая заменяет 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> 
3

Я думаю, что при создании записи в консоли Google API, который включает в себя как ключ разблокировки и ключ отладки (как отображение в том же пакет) прекрасно работает и является гораздо более простым способом не придется беспокоиться о будь то отладка или компиляция версии выпуска. Решение излагается here

+0

Добавление нескольких ключей sha1 отлично подходит для Maps API 2 - все упомянутые здесь решения относятся к предыдущему API 1, где не было удобного решения. – Bachi

2

Все ответы здесь кажутся устаревшими, если вы используете 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"/> 

source

И если вы хотите сохранить некоторые пароли для отладки и выпуска иначе, то вы должны следовать this

0

В Map V2 Its легко отправить раздельные клавиши с помощью Android Studio Gradle инструмента. Я применил для этого простой способ. перейдите по ссылке here.

Смежные вопросы