Google Maps Android API v2入門
概述
創建一個新的使用了Google Maps Android API v2的Android應用需要許多個步驟。這一節中所概述的其中的許多步驟只是需要必須執行一次而已,但有些信息則是未來應用開發方便的參考。給一個Android應用程序添加一個地圖的總體過程如下:
- 安裝Android SDK.
- 下載并配置Google Play services SDK,其中包含了Google Maps Android API。如果你使用了商業Google Maps Mobile SDK,則你必須下載并配置商業Google Maps Mobile SDK靜態庫
- 獲取一個API key。為了做到這一點,你需要在Google APIs Console注冊一個工程,并為你的app獲取一個簽名證書。
- 在你的應用程序的manifest中添加所需要的設置。
- 給你的應用程序添加一個map。
- 發布你的應用程序。
你也可能想要通過查看示例代碼來開始,示例代碼包含在Google Play services SDK中。
安裝Android SDK
這是一個先決條件,你需要安裝Android SDK。請參考獲取Android SDK。
安裝并配置Google Play services SDK
你將需要為你的app創建一個Android工程,來完成這個小節的那些步驟。如果你還沒有創建一個Android應用,你可以按照指南來創建一個"hello world" app。請參考創建一個Android工程。
Google Maps Android API v2是作為Google Play services SDK的一部分來分發的。你可以通過Android SDK Manager來下載 Google Play services SDK。
更詳細的說明,請參考Google Play services文檔。這里是你需要執行的步驟的一個總結:
- 安裝Google Play services SDK。
- 添加Google Play services作為一個Android library project。
- 在你app的project中引用Google Play services
添加Google Play services版本到你app的manifest
編輯你的應用程序的AndroidManifest.xml文件,并在<application>元素內添加如下的聲明。這會嵌入編譯app所使用的Google Play services的版本。
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
獲取一個Android認證證書及Google Maps API key
注意:Google Maps Android API v2使用了一個新的管理key的系統。來自于一個Google Maps Android v1應用程序的現存的key,通常被稱為MapView,在使用v2 API時將是無效的。
為了通過Maps API訪問Google Maps服務器,你不得不給你的應用程序添加一個Maps API key 。這個key是免費的,你可以在你任何調用了Maps API的應用程序中使用,而且它支持無限多的用戶。你可以通過提供你的應用程序的簽名證書及它的包名,從Google APIs Console,獲取一個Maps API key。通過給你的應用程序的AndroidManifest.xml文件添加一個元素來為你的應用添加key。
理解注冊你的應用程序及獲取一個key的過程,還需要一些關于Android應用的發布過程和要求的知識。總結一下,所有的Andriod應用都必須通過一個數字證書來簽名,而你持有著私有的key。由于數字證書是唯一的,它們提供了一種簡單的方式來唯一的識別你的app。這對于在系統中追蹤你的應用程序很有用,比如像Google Play Store,對于追蹤你的應用程序使用的resource,比如Google Maps服務器,也很有用。
注意:參考Android指南認證你的應用程序來獲取更多關于數字認證的信息。
Maps API keys是與特定的 證書/包 對關聯的,而不是與用戶或應用程序。每個證書你只需要一個key即可,而無論你的一個應用程序有多少用戶。使用了相同的證書的應用程序可以使用相同API key。然而,建議的方式是為你的每一個應用程序通過一個不同的證書獲取一個不同的key來認證。
為你的應用程序獲取一個key需要幾個步驟。這些步驟列出如下,并將在接下來的小節中詳細描述。
- 提取關于你的應用程序的證書的信息。
- 在Google APIs Console中注冊一個工程,并為該工程添加Maps API作為一個服務。
- 請求一個或多個keys。
- 為你的應用程序添加你的key并開始開發。
注意: 商業Google Maps Mobile SDK的用戶必須額外的為他們的API工程啟用 SDK。
顯示你的app的證書信息
Maps API key是基于你的應用程序數字證書的一個short form的,被稱為它的SHA-1指紋。這個指紋是由通用的SHA-1哈希算法產生的一個唯一的文本串。由于這個指紋本身是唯一的,所以Google Maps使用它來作為識別你的應用程序的一種方式。
為了給你的證書顯示SHA-1指紋,首先要確保你正在使用正確的證書。你可能有兩個證書:
- Debug證書:當你從命令行執行一個"debug"編譯時,或當你在Eclipse中編譯并執行一個工程而沒有將它導出為一個released應用時,Android SDK工具自動地產生這個證書。只有當你在測試時才讓你的app使用這個證書;不要試圖發布一個用debug認證簽名的app。在Android Developer文檔中的Signing in Debug Mode一節中有對于debug證書更詳細的描述。
- Release證書:當你通過ant程序或Eclipse執行一個“release”編譯時,Android SDK工具會產生這種證書。你也可以使用keytool程序產生這種證書。當你已經為向全世界發布你的應用程序做好了準備時,使用這種證書。
你可以使用keytool程序加-v參數來顯示一個證書的SHA-1指紋。更多關于Keytool的信息,請參考文檔http://docs.oracle.com/javase/6/docs/technotes/tools/windows/keytool.html。
展開下面的小節,來了解關于如何顯示你的debug或release證書的詳細的指導。
顯示debug證書指紋
-
定位你的debug keystore文件。文件名為debug.keystore,在你第一次編譯你的工程時創建。默認地,它與你的Android Virtual Device (AVD)文件存儲在相同的目錄下:
- OS X and Linux: ~/.android/
- Windows Vista and Windows 7: C:\Users\your_user_name\.android\
如果你同時在使用ADT與Eclipse,并且你不確定你的debug keystone位置在哪兒,你可以選擇Windows > Prefs > Android > Build來查看完整的路徑,你可以把這個路徑粘貼到一個文件瀏覽器來定位包含了keystore的目錄。
-
列出SHA-1指紋。
-
對于Linux或OS X,打開一個終端窗口并鍵入下列內容:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
-
對于Windows Vista和Windows 7,執行:
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
-
-
你應當看到與下面類似的輸出:
Alias name: androiddebugkey
Creation date: Jan 01, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4aa9b300
Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033
Certificate fingerprints:
MD5: AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9
SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75
Signature algorithm name: SHA1withRSA
Version: 3
以SHA1開頭的那一行包含了證書的SHA-1指紋。指紋是由冒號隔開的20對兩位16進制數的序列。
顯示release證書指紋
-
定位你的release證書keystore文件。對于release keystore則沒有默認的位置或名字。如果你不在為你的應用程序編譯release版時指定一個,則編譯出來的.apk將是未簽名的,并且你將不得不在你可以發布它之前簽名。對于release證書,為keystore和證書,你也需要證書的別名和密碼。你可以通過輸入下面內容來列出keystore中所有的keys的別名:
keytool -list -keystoreyour_keystore_name
將your_keystore_name用完整的路徑和keystore的名字來替換,包含.keystore擴展名。你將會看到keystore的密碼的提示。你但你鍵入了它,keytool將顯示出keystore中所有的別名。
-
在一個終端或命令提示符中鍵入下面內容:
keytool -list -v -keystoreyour_keystore_name-aliasyour_alias_name
將your_keystore_name 用完整的路徑和keystore的名字來替換,包含.keystore擴展名。將your_alias_name用創建它時分配給證書的別名來替換。
注意:為了保護你的keystore和key,不要在命令行鍵入storepass或keypass參數,除非你對你的電腦的安全性非常自信。比如,在一臺公共的電腦上,某些人可能會看到你的終端窗口的歷史,或列出正在運行的進程,獲取密碼,然后具有對你的簽名證書的寫權限。這將允許那些人修改或用他們自己的應用來替換你的應用。
-
你應當看到與下面內容類似的輸出:
Alias name: <alias_name>
Creation date: Feb 02, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4cc9b300
Valid from: Mon Feb 02 08:01:04 UTC 2013 until: Mon Feb 02 18:05:04 PST 2033
Certificate fingerprints:
MD5: AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6B:AC:F9
SHA1: BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:90:AF:A1:66:6E:44:5D:75
Signature algorithm name: SHA1withRSA
Version: 3
以
SHA1開頭的那一行包含了證書的
SHA-1指紋。指紋
是由冒號隔開的20對兩位16進制數的序列。
在Google APIs Console中創建一個API工程
遵循如下的步驟,在Google APIs Console中為你的應用程序創建或修改一個工程,并為Maps API執行注冊。
- 在一個瀏覽器中,導航到Google APIs Console。
- 如果你之前沒有使用過Google APIs Console,你會得到提示,來創建一個工程,用于追蹤你對于Google Maps Android API的使用。點擊Create Project;Console創建一個稱為API Project的新工程。在下一頁,這個名字顯示在左上角。要重命名或管理該工程,則點擊它的名字。
- 如果你已經在使用Google APIs Console了,你將立即看到一個你的已有工程和可用服務的列表。為Google Maps Android API使用一個新的工程仍然是一個好主意,因而選擇左上角的工程名并點擊Create。
- 你應該在主窗口看到一個APIs和服務的列表。如果沒有,則在左邊的導航欄選擇Services。
- 頁面中間所顯示的服務的列表中,向下滾動直到看見Google Maps Android API v2。這一項的右邊點擊開關指示符來使它為on。
- 這顯示了Google Maps Android API Terms of Service。如果你同意服務條款,則點擊服務條款下方的checkbox,然后點擊Accept。這將使你返回到APIs和服務的列表。
獲取一個Google Maps API key
如果你的應用程序已經完成了對Google Maps Android API v2服務的注冊,則你可以請求一個API key了。每個工程注冊多于一個的key也是可能的。
- 在Google APIs Console中導航到你的工程。
- 在左邊的導航條中,點擊API Access。
- 在結果頁中,點擊Create New Android Key...。
-
在結果對話框中,鍵入SHA-1指紋,然后是一個分號,然后是你的應用程序的包名。比如:
BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75;com.example.android.mapexample
-
Google APIs Console通過顯示Key for Android apps (with certificates),并后跟一個四十字符的API key來作出反應,比如:
AIzaSyBdVl-cTICSwYKrZ95SuvNw7dbMuDt1KG0
給你的應用程序添加API key
遵循下面的步驟來在你的應用程序的manifest中包含API key,包含在AndroidManifest.xml文件中。Maps API從這兒讀取key值并將它傳給Google Maps服務器,以確認你具有對Google Maps數據的訪問權限。
1. 在AndroidManifest.xml中,添加下面的元素作為<application>元素的一個子元素,通過在閉合標簽</application>之前插入它來實現:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="API_KEY"/>
用你的API key來替換API_KEY。這個元素將鍵 com.google.android.maps.v2.API_KEY的值設為API_KEY并使得API key對于你的應用程序中的任何MapFragment都是可見的。
2. 保存AndroidManifest.xml,然后重新編譯你的應用程序
在應用的manifest中指定app設置
一個使用了Google Maps Android API的android應用程序應該在它的manifest文件中指定如下的設置,AndroidManifest.xml:
- 一個對Google Play服務版本的引用。如果你遵從了本頁上面的步驟而到了這個位置,你已經向你的應用程序的manifest添加了所需要的聲明。
- 應用程序的Maps API key。這個key確認你已經通過Google APIs Console注冊了Google Maps服務。如果你遵從了本頁上面的步驟而到了這個位置,你已經向你的應用程序的manifest添加了API key。
- 賦予應用程序對Android系統功能及對Google Maps服務器訪問權限的Permissions。參考下面的指導來添加這些設置。
- (建議)應用程序請求OpenGL ES版本2的通知。外部服務可以探測到這個通知,并據此行動。比如,Google Play Store將不會在那些沒有OpenGL ES版本2的設備上顯示你的應用程序。參考下面的指導來添加這項設置。
指定permissions
指定你的應用程序需要的permissions,通過添加<uses-permission>元素作為<manifest>元素的子元素來實現。語法為:
<uses-permission android:name="permission_name"/>
比如,請求Internet permission,添加:
<uses-permission android:name="android.permission.INTERNET"/>
除了你的應用程序其他部分需要的權限,你必須添加如下的權限以使用Google Maps Android API:
- android.permission.INTERNET 被API使用,來從Google Maps服務器下載地圖拼貼。
- android.permission.ACCESS_NETWORK_STATE 允許API檢查連接狀態以決定數據是否可以被下載。
- com.google.android.providers.gsf.permission.READ_GSERVICES 允許API訪問Google基于web的服務。
- android.permission.WRITE_EXTERNAL_STORAGE允許API在設備的外部存儲區域緩存地圖拼貼數據。
下面的permissions是建議添加的,但如果你的應用程序不訪問用戶的當前位置,以編程的方式,或啟用My Location層,則可以忽略,
- android.permission.ACCESS_COARSE_LOCATION 允許API使用WiFi或移動蜂窩數據(或同時)來決定設備的位置。
-
android.permission.ACCESS_FINE_LOCATION 允許API使用全球定位系統(GPS)來在一個非常小的區域內決定設備的位置。
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<!-- The following two permissions are not required to use
Google Maps Android API v2, but are recommended. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
指定對OpenGL ES版本2的請求
Google Maps Android API使用OpenGL ES版本2來渲染地圖。如果沒有安裝OpenGL ES版本2,你的地圖將不會出現。我們建議你在AndroidManifest.xml中添加如下的<uses-feature>元素,作為<manifest>元素的一個子元素:
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
這個元素通知需要的外部服務。特別地,它具有阻止Google Play Store將你的應用程序顯示在不支持OpenGL ES版本2的設備上的效果。
添加一個地圖
測試你的應用程序是否被正確配置的最簡單的方式是添加一個簡單的地圖。你將不得不修改兩個文件:定義了app的layout的XML文件,及main activity Java文件。
請注意下面的代碼只在測試目標平臺為Android API 12或更新的應用程序的設置時有用。這段代碼不應該被用于一個產品應用程序中。如何添加更健壯的代碼的例子將貫穿于這份指南,并出現在示例代碼中。
1. 在app的layout XML文件中添加如下的fragment。如果你使用Eclipse中的Android Developer Tools (ADT)包創建了一個‘hello world’ app,則這個文件為res/layout/activity-main.xml。將那個文件中所有的內容替換為下面的代碼:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"/>
2. 在
MainActivity.java中添加如下的代碼:
package com.example.mapdemo;import android.app.Activity; import android.os.Bundle;
public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}</pre>
3. 編譯并運行你的應用程序。你應該能看到一個地圖。如果你沒有看到一個地圖,請確認你已經完成了本頁中所描述的所有的步驟。
實踐
1. 首先,用eclipse,以默認的方式創建一個hello world app,并將它的main layout文件的內容替換為前述只有一個MapFragment的layout,然后便執行應用程序。不出所料,這個app是無法運行起來的,會有如下的一個exception拋出來:
11-30 16:31:59.341: D/dalvikvm(6202): Late-enabling CheckJNI 11-30 16:31:59.491: E/ActivityThread(6202): Failed to inflate 11-30 16:31:59.491: E/ActivityThread(6202): android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 16:31:59.491: E/ActivityThread(6202): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 16:31:59.491: E/ActivityThread(6202): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 16:31:59.491: E/ActivityThread(6202): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 16:31:59.491: E/ActivityThread(6202): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 16:31:59.491: E/ActivityThread(6202): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.Activity.setContentView(Activity.java:1895) 11-30 16:31:59.491: E/ActivityThread(6202): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.Activity.performCreate(Activity.java:5133) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 16:31:59.491: E/ActivityThread(6202): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 16:31:59.491: E/ActivityThread(6202): at android.os.Looper.loop(Looper.java:137) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 16:31:59.491: E/ActivityThread(6202): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 16:31:59.491: E/ActivityThread(6202): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 16:31:59.491: E/ActivityThread(6202): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 16:31:59.491: E/ActivityThread(6202): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 16:31:59.491: E/ActivityThread(6202): at dalvik.system.NativeStart.main(Native Method) 11-30 16:31:59.491: E/ActivityThread(6202): Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.google.android.gms.maps.MapFragment: make sure class name exists, is public, and has an empty constructor that is public 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.Fragment.instantiate(Fragment.java:592) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.Fragment.instantiate(Fragment.java:560) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.Activity.onCreateView(Activity.java:4738) 11-30 16:31:59.491: E/ActivityThread(6202): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 16:31:59.491: E/ActivityThread(6202): ... 20 more 11-30 16:31:59.491: E/ActivityThread(6202): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.maps.MapFragment" on path: DexPathList[[zip file "/data/app/com.hanpfei.mymapexample-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.hanpfei.mymapexample-1, /vendor/lib, /system/lib]] 11-30 16:31:59.491: E/ActivityThread(6202): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53) 11-30 16:31:59.491: E/ActivityThread(6202): at java.lang.ClassLoader.loadClass(ClassLoader.java:501) 11-30 16:31:59.491: E/ActivityThread(6202): at java.lang.ClassLoader.loadClass(ClassLoader.java:461) 11-30 16:31:59.491: E/ActivityThread(6202): at android.app.Fragment.instantiate(Fragment.java:582) 11-30 16:31:59.491: E/ActivityThread(6202): ... 23 more 11-30 16:31:59.491: D/AndroidRuntime(6202): Shutting down VM 11-30 16:31:59.491: W/dalvikvm(6202): threadid=1: thread exiting with uncaught exception (group=0x415367c0) 11-30 16:31:59.491: E/AndroidRuntime(6202): FATAL EXCEPTION: main 11-30 16:31:59.491: E/AndroidRuntime(6202): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hanpfei.mymapexample/com.hanpfei.mymapexample.MainActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.os.Looper.loop(Looper.java:137) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 16:31:59.491: E/AndroidRuntime(6202): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 16:31:59.491: E/AndroidRuntime(6202): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 16:31:59.491: E/AndroidRuntime(6202): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 16:31:59.491: E/AndroidRuntime(6202): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 16:31:59.491: E/AndroidRuntime(6202): at dalvik.system.NativeStart.main(Native Method) 11-30 16:31:59.491: E/AndroidRuntime(6202): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 16:31:59.491: E/AndroidRuntime(6202): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.Activity.setContentView(Activity.java:1895) 11-30 16:31:59.491: E/AndroidRuntime(6202): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.Activity.performCreate(Activity.java:5133) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 16:31:59.491: E/AndroidRuntime(6202): ... 11 more 11-30 16:31:59.491: E/AndroidRuntime(6202): Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.google.android.gms.maps.MapFragment: make sure class name exists, is public, and has an empty constructor that is public 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.Fragment.instantiate(Fragment.java:592) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.Fragment.instantiate(Fragment.java:560) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.Activity.onCreateView(Activity.java:4738) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 16:31:59.491: E/AndroidRuntime(6202): ... 20 more 11-30 16:31:59.491: E/AndroidRuntime(6202): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.maps.MapFragment" on path: DexPathList[[zip file "/data/app/com.hanpfei.mymapexample-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.hanpfei.mymapexample-1, /vendor/lib, /system/lib]] 11-30 16:31:59.491: E/AndroidRuntime(6202): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53) 11-30 16:31:59.491: E/AndroidRuntime(6202): at java.lang.ClassLoader.loadClass(ClassLoader.java:501) 11-30 16:31:59.491: E/AndroidRuntime(6202): at java.lang.ClassLoader.loadClass(ClassLoader.java:461) 11-30 16:31:59.491: E/AndroidRuntime(6202): at android.app.Fragment.instantiate(Fragment.java:582) 11-30 16:31:59.491: E/AndroidRuntime(6202): ... 23 more2. 總之意思就是說,找不到com.google.android.gms.maps.MapFragment這個類。解決這個問題,需要把Google Play services的類庫加載進來:
在Eclipse里面選擇:File > Import > Android > Existing Android Code Into Workspace然后點擊Next。
之后Browse..., 找到路徑下的<android-sdk-folder>/extras/google/google_play_services/libproject/google-play-services_lib, 然后選擇Finish。(如果沒有這個庫,請在Android SDK Manager更新,在底端的Extras里面更新Google Play services即可)。
然后是添加對這個庫的引用:
在自己的項目上右鍵,選Properties,左邊選Android,然后在下面的Library里面Add剛才的google-play-services_lib。
3. 這個時候,應用程序是連編譯都編譯不過。解決方法就是要先把上一步創建出來的那個google-play-services_lib的project編譯一下。OK,可以編譯了,那就再一次編譯執行。這次又遇到了另外的一個exception:
11-30 17:02:56.262: E/ActivityThread(9967): Failed to inflate 11-30 17:02:56.262: E/ActivityThread(9967): android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:02:56.262: E/ActivityThread(9967): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 17:02:56.262: E/ActivityThread(9967): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 17:02:56.262: E/ActivityThread(9967): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 17:02:56.262: E/ActivityThread(9967): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 17:02:56.262: E/ActivityThread(9967): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.Activity.setContentView(Activity.java:1895) 11-30 17:02:56.262: E/ActivityThread(9967): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.Activity.performCreate(Activity.java:5133) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 17:02:56.262: E/ActivityThread(9967): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 17:02:56.262: E/ActivityThread(9967): at android.os.Looper.loop(Looper.java:137) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 17:02:56.262: E/ActivityThread(9967): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 17:02:56.262: E/ActivityThread(9967): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 17:02:56.262: E/ActivityThread(9967): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 17:02:56.262: E/ActivityThread(9967): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 17:02:56.262: E/ActivityThread(9967): at dalvik.system.NativeStart.main(Native Method) 11-30 17:02:56.262: E/ActivityThread(9967): Caused by: java.lang.IllegalStateException: A required meta-data tag in your app's AndroidManifest.xml does not exist. You must have the following declaration within the <application> element: <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.common.GooglePlayServicesUtil.n(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.common.GooglePlayServicesUtil.isGooglePlayServicesAvailable(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.maps.internal.q.v(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.maps.internal.q.u(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.maps.MapsInitializer.initialize(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.maps.MapFragment$b.cE(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.maps.MapFragment$b.a(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.dynamic.a.a(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.dynamic.a.onInflate(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at com.google.android.gms.maps.MapFragment.onInflate(Unknown Source) 11-30 17:02:56.262: E/ActivityThread(9967): at android.app.Activity.onCreateView(Activity.java:4745) 11-30 17:02:56.262: E/ActivityThread(9967): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 17:02:56.262: E/ActivityThread(9967): ... 20 more 11-30 17:02:56.262: D/AndroidRuntime(9967): Shutting down VM 11-30 17:02:56.262: W/dalvikvm(9967): threadid=1: thread exiting with uncaught exception (group=0x415367c0) 11-30 17:02:56.262: E/AndroidRuntime(9967): FATAL EXCEPTION: main 11-30 17:02:56.262: E/AndroidRuntime(9967): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hanpfei.mymapexample/com.hanpfei.mymapexample.MainActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.os.Looper.loop(Looper.java:137) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 17:02:56.262: E/AndroidRuntime(9967): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 17:02:56.262: E/AndroidRuntime(9967): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 17:02:56.262: E/AndroidRuntime(9967): at dalvik.system.NativeStart.main(Native Method) 11-30 17:02:56.262: E/AndroidRuntime(9967): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.Activity.setContentView(Activity.java:1895) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.Activity.performCreate(Activity.java:5133) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 17:02:56.262: E/AndroidRuntime(9967): ... 11 more 11-30 17:02:56.262: E/AndroidRuntime(9967): Caused by: java.lang.IllegalStateException: A required meta-data tag in your app's AndroidManifest.xml does not exist. You must have the following declaration within the <application> element: <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.common.GooglePlayServicesUtil.n(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.common.GooglePlayServicesUtil.isGooglePlayServicesAvailable(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.maps.internal.q.v(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.maps.internal.q.u(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.maps.MapsInitializer.initialize(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.maps.MapFragment$b.cE(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.maps.MapFragment$b.a(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.dynamic.a.a(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.dynamic.a.onInflate(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at com.google.android.gms.maps.MapFragment.onInflate(Unknown Source) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.app.Activity.onCreateView(Activity.java:4745) 11-30 17:02:56.262: E/AndroidRuntime(9967): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 17:02:56.262: E/AndroidRuntime(9967): ... 20 more4. 這個exception呢,大體意思就是說,在app的AndroidManifest.xml文件中少加入了一個<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />標簽。OK,我們遵照前面文檔的說明,把這個元素加入到AndroidManifest.xml文件就是了,可以參考文檔前面的添加Google Play services版本到你app的manifest部分,把那兩行code直接復制粘貼即可。不過我們卻又遭遇了另一個exception:
11-30 17:09:34.261: E/ActivityThread(10763): Failed to inflate 11-30 17:09:34.261: E/ActivityThread(10763): android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:09:34.261: E/ActivityThread(10763): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 17:09:34.261: E/ActivityThread(10763): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 17:09:34.261: E/ActivityThread(10763): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 17:09:34.261: E/ActivityThread(10763): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 17:09:34.261: E/ActivityThread(10763): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.Activity.setContentView(Activity.java:1895) 11-30 17:09:34.261: E/ActivityThread(10763): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.Activity.performCreate(Activity.java:5133) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 17:09:34.261: E/ActivityThread(10763): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 17:09:34.261: E/ActivityThread(10763): at android.os.Looper.loop(Looper.java:137) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 17:09:34.261: E/ActivityThread(10763): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 17:09:34.261: E/ActivityThread(10763): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 17:09:34.261: E/ActivityThread(10763): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 17:09:34.261: E/ActivityThread(10763): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 17:09:34.261: E/ActivityThread(10763): at dalvik.system.NativeStart.main(Native Method) 11-30 17:09:34.261: E/ActivityThread(10763): Caused by: java.lang.SecurityException: The Maps API requires the additional following permissions to be set in the AndroidManifest.xml to ensure a correct behavior: 11-30 17:09:34.261: E/ActivityThread(10763): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 11-30 17:09:34.261: E/ActivityThread(10763): <uses-permission android:name="android.permission.INTERNET"/> 11-30 17:09:34.261: E/ActivityThread(10763): <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 11-30 17:09:34.261: E/ActivityThread(10763): <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> 11-30 17:09:34.261: E/ActivityThread(10763): at maps.af.cf.a(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at maps.af.ay.a(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at maps.af.al.a(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at maps.af.be.a(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at maps.af.bd.a(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at cmj.onTransact(SourceFile:107) 11-30 17:09:34.261: E/ActivityThread(10763): at android.os.Binder.transact(Binder.java:347) 11-30 17:09:34.261: E/ActivityThread(10763): at com.google.android.gms.maps.internal.IMapFragmentDelegate$a$a.onCreateView(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at com.google.android.gms.maps.MapFragment$a.onCreateView(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at com.google.android.gms.dynamic.a$4.b(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at com.google.android.gms.dynamic.a.a(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at com.google.android.gms.dynamic.a.onCreateView(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at com.google.android.gms.maps.MapFragment.onCreateView(Unknown Source) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.Fragment.performCreateView(Fragment.java:1695) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:861) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1137) 11-30 17:09:34.261: E/ActivityThread(10763): at android.app.Activity.onCreateView(Activity.java:4746) 11-30 17:09:34.261: E/ActivityThread(10763): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 17:09:34.261: E/ActivityThread(10763): ... 20 more 11-30 17:09:34.261: D/AndroidRuntime(10763): Shutting down VM 11-30 17:09:34.261: W/dalvikvm(10763): threadid=1: thread exiting with uncaught exception (group=0x415367c0) 11-30 17:09:34.261: E/AndroidRuntime(10763): FATAL EXCEPTION: main 11-30 17:09:34.261: E/AndroidRuntime(10763): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hanpfei.mymapexample/com.hanpfei.mymapexample.MainActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.os.Looper.loop(Looper.java:137) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 17:09:34.261: E/AndroidRuntime(10763): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 17:09:34.261: E/AndroidRuntime(10763): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 17:09:34.261: E/AndroidRuntime(10763): at dalvik.system.NativeStart.main(Native Method) 11-30 17:09:34.261: E/AndroidRuntime(10763): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.Activity.setContentView(Activity.java:1895) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.Activity.performCreate(Activity.java:5133) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 17:09:34.261: E/AndroidRuntime(10763): ... 11 more 11-30 17:09:34.261: E/AndroidRuntime(10763): Caused by: java.lang.SecurityException: The Maps API requires the additional following permissions to be set in the AndroidManifest.xml to ensure a correct behavior: 11-30 17:09:34.261: E/AndroidRuntime(10763): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 11-30 17:09:34.261: E/AndroidRuntime(10763): <uses-permission android:name="android.permission.INTERNET"/> 11-30 17:09:34.261: E/AndroidRuntime(10763): <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 11-30 17:09:34.261: E/AndroidRuntime(10763): <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> 11-30 17:09:34.261: E/AndroidRuntime(10763): at maps.af.cf.a(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at maps.af.ay.a(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at maps.af.al.a(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at maps.af.be.a(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at maps.af.bd.a(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at cmj.onTransact(SourceFile:107) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.os.Binder.transact(Binder.java:347) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.google.android.gms.maps.internal.IMapFragmentDelegate$a$a.onCreateView(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.google.android.gms.maps.MapFragment$a.onCreateView(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.google.android.gms.dynamic.a$4.b(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.google.android.gms.dynamic.a.a(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.google.android.gms.dynamic.a.onCreateView(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at com.google.android.gms.maps.MapFragment.onCreateView(Unknown Source) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.Fragment.performCreateView(Fragment.java:1695) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:861) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1137) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.app.Activity.onCreateView(Activity.java:4746) 11-30 17:09:34.261: E/AndroidRuntime(10763): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 17:09:34.261: E/AndroidRuntime(10763): ... 20 more5. 這次是關于權限的。那我們就將前文中提到的要添加的那些權限都加進去。必須要的4種,可選的兩種。真是讓人無奈,編譯執行之后,還是有exception拋出來:
11-30 17:14:36.155: I/Process(11373): Sending signal. PID: 11373 SIG: 9 11-30 17:14:41.851: E/ActivityThread(11619): Failed to inflate 11-30 17:14:41.851: E/ActivityThread(11619): android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:14:41.851: E/ActivityThread(11619): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 17:14:41.851: E/ActivityThread(11619): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 17:14:41.851: E/ActivityThread(11619): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 17:14:41.851: E/ActivityThread(11619): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 17:14:41.851: E/ActivityThread(11619): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.Activity.setContentView(Activity.java:1895) 11-30 17:14:41.851: E/ActivityThread(11619): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.Activity.performCreate(Activity.java:5133) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 17:14:41.851: E/ActivityThread(11619): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 17:14:41.851: E/ActivityThread(11619): at android.os.Looper.loop(Looper.java:137) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 17:14:41.851: E/ActivityThread(11619): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 17:14:41.851: E/ActivityThread(11619): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 17:14:41.851: E/ActivityThread(11619): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 17:14:41.851: E/ActivityThread(11619): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 17:14:41.851: E/ActivityThread(11619): at dalvik.system.NativeStart.main(Native Method) 11-30 17:14:41.851: E/ActivityThread(11619): Caused by: java.lang.RuntimeException: API key not found. Check that <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="your API key"/> is in the <application> element of AndroidManifest.xml 11-30 17:14:41.851: E/ActivityThread(11619): at maps.af.ay.a(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at maps.af.ay.a(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at maps.af.al.a(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at maps.af.be.a(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at maps.af.bd.a(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at cmj.onTransact(SourceFile:107) 11-30 17:14:41.851: E/ActivityThread(11619): at android.os.Binder.transact(Binder.java:347) 11-30 17:14:41.851: E/ActivityThread(11619): at com.google.android.gms.maps.internal.IMapFragmentDelegate$a$a.onCreateView(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at com.google.android.gms.maps.MapFragment$a.onCreateView(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at com.google.android.gms.dynamic.a$4.b(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at com.google.android.gms.dynamic.a.a(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at com.google.android.gms.dynamic.a.onCreateView(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at com.google.android.gms.maps.MapFragment.onCreateView(Unknown Source) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.Fragment.performCreateView(Fragment.java:1695) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:861) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1137) 11-30 17:14:41.851: E/ActivityThread(11619): at android.app.Activity.onCreateView(Activity.java:4746) 11-30 17:14:41.851: E/ActivityThread(11619): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 17:14:41.851: E/ActivityThread(11619): ... 20 more 11-30 17:14:41.861: D/AndroidRuntime(11619): Shutting down VM 11-30 17:14:41.861: W/dalvikvm(11619): threadid=1: thread exiting with uncaught exception (group=0x415367c0) 11-30 17:14:41.861: E/AndroidRuntime(11619): FATAL EXCEPTION: main 11-30 17:14:41.861: E/AndroidRuntime(11619): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hanpfei.mymapexample/com.hanpfei.mymapexample.MainActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.ActivityThread.access$600(ActivityThread.java:153) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.os.Handler.dispatchMessage(Handler.java:99) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.os.Looper.loop(Looper.java:137) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.ActivityThread.main(ActivityThread.java:5289) 11-30 17:14:41.861: E/AndroidRuntime(11619): at java.lang.reflect.Method.invokeNative(Native Method) 11-30 17:14:41.861: E/AndroidRuntime(11619): at java.lang.reflect.Method.invoke(Method.java:525) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) 11-30 17:14:41.861: E/AndroidRuntime(11619): at dalvik.system.NativeStart.main(Native Method) 11-30 17:14:41.861: E/AndroidRuntime(11619): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.view.LayoutInflater.inflate(LayoutInflater.java:469) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:320) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.Activity.setContentView(Activity.java:1895) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.hanpfei.mymapexample.MainActivity.onCreate(MainActivity.java:12) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.Activity.performCreate(Activity.java:5133) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293) 11-30 17:14:41.861: E/AndroidRuntime(11619): ... 11 more 11-30 17:14:41.861: E/AndroidRuntime(11619): Caused by: java.lang.RuntimeException: API key not found. Check that <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="your API key"/> is in the <application> element of AndroidManifest.xml 11-30 17:14:41.861: E/AndroidRuntime(11619): at maps.af.ay.a(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at maps.af.ay.a(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at maps.af.al.a(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at maps.af.be.a(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at maps.af.bd.a(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at cmj.onTransact(SourceFile:107) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.os.Binder.transact(Binder.java:347) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.google.android.gms.maps.internal.IMapFragmentDelegate$a$a.onCreateView(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.google.android.gms.maps.MapFragment$a.onCreateView(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.google.android.gms.dynamic.a$4.b(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.google.android.gms.dynamic.a.a(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.google.android.gms.dynamic.a.onCreateView(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at com.google.android.gms.maps.MapFragment.onCreateView(Unknown Source) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.Fragment.performCreateView(Fragment.java:1695) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:861) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1137) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.app.Activity.onCreateView(Activity.java:4746) 11-30 17:14:41.861: E/AndroidRuntime(11619): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689) 11-30 17:14:41.861: E/AndroidRuntime(11619): ... 20 more6. 這次是關于API key的。OK,那我們就再遵照前文的說明,在Google APIs Console中產生一個API key加進來。這個地方多說一點,其實我們通過eclipse已經是可以看到debug證書的SHA-1指紋了,而不需要再去執行什么keytool。方法為,選擇Window->Preferences->Android->Build,在SHA-1 fingerprint那一行。再次編譯并執行。
哎,我們終于看到了期待已久的地圖了。
![]()
Done.
來自:http://my.oschina.net/wolfcs/blog/180390
