Android 的 Mapview & Location 使用教程
本教程將探討如何使用谷歌地圖API來顯示出信息點(POI),并使用手機提供的定位服務,來顯示當前位置可搜索到的POI位置。這種情況下,我們應使用商場作為POI。
我把教程分為了兩部分。
第一部分(在本節中)將介紹包括:
1.MapView對象的使用
2.使用MD5密文獲取一個谷歌地圖API密鑰
3.實現一個地點監聽器,以獲得你的當前位置
第二部分將包括:
1.在應用程序中使用外部庫類
2.創建顯示出你的當前位置和周邊的信息點
現在讓我們開始吧!
步驟1:創建一個新的Android項目
啟動Eclipse IDE并創建一個新的Android項目。
File > Create > New Android Project
使用以下設置創建新的項目:
項目名稱:MallFinder
生成目標:Google APIs Platform–2.1 API Level 7
應用程序名:Mall Finder
包名稱:com.shawnbe.mallfinder
創建Activity:MallFinderActivity
最低SDK版本:7
步驟2:在谷歌上注冊獲取API密鑰
因為MapView對象使用谷歌地圖,你需要在谷歌注冊一個API密鑰,并同意服務條款,然后才可以使用他們。注冊過程相當簡單。想要了解更多關于獲得地圖API密鑰信息,請查看此鏈接。
要對你的應用程序進行簽名就必須要用到的MD5密文生成的API秘鑰,聽起來很令人困惑,但它并不難,因為你會發現它像當我們之前的幾個步驟 。而不是上面的鏈接所述,使用命令行的方式得到你的MD5密文,我們將使用keytool的一個Eclipse插件 。想要了解更多有關keytool的插件信息,請查看此鏈接。
步驟3:安裝keytool插件
在Eclipse IDE中,導航到 Help > Install New Software。
當新的窗口彈出,在窗口的頂部點擊“Add”按鈕。
在“Name”欄輸入“keytool”(不含引號),
在“Location”欄輸入“http://www.keytool.sourceforge.net/update”
點擊“OK”。
經過短暫的加載時間,窗口將出現一個標有“keytool”的復選框。選中該復選框并單擊“下一步”。同意協議的條款,然后單擊“下一步”完成。
注意:在安裝過程中,可能會提示您確定是否信任安全證書。如果你確定,就選中復選框并單擊“確定”繼續安裝。
安裝完成后,將會提示重新啟動Eclipse。
步驟4:獲取MD5密文
Eclipse重新啟動之后,你應該看到一個新的菜單項“keytool”,它旁邊有一個小鑰匙圖標。
我們現在要打開調試的keystore。
注意:由于操作系統的位置可能會有所不同。各種操作系統的默認位置:
- Windows Vista : C:\Users\
\.android\debug.keystore - Windows XP : C:\Documents and Settings\
\.android\debug.keystore - OS X and Linux : ~/.android/debug.keystore
點擊keytool菜單項>打開密鑰庫。
點擊位于“文件名”文本框右側的“瀏覽”按鈕,并找到keystore的位置(上述為默認位置),并選擇debug.keystore文件。
現在應該在屏幕底部的面板可見一個新的keytool的標簽(如果你沒有看到它,導航到“Window > Open Perspective > Java Browsing”)。
點擊debug.keystore路徑左側的小箭頭將顯示androiddebugkey。
雙擊androiddubugkey并復制MD5密文。
打開Web瀏覽器,進入以下網址。 http://code.google.com/android/maps-api-signup.html
閱讀并同意條款,在文本框中輸入MD5密文,并點擊“Generate API Key”。請注意保存好你的API密鑰,因為使用MapView的時候需要它。
步驟5:在布局中添加MapView
在這一步,我們將添加一個MapView到布局文件。
打開位于MallFinder > res > layout> main.xml中的main.xml文件,并修改該文件如下所示,包括一個FrameLayout和MapView:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.google.android.maps.MapView android:id="@+id/mapView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="PUT YOUR API KEY HERE"/> </FrameLayout> </LinearLayout>
上述布局在整個可用的屏幕空間創建一個MapView。在當前狀態下運行的應用程序,將導致在強制關閉。我們還需要完成多個步驟。
步驟6:設置權限,并導入所需的庫
由于我們的應用程序將會從Google Maps下載數據,同時需要從手機的GPS或其他定位服務訪問信息,所以我們需要在AndroidManifest文件中的聲明必要的權限來使用這些服務。
要做到這一點,打開位于MallFinder > AndroidManifest.xml中的AndroidManifest.xml文件。
在關閉應用程序標記(</application>)后面,和在閉幕清單標記(</manifest>)之前添加以下幾行。
<uses-feature android:name="android.hardware.location.gps"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.INTERNET"/>
在這個例子中,我不需要FINE_LOCATION,但我已經包含在此,我想你可能要調整你的代碼來測試各種提供商,如果你想獲得更準確的位置,你將需要FINE_LOCATION權限。通常任何生產中的應用程序都不應該聲明不需要的權限。如你要求更多的權限,這是一個非常糟糕的做法,使用戶警惕你的應用程序。如果你不打算使用更準確的供應商,你可以不聲明android.permission.ACCESS_COARSE_LOCATION。
為了在我們的MapView中使用谷歌地圖,我們需要在Manifest文件中聲明該庫,這樣我們要在關閉活動標記和關閉應用程序標記代碼之間加入下面的標簽:
<uses-library android:required="true" android:name="com.google.android.maps" />
android:theme="@android:style/Theme.NoTitleBar"
現在我們完整的Manifest文件看起來像這樣:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.shawnbe.mallfinder" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar"> <activity android:label="@string/app_name" android:name=".MallFinderActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <uses-library android:required="true" android:name="com.google.android.maps" /> </application> <uses-feature android:name="android.hardware.location.gps"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.INTERNET"/> </manifest>
步驟7:設置MapView
在我們運行MapView之前,我們還需要做一些MallFinderActivity類的調整。
打開的主要活動類(MallFinderActivity.java),這是位于:MallFinder > src > com.shawnbe.mallfinder > MallFinderActivity.java
在我們的應用程序中,我們需要將這個類繼承“MapActivity”,而不是“Activity”。
修改行:
public class MallFinderActivity extends Activity {
改成:
public class MallFinderActivity extends MapActivity {
繼承MapActivity類時,我們需要實現isRouteDisplayed()
方法,所以我們需要添加下面的方法 :
@Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; }
這時,我們可以啟動應用程序并顯示MapView,但我們的沒有設置選項,如縮放級別和可見圖層。我們開始在onCreate方法中聲明以下變量:
private MapController mapController; private MapView mapView;
在onCreate
方法中添加以下幾行代碼:
mapView = (MapView)findViewById(R.id.mapView); mapView.setBuiltInZoomControls(true); mapView.setSatellite(false); mapView.setStreetView(true); mapController = mapView.getController(); mapController.setZoom(13);
上面的代碼只顯示街層并隱藏的衛星層。我個人喜好選擇它,因為我覺得在這種情況下更容易讀。正如你喜歡用布爾值false和true來隨意調整一樣。此外,縮放級別設置為13,你也可以調整到1作為整個世界視圖來看和20最大變焦。
最后,我們可以繼續啟動應用程序,以確保一切運行像預期一樣。
有幾種方法來運行應用程序,首先:
在Package Explorer window中右鍵單擊項目 > Run as > Android Application
或者
然后選擇你的手機或模擬器。你應該可以看到一個地圖覆蓋整個屏幕,除了在屏幕上方的通知欄,而且可以滾動并使用縮放。
步驟8:獲取你當前的位置
要獲得你的當前位置,我們使用
locationManager類,它允許應用程序獲取設備的位置。此過程可能需要一些時間來定位當前位置,因此,建議使用你的
lastKnownLocation,直到你可以得到一個更準確的當前的位置。
再聲明以下兩個變量在步驟7中:
private LocationManager locationManager; private GeoPoint currentLocation;
此外,將以下方法添加到MallFinderActivity.java
類:
public void getLastLocation(){ String provider = getBestProvider(); currentLocation = locationManager.getLastKnownLocation(provider); if(currentLocation != null){ setCurrentLocation(currentLocation); } else { Toast.makeText(this, "Location not yet acquired", Toast.LENGTH_LONG).show(); } } public void animateToCurrentLocation(){ if(currentPoint!=null){ mapController.animateTo(currentPoint); } } public String getBestProvider(){ locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setPowerRequirement(Criteria.NO_REQUIREMENT); criteria.setAccuracy(Criteria.NO_REQUIREMENT); String bestProvider = locationManager.getBestProvider(criteria, true); return bestProvider; } public void setCurrentLocation(Location location){ int currLatitude = (int) (location.getLatitude()*1E6); int currLongitude = (int) (location.getLongitude()*1E6); currentLocation = new GeoPoint(currLatitude,currLongitude); currentLocation = new Location(""); currentLocation.setLatitude(currentPoint.getLatitudeE6() / 1e6); currentLocation.setLongitude(currentPoint.getLongitudeE6() / 1e6); }
在onCreate方法中添加以下兩行:
getLastLocation(); animateToCurrentLocation();
onCreate方法現在看起來:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mapView = (MapView)findViewById(R.id.mapView); mapView.setBuiltInZoomControls(true); mapView.setSatellite(false); mapView.setStreetView(true); mapController = mapView.getController(); mapController.setZoom(13); getLastLocation(); animateToCurrentLocation(); }
getLastLocation方法創建的locationManager類的實例,這是基于最好的供應商使用定位服務的要求。在上面的代碼中,我們沒有指定任何條件的供應商,但是你可以根據你的精度和功耗要求的標準來調整使用criteria.setAccuracy()和criteria.setPowerRequirement()方法。上述步驟6中,我提到,你可能需要調整你的標準,以獲得更精確的的位置。如果你想做到這一點,你設置的精度標準ACCURACY_FINE的代碼是:
criteria.setAccuracy(Criteria.ACCURACY_FINE);
我沒有選擇最精確的供應商(GPS)的原因是,因為我在室內測試此代碼,并可能永遠不會得到我位置。如果你能用GPS定位到當前位置,你隨時可以改變準確性在外面測試它。
由于你的手機可能會使用不同的供應商指定的標準,這通常是GPS或網絡(也可以是別的)。如果設置為currentLocation,最后知道的位置至少要等到我們得到了更準確和更新的位置。我們滾動圍繞這些坐標為中心的地圖才能發現當前位置的經度和緯度。
現在我們得到最后一個已知的位置,我們使用位置監聽器來檢測我們的位置變化來更新應用程序。要做到這一點,我們需要我們的類(MallFinderActivity.java)實現locationListener。首先,我們修改行:
public class MallFinderActivity extends MapActivity {
改成:
public class MallFinderActivity extends MapActivity implements LocationListener{
實現地點監聽器,需要我們重寫一組方法,所以我們要添加以下標準方法如下(我指的這些標準方法,實際上并不做任何事情):
@Override public void onLocationChanged(Location arg0) { // TODO Auto-generated method stub } @Override public void onProviderDisabled(String arg0) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String arg0) { // TODO Auto-generated method stub } @Override public void onStatusChanged(String arg0, int arg1, Bundle arg2) { // TODO Auto-generated method stub }
我們將使用onLocationChanged
的方法檢測我們的位置更新,然后使用 setcurrentLocation方法設置為我們當前的位置。
修改onlocationChanged的方法如下:
@Override public void onLocationChanged(Location newLocation) { // TODO Auto-generated method stub setCurrentLocation(newLocation); }
添加以下幾行代碼。這些方法會在每當應用程序啟動或恢復的時候,請求更新;當應用程序被暫停或關閉的同時,也將停止檢查更新。
@Override protected void onResume() { super.onResume(); locationManager.requestLocationUpdates(getBestProvider(), 1000, 1, this); } @Override protected void onPause() { super.onPause(); locationManager.removeUpdates(this); }
如果此時運行的應用程序的MapView應圍繞你最后知道的位置,當你的手機能夠定位,它將會圍繞你的當前位置為中心更新。由于在步驟7設置定位的精確性,得到你的位置時間長度會有所不同。
在這一節中,我們已經學會如何使用的MapView,實現locationListener,并取得你的當前位置。在下一節中,我們將擴展包括使用外部的庫來處理的MapView上信息點的覆蓋和使用氣球彈出窗口顯示一些信息。