Android: автоматически выбрать ключ отладки / выпуска Карты API? - PullRequest
40 голосов
/ 12 июня 2010

УДАЛЕНО: этот старый вопрос относится к устаревшему API Карт Google v1.При использовании v2 API вы можете использовать несколько отпечатков сертификатов в одной консоли API Google .Ключ API больше не хранится ни в манифесте, ни в коде.


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

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

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

Ответы [ 11 ]

46 голосов
/ 24 марта 2012

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

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

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

ОБНОВЛЕНИЕ: Я столкнулся с ошибкой в ​​ADT: иногда BuildConfig.DEBUG равен true после экспорта пакета приложения.Описание здесь: http://code.google.com/p/android/issues/detail?id=27940

26 голосов
/ 30 сентября 2010

Были те же хлопоты с ключом 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);
    }
10 голосов
/ 17 мая 2011

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

public boolean isDebugBuild() throws Exception
{
   PackageManager pm = _context.getPackageManager();
   PackageInfo pi = pm.getPackageInfo(_context.getPackageName(), 0);

   return ((pi.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
}

Как только отладочная сборка найдена, вы можете использовать другой ресурсдля отображения карты или создания карты в приложении и добавления к макету.

    if(isDebugBuild())
    {
        _mapView = new MapView(this, getString(R.string.debugmapskey));
    }
    else
    {
        _mapView = new MapView(this, getString(R.string.releasemapskey));
    }
3 голосов
/ 31 августа 2013

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

3 голосов
/ 01 февраля 2011

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

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

3 голосов
/ 12 декабря 2010

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

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

ant -DmapsApiKey=.... release 

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

2 голосов
/ 30 марта 2016

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

И если вы хотите сохранить некоторые пароли для отладки и выпуска по-другому, то выследует это

1 голос
/ 12 августа 2011

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

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

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

  1. вам не нужно писать цель муравья (хорошо, если вы используете eclipse)
  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;
        }
    
    }
    
1 голос
/ 14 июня 2010

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

РЕДАКТИРОВАТЬ: см новый принятый ответ, он работает лучше

0 голосов
/ 01 сентября 2016

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

...