1. 程式人生 > 實用技巧 >Google API V2申請及Google Map簡單應用例子

Google API V2申請及Google Map簡單應用例子

步驟一:

GoogleMap環境準備。

Android系統預設並不支援呼叫Google Map,為正常呼叫Google Map服務,需要先進行如下準備工作。

1)獲取Map API Key

單擊Eclipse主選單:Window —>Preferences —> 單擊左側“Android”—> Build —> 彈出如圖1所示。

151221371.jpg

圖1檢視Android模擬器的Keystore

2)上圖中顯示的便是模擬器的keystore的儲存位置,接下來應用程式需要根據該keystore來生成Google API的Key。

3)用JDK提供的keytool工具為Android keystore生成認證指紋,啟動命令列視窗輸入如下命令:

keytool –list –keystore <Android keystore的儲存位置>

其中<Android keystore的儲存位置>要替換成圖1中Androidkeystore的儲存位置,如:Keytool -list -keystore "D:\Program Files\android-sdks \.android\debug.keystore"。

151229821.jpg

圖2指紋

注:預設金鑰庫口令是:android

就會得到MD5的指紋,記錄下此記錄:二十段用冒號割開的數字段,每段是兩個十六進位制的數(圖2中紅色刪除線下的部分)

4)在Google APIs Console上建立專案,並且註冊Maps API。

首先,去這個網址:https://code.google.com/apis/console/

注:本文對申請API Key V2的說明是基於google developer console(上面的網址)網站舊版本的說明,現在已更新了,如果要返回舊版本可在開啟網址後,選擇舊版本。

170530461.jpg

用Gmail的賬戶登入,如果是第一次的話,需要建立專案,預設情況會建立一個叫做APIProject的專案。

登陸之後出現頁面(如圖3所示):

151243437.jpg

圖3建立APIProject工程

單擊“Createproject...”後到達頁面(如圖4所示):

151250852.jpg

圖4 服務頁面

點選左邊的Services,會在中間看到很多的APIs和Services,找到GoogleMaps Android API v2,然後把它設定成on,需要接受一些服務條款,如圖5所示。

151253977.jpg

圖5 開啟的服務頁面

之後跳轉到頁面,如圖6所示:

151255544.jpg

圖6 同意條款

勾選同意條款,單擊接受按鈕。

5)獲得API Key

在左邊的導航條中選擇API Access(如圖7)。


151257162.jpg

圖7 導航欄

在出來的頁面中選擇Create New Android Key...就可以生成key了(如圖8所示)

151305346.jpg

圖8 生成Key

然後在對話方塊中填入:SHA-1 指紋,分號隔開,然後是應用的 package name.然後就會生成一個Key,如圖9所示。151308140.jpg9 生成自己的Key操作圖

最後生成的API Key如圖10所示:

151310143.jpg

10 生成的API Key

步驟二:

把API Key加入應用程式。

1)首先,新建Android應用程式。建立應用程式時,注意包名應該和申請key時候的包名一致。

2)之後修改AndroidManifest.xml檔案,在<application>元素中加入子標籤

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

注:其中your_api_key置換成自己申請的API Key。

在該檔案中加入一些許可資訊,允許必要的許可權。

<permission
    android:name="com.example.mapdemo.permission.MAPS_RECEIVE"
    android:protectionLevel="signature"/>
<uses-permission
    android:name="com.example.mapdemo.permission.MAPS_RECEIVE"/>

注:其中com.example.mapdemo換成自己的包名。

步驟三:


AndroidManifest.xml檔案中的其他的選項設定。

1)許可設定

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GSERVICE S"/>
<uses-permission
    android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission
    android:name="android.permission.ACCESS_FINE_LOCATION"/>

2)OpenGL ES V2特性支援(作為<manifest> 的子元素)

<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>

步驟


在佈局檔案中加上地圖。

<fragment xmlns:android=http://schemas.android.com/apk/res/android
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment"/>

遇到的問題和解決的方法。

