Android:自动选择调试/发布 Maps api 密钥?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3029819/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:22:42  来源:igfitidea点击:

Android: automatically choose debug/release Maps api key?

androidgoogle-mapsdebuggingkeyandroid-mapview

提问by tomash

OBSOLETED: this old question refers to obsoleted Google Maps v1 API. When using v2 API, you can use multiple certificate fingerprints in one Google API Consoleentry. API Key is no longer stored in Manifest nor code.

过时:这个老问题是指过时的 Google Maps v1 API。使用 v2 API 时,您可以在一个Google API 控制台条目中使用多个证书指纹。API Key 不再存储在 Manifest 和代码中。



Is it possible to automatically detect, which certificate was used for signing APK? I'd like to have both debug and release Maps certificates in application and pass valid one to MapView constructor.

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

With such setup I will not make mistake while releasing application - I'm using debug certificate on emulator and my device, then sign with release one before sending app to Market.

通过这样的设置,我在发布应用程序时不会出错 - 我在模拟器和我的设备上使用调试证书,然后在将应用程序发送到市场之前使用发布版本签名。

I was thinking about detecting my particular device or whether debugger is connected but it is not perfect. Maybe some file marking need for debug certificate? Is there any better way?

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

回答by Alexander Mironov

There is a new way to determine is it a debug build or release one in SDK Tools, Revision 17. An excerpt from new features overview:

SDK Tools, Revision 17 中有一种新方法可以确定它是调试版本还是发布版本。新功能概述的摘录:

Builds now generate a class called BuildConfigcontaining a DEBUGconstant that is automatically set according to your build type. You can check the (BuildConfig.DEBUG) constant in your code to run debug-only functions.

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

So now you can simply write something like this:

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

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

UPDATE:I've encountered bug in ADT: sometimes BuildConfig.DEBUGis trueafter exporting application package. Description is here: http://code.google.com/p/android/issues/detail?id=27940

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

回答by Bachi

Had the same hassle with the API key. Here's a full solution, based on the above link and example from Bijarni(which somehow didn't work for me), I use now this method:

与 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;
}

You have to find out your debug signature's hashValue() once, just output sigs[i].hashCode().

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

Then, I didn't want to dynamically add the MapView, but rather use the xml file. You cannot set the api key attribute in the code and use an xml layout, so I use this simple method (though copying the xml layout isn't so beautiful):

然后,我不想动态添加 MapView,而是使用 xml 文件。不能在代码中设置api key属性并使用xml布局,所以我使用了这个简单的方法(虽然复制xml布局不是那么漂亮):

In my MapActivity:

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

回答by Suriya

Much easier way to determine whether it is a debug build is by checking the debug flag on the application info than the signature hash.

确定它是否是调试版本的更简单的方法是通过检查应用程序信息上的调试标志而不是签名哈希。

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

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

Once debug build is found, either you can use different resource for showing map or create the mapview within the app and add to a layout.

找到调试版本后,您可以使用不同的资源来显示地图或在应用程序中创建地图视图并添加到布局中。

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

回答by ge0rg

I have worked around the horrendous mis-integration of the api keys into the build process and source control by making it a property stored in local.properties. I had to add the following to build.xml:

我通过将 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>

Now, of course I had to create mapview.xml.tplin my projects root (it can't go to res/layoutbecause it will break the build process):

现在,当然我必须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@"
    />

During pre-compilation, the template is copied to the right place and @apiKey@ is replaced with the real key. Unfortunately I have not found a way to distinguish between debug and release builds in this phase, so to compile for release, I just add the release apiKey to the ant parameters:

在预编译期间,模板被复制到正确的位置,@apiKey@ 被替换为真正的密钥。不幸的是,我还没有找到在这个阶段区分调试和发布版本的方法,所以为了发布版本进行编译,我只需将发布 apiKey 添加到 ant 参数中:

ant -DmapsApiKey=.... release 

This approach integrates well with SCM (I do not need to check in the keys) and acceptably with the build process.

这种方法与 SCM(我不需要签入密钥)很好地集成在一起,并且与构建过程是可以接受的。

回答by Romain

If you're still interested I just blogged about another way to do this. With a simple change to the Android build script, you can switch the Map API key as well as all other required release changes. What I like about this is that nothing debug-related goes into the release, and you can keep the XML layouts just the way they were before.

如果你仍然感兴趣,我刚刚写了一篇关于另一种方法的博客。通过对 Android 构建脚本的简单更改,您可以切换 Map API 密钥以及所有其他必需的版本更改。我喜欢这一点的一点是发行版中没有任何与调试相关的内容,并且您可以保持 XML 布局与以前一样。

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

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

回答by guibar

I think that creating an entry in the Google API's console which includes both your release key and your debug key (both mapping to the same package) works great and is a much simpler way to not have to worry about whether you are debuging or compiling a release version. The solution is outlined here

我认为在 Google API 的控制台中创建一个包含您的发布密钥和调试密钥(都映射到同一个包)的条目效果很好,并且是一种更简单的方法,无需担心您是在调试还是编译发行版。此处概述解决方案

回答by penduDev

All answers here seem outdated, if you are using android studio then gradle is the way to go

这里的所有答案似乎都过时了,如果您使用的是 android studio,那么 gradle 是最佳选择

Use different keys in your build.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]"
       }
    }
  }

And in your AndroidManifest.xml

在你的AndroidManifest.xml 中

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

source

来源

And if you want to save some passwords for debug and release differently then you should follow this

如果你想保存一些密码以进行调试和不同的发布,那么你应该遵循这个

回答by tomash

I've ended up with the special file on SD card - if present, use debug key; missing - use release one. And it works.

我最终得到了 SD 卡上的特殊文件 - 如果存在,请使用调试密钥;缺少 - 使用第一个版本。它有效。

EDIT:see new accepted answer, it works better

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

回答by jimoleary

I don't know if this helps anyone but I have merged some of the other suggestions here to produce the following MapViewActivity.

我不知道这是否对任何人有帮助,但我在这里合并了一些其他建议以生成以下 MapViewActivity。

In this example R.layout.map_dbg is only used if this is a debug build and the file exists (add this file to your .gitignore).

在这个例子中,R.layout.map_dbg 仅在这是一个调试版本并且文件存在时才使用(将此文件添加到您的 .gitignore)。

The advantages of this approach are :

这种方法的优点是:

  1. you don't need to write an ant target (good if you use eclipse)
  2. the correct release key is always in map.xml (hopefully a debug key won't be checked in by mistake)
  3. the release key is always used for a release build
  4. multiple debug keys can be used
  1. 你不需要写一个 ant 目标(如果你使用 eclipse 就好了)
  2. 正确的发布密钥始终在 map.xml 中(希望调试密钥不会被错误签入)
  3. 发布密钥始终用于发布版本
  4. 可以使用多个调试键

The disadvantages of this approach are :

这种方法的缺点是:

  1. you need to remember to update map_dbg.xml every time map.xml is updated

    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. 每次更新 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;
        }
    
    }
    

回答by slott

I have setup a simple ant target that replaces the apikey with either a debug key or a release key. This is really simple and keeps the code free of unwanted logic.

我已经设置了一个简单的 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>