這次做一個地圖應用,通過 Google Map 顯示自己的位置以及對應的座標。
功能
- 在首頁提供一個按鈕,點下去會檢查有沒有使用定位功能的權限。
- 如果沒有權限,則跳出請求。
- 如果有權限,則進入 MapsActivity
- 進入 MapsActivity 取得使用者的 location,將地圖移動並且放大到當前位置。
- 將使用者的座標顯示在畫面上。
接觸的內容
- Google Map
- Location Manager & Permission
- Intent 跳轉 Activity
通過 IDE 建立 MapActivity
iOS 可以通過 Cocoapod 等依賴包管理工具引入 Google Map,而 Android 可以直接通過 IDE.
通過在 App 上右鍵的方式建立一個 Activity,點開 Gallery 以後會看到 Google Maps Activity。
IDE 會同時幫我們建立一個 Activity 以及一個對應的 Layout。
而 IDE 同時還會建立一個 google_maps_api.xml 文件,這裡面會需要寫上我們的 Google Map 金鑰。
我在 Github 上有看到一些人是將 key 放在 /values/strings/ 底下,又或者在 values 下另外建立文件來使用。
1 |
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">Your Google API Key</string> |
而在 AndroidManifest.xml 文件中,IDE 也幫我們加了一些東西,比如:
1 2 3 4 5 6 7 |
<meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" /> <activity android:name=".MapsActivity" android:label="@string/title_activity_maps" /> |
這裡發現 google_maps_key 又或者 MapsActivity 的 title 都是通過 @string/key 的方式來引用。
1 2 3 4 5 |
<resources> <string name="app_name">MyLocation</string> <string name="title_activity_maps">Map</string> <string name="title_activity_map">Map</string> </resources> |
@string/key 的內容部分是來自下圖中的 strings.xml
通過 Intent 切換 Activity
在 Android 中,可以通過 Intent 來切換 Activity。
1 2 |
val intentMapActivity = Intent(this, MapsActivity::class.java) startActivity(intentMapActivity) |
Permission
這次會用到定位的權限,需要在 AndroidManifest 加入:
1 |
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
檢查與請求權限
- ContextCompat.checkSelfPermission 檢查使用權限。
- ActivityCompat.requestPermissions – 請求權限。
在請求使用權限的時候還可以加入一個參數之後用來判斷是哪一種請求。
1 2 3 4 |
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), MY_PERMISSIONS_REQUEST_LOCATION) } |
請求結果的 Handler
1 2 3 4 5 6 7 8 9 10 |
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray){ if (requestCode == MY_PERMISSIONS_REQUEST_LOCATION) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED){ showMapsActivity() } else { Toast.makeText(this, "需要定位功能", Toast.LENGTH_SHORT).show() } } } |
LocationManager
我們實例化一個 locationManager 並且嘗試獲取用戶當前位置,並委派一個 locationListener。
1 2 3 4 5 6 7 8 9 |
// Create persistent LocationManager reference locationManager = getSystemService(LOCATION_SERVICE) as LocationManager? try { // Request location updates locationManager?.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0L, 0f, locationListener) } catch(ex: SecurityException) { Log.d("myTag", "Security Exception, no location available") } |
locationListener
在取得座標的時候,將地圖移動到座標所在位置,並且將座標顯示在 locationTextView 上。
1 2 3 4 5 6 7 8 9 10 11 |
private val locationListener: LocationListener = object : LocationListener { override fun onLocationChanged(location: Location) { mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location.latitude, location.longitude), 12.0f)) locationTextView.text = "${location.latitude} - ${location.longitude}" } override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {} override fun onProviderEnabled(provider: String) {} override fun onProviderDisabled(provider: String) {} } |
筆記
- /src/debug/res/values/google_maps_api.xml 這個文件在 IDE 中,是在哪裡寫了引用?
以至於 AndroidManifest.xml 可以直接使用? - 在 onMapReady() 方法上,IDE建議我加入 @SuppressLint(“MissingPermission”)
不知道這個作用是什麼,提示我在 function 中加入權限判斷?
參考
- 官方文件 – GoogleMap
- 官方文件 – LocationManager
- 可以到 Github 上看對應的 SourceCode