程式編譯錯誤,顯示找不到一些類,如圖11所示。

151312459.jpg

11 錯誤提示資訊


解決這個問題,首先需要把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。

新增對這個庫的引用在自己的專案上右鍵,選Properties,左邊選Android,然後在下面的Library裡面Add剛才的google-play-services_lib,如圖12所示。

151316157.jpg

12 引用類庫步驟圖

之後執行程式就應該出來地圖了。執行過程中,有可能會碰到下面的問題:程式執行成功,但是顯示This app won't run unlessyou update Google Play services,如圖13所示。需要點選Update,按照提示操作。

151318656.jpg

13 提示介面

之後執行程式,就出地圖了,如14所示。151321922.jpg

圖14 執行結果圖

注:

因為MapFragment只在API 12及之後的版本才有,所以對於之前的版本需要使用Support Library來進行輔助。

如果minSdkVersion設定為12以前的,就需要使用Support Library

需要更改的地方是:佈局檔案中,把MapFragment改為SupportMapFragment。

MainActivity繼承自FragmentActivity而不是Activity。(需要import android.support.v4. app.FragmentActivity;)。

步驟


新建工程GoogleMapTest,包名為com.example.googlemaptest,將一張名為pos.png的圖片匯入到drawable目錄下,用於標註當前的位置。專案中Activity的名字為MainActivity.java,對應的佈局檔名字為activity_main.xml,佈局檔案中包括2個輸入框,用於接收使用者輸入的經緯度資訊,有1個按鈕,用於根據使用者輸入的經緯度定位具體位置;有兩個單選按鈕,分別顯示普通地圖和衛星地圖;有1個地圖元件。該工程目錄結構及佈局檔案介面如圖15所示:

151215166.jpg

15 工程目錄結構圖

步驟


編輯地圖元件對應的佈局檔案googlemap.xml,主要程式碼如下。

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment"
map:cameraBearing="45"
map:cameraTargetLat="25.033611"
map:cameraTargetLng="121.565000"
map:cameraTilt="0"
map:cameraZoom="13"
map:uiCompass="true"
map:mapType="normal"
map:uiRotateGestures="true"
map:uiScrollGestures="true"
map:uiTiltGestures="true"
map:uiZoomControls="false"
map:uiZoomGestures="true" />

注:此檔案中,class屬性以下的幾行程式碼,是用於設定地圖的一些屬性,這部分內容不是必須的,可以根據自己的需要進行設定,也可以都不設定,而在Activity中使用程式碼進行設定。

當在XML檔案中加入這些map屬性的設定時,必須要新增名稱空間:xmlns:map="http://schemas.android.com/apk/res-auto",並且該XML檔案中不能再加入其它的元件,例如編輯框,甚至不能為其新增容器,例如LinearLayout。如果設定了這些屬性,並且還想新增其它元件,就需要將該XML檔案作為主XML佈局檔案的一部分,通過<include>標籤包含在主佈局檔案中。具體方法稍後具體說明。

如果不在XML檔案中設定這些map屬性的話,該XML檔案可以不新增名稱空間,並且可以在此檔案中新增其它的元件。

步驟

編寫主佈局檔案:activity_main.xml,採用線性佈局並將上面的地圖元件對應的XML檔案(googlemap.xml)包含進來。

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
    android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="定位"
android:textSize="15sp" />
<LinearLayout
    android:id="@+id/location"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >
<!-- 定義輸入經度值的文字框 -->
<EditText
        android:id="@+id/edt_lng"
    android:layout_width="wrap_content"
android:layout_height="wrap_content"
        android:ems="6"
            android:hint="經度"
android:textSize="20sp" />
<!-- 定義輸入緯度值的文字框 -->
<EditText
android:id="@+id/edt_lat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:ems="6"
android:hint="緯度"
android:textSize="20sp" />
<Button
android:id="@+id/btn_loc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="定位"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/mapsChoice"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<!-- 定義選擇地圖型別的單選按鈕 -->
<RadioGroup
    android:id="@+id/rg_mapType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal" >
<RadioButton
android:id="@+id/rb_nomal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="普通檢視" />
 <RadioButton
android:id="@+id/rb_satellite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="衛星檢視" />
</RadioGroup>
</LinearLayout>
</LinearLayout>
<include android:id="@+id/googleMap"
layout="@layout/googlemap" />

步驟

編寫Activity檔案,MainActivity.java

宣告各元件及必要的類。

//定義介面上的視覺化元件
private Button btn_loc;
private EditText edt_lng, edt_lat;
private RadioGroup rg_mapType;
GoogleMap mMap;
private CameraPosition cameraPosition;
private MarkerOptions markerOpt;
//定義LocationManager物件
private LocationManager locManager;
private Location location;
private String bestProvider;

在onCreate()方法中獲取各元件,並給按鈕註冊事件監聽器,實現地理位置的實時定位。

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//獲取使用者介面的元件
findViews();
//建立LocationManager物件,並獲取Provider
initProvider();
//取得地圖元件
mMap = ((MapFragment)getFragmentManager()
.findFragmentById(R.id.mapView)).getMap();
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//更新位置資訊
updateToNewLocation(location);
//給按鈕新增監聽器
btn_loc.setOnClickListener(new MapClickedListener());
//為RadioGroup的選中狀態改變新增監聽器
rg_mapType.setOnCheckedChangeListener(new ChangeMapTypeListener());
// 設定監聽器,自動更新的最小時間為間隔N秒(1秒為1*1000,這樣寫主要為了方便)或最小位移變化超過N
locManager.requestLocationUpdates(bestProvider,  3 * 1000, 8
, new LocationListener() {       
//當Provider的狀態改變時
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
// 當GPS LocationProvider可用時,更新位置
location = locManager.getLastKnownLocation(provider);
}
@Override
public void onProviderDisabled(String provider) {
updateToNewLocation(null);
}
@Override
public void onLocationChanged(Location location) {
// 當GPS定位資訊發生改變時,更新位置
        updateToNewLocation(location);
}
});
}
private void initProvider() {
//建立LocationManager物件
locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// List all providers:
List<String> providers = locManager.getAllProviders();
Criteria criteria = new Criteria();
bestProvider = locManager.getBestProvider(criteria, false);
location = locManager.getLastKnownLocation(bestProvider);
System.out.println("經度:"+location.getLatitude()+"緯度:" + location.getLongitude());
}
//獲取使用者介面元件
private void findViews() {
//獲取介面上的兩個按鈕
btn_loc = (Button) findViewById(R.id.btn_loc);
//獲取介面上的兩個文字框
edt_lng = (EditText) findViewById(R.id.edt_lng);
edt_lat = (EditText) findViewById(R.id.edt_lat);
//獲得RadioGroup
rg_mapType = (RadioGroup) findViewById(R.id.rg_mapType);
}

實現各個事件監聽器類。

//定位按鈕的點選事件監聽器
private class MapClickedListener implements OnClickListener{
//根據使用者輸入經緯度定位
@Override
public void onClick(View v) {            
        //獲取使用者輸入的經緯度
        String lng = edt_lng.getText().toString().trim();
        String lat = edt_lat.getEditableText().toString().trim();
        if(lng.equals("") || lat.equals("")){
        Toast.makeText(getApplicationContext(), "請輸入有效的經緯度資訊!
", Toast.LENGTH_LONG).show();
            location = locManager.getLastKnownLocation(bestProvider);
            updateToNewLocation(location);
}else{
        location.setLongitude(Double.parseDouble(lng));
        location.setLatitude(Double.parseDouble(lat));
        //呼叫方法更新地圖定位資訊
        updateToNewLocation(location);
}
}
}
private class ChangeMapTypeListener implements OnCheckedChangeListener{
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch(checkedId){       
        case R.id.rb_nomal://如果勾選的是"正常檢視"的單選按鈕
                mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;
            case R.id.rb_satellite://如果勾選的是"衛星檢視"的單選按鈕
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;
        }
}
}

實現更新位置資訊的方法。

private void updateToNewLocation(Location location){
mMap.clear();
//Marker1
markerOpt = new MarkerOptions();
double dLong = 114.51500;
double dLat = 38.042000;
if(location != null){
    //獲取經度
    dLong = location.getLongitude();
    //獲取緯度
    dLat = location.getLatitude();
}
markerOpt.position(new LatLng(dLat, dLong));
    markerOpt.draggable(false);
    markerOpt.visible(true);
    markerOpt.anchor(0.5f, 0.5f);//設為圖片中心
    markerOpt.icon(BitmapDescriptorFactory.fromResource(R.drawable.pos));
    mMap.addMarker(markerOpt);
    //將攝影機移動到指定的地理位置
    cameraPosition = new CameraPosition.Builder()
            .target(new LatLng(dLat, dLong))
            .zoom(15) // 縮放比例
            .bearing(0) // Sets the orientation of the camera to east
            .tilt(30)  // Sets the tilt of the camera to 30 degrees
            .build();// Creates a CameraPosition from the builder
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}

步驟

編輯AndroidManifest.xml,需要新增必要的許可權及所申請的API Key

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   …  >
    <uses-sdk
       … />
    <!—下面的許可權中,com.example.googlemaptest 要換成你的工程檔案的包名-->
    <permission android:name="com.example.googlemaptest.permission.MAPS_RECEIVE"
        android:protectionLevel="signature"/>
<uses-permission
android:name="com.example.googlemaptest.permission.MAPS_RECEIVE"/>
    <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"/>
<!—下面的兩條許可權在API V2中是不要求的,但是在開發過程中建議新增 -->
    <uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true"/>
    <application
        … >
        <activity
            android:name="com.example.googlemaptest.MainActivity"
…
        </activity>
        <meta-data android:name="com.google.android.maps.v2.API_KEY"
<!—下面的屬性值要求新增你申請的API Key值-->
            android:value="你申請的API Key值 " />
        <uses-library android:required="true"
                android:name="com.google.android.maps" />
    </application>
</manifest>

步驟

執行改專案,測試定位功能。

注:由於本專案提取歷史定位資料,所以首次使用,在沒有歷史資料的情況下會閃退,這是因為第一次獲取GPS的時候沒有歷史資料,location = locManager.getLastKnownLocation(provider)這條語句獲取不到歷史資料造成的,常見的解決辦法有如下幾種:

1. 迴圈獲取定位資料,直到獲取到經緯度為止。該方法的缺點是獲取不到資料時會進入死迴圈。

while(location  == null){
    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 1, new LocListener()); 
}

2. 優先採用NETWORK_PROVIDER,該Provider比GPS_PROVIDER的穩定性好。

3. 讀取定位資料之前,先讓程式獲取定位資料,給程式預留一定的時間,因為定位資料不一定一次性獲取成功,這和位置、手機軟硬體有關。

4. 偷懶的方法是使用其他的軟體如百度地圖,首先獲取到定位資料,有歷史資料了以後再執行該程式。

5. 在程式中給定初始化的經緯度資料。


附錄:

新版本中對於已申請的API Key可以服務於多個包,直接新增就可以了。

新版本的谷歌開發網左側的列表中,點選APIs & auth下的APIs,會顯示所開啟的服務。

左側的列表如下圖所示

173100165.jpg

點選Credentials列表可申請新的API Key,如下圖示。

173322787.jpg

點選“CREATE NEW KEY”可申請新的Key,點選“Edit allowed Android applications”可編輯已有的API Key,也可使用已有Key,支援更多的服務,如下圖所示。

173611287.jpg

直接在框中新增Key所支援的包名即可,需要注意的是,Key與包名之間要命“;”隔開。之後點選“Update”按鈕。


到此結束,希望對大家有幫助。

以上純屬個人觀點,供新手交流學習。歡迎高手及大神批評指正。

轉載於:https://blog.51cto.com/weiweili/1342861