到了第五天,終於要來動動手了。
本次練習都是使用 Android Studio 的最新版本 Giraffe。
文章中對於 Android Studio 的安裝流程就不多做介紹,細節可以參考 官方的安裝教學,或是 iThome 社群上諸多大神們的分享。
基本上照著安裝指示走,遇到不確定的設定稍微看一下文件或是 Google 一下,應該都可以解決。
如果你在安裝上有遇到問題,歡迎留言討論~
如果你已經安裝完畢,也開啟了一個新的專案,請在以下檔案中加入這些相依設定。
settings.gradle.kts
檢查 setting.gradle.kts
內有無以下的設定值
pluginManagement {
repositories {
google() // 這個
mavenCentral() // 這個
gradlePluginPortal() // 這個
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
build.gradle
(app)要使用 Google Maps 的 SDK,compileSdk
必須大於 API 31,minSdk
必須大於 API 19。最後在 depedencies
block 中加入以下的 implementation
。
implementation("com.google.android.gms:play-services-maps:18.1.0")
大概是會長這樣。
android {
// 必須大於 31
compileSdk = 33
defaultConfig {
// 必須大於 19
minSdk = 26
// 略...
}
// 略...
}
dependencies {
// 略...
// 加入 Google Maps SDK
implementation("com.google.android.gms:play-services-maps:18.1.0")
}
以上設定調整完後,請根據 IDE 的提示將專案 Sync,確認套件相依都沒有問題,沒有出現 Build Errors。
如果你是創立新的專案,而且 Google Maps 是要建立在一個新的 Activity
,那可以使用 Android Studio 的新增功能,IDE 將會自動把缺少的套件設定補上。
當然你也可以透過這個方法做好套件設定後,在把用不到的 Google Maps View Activity 刪除,另外自己實作 Google Maps。
到這一步,我們已經完成了基本的環境建置,現在就讓我們實際建立一個帶有 MapView
的 Activity
,看看能不能成功的把地圖開起來。
MapView
的 Activity
如果是前面用偷吃步的方法建立,這個步驟可以直接省略,直接將 App build 起來看看有沒有看到地圖。
如果是跟我一樣只有設定好 implementation
的朋友,可以跟著我繼續做下去。
這裡用的方式,有別於官方範例是使用 SupportMapFragment
,而是改用 MapView
。
至於為什麼我要用 MapView
建立呢?
因為 SupportMapFragment
已經有範例可看了,當然寫點不一樣的囉XD
因為在小弟的開發實務上,常遇到 MapView
的寫法,想說就用這個來當範例,跟還不知道的人分享~
首先建立一個 Empty Activity
並在對應的 layout XML 中加入一個 MapView
。
activity_map_view.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity">
<com.google.android.gms.maps.MapView
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MapViewActivity
設定好 Layout,讓我們回到 MapViewActivity
。
使用 ViewBinding 取得 RootView
,與其底下的 MapView
。
(如果你是使用 findViewById()
其實也是一樣,只要能拿到 XML 上的那個 MapView
就可以了。)
取得 MapView
後,在分別 override
Activity
的生命週期方法,並在裡面呼叫 MapView
相同名稱的方法。
onCreate()
onStart()
onResume()
onPause()
onStop()
onDestroy()
onSaveInstanceState()
onLowMemory()
以上這幾個方法,都是實作 MapView 時必須在對應的生命週期中呼叫的方法。
那為什麼 SupportMapsFragment 不用?
這是因為在 SupportMapsFragment
中,其類別已經幫你做好 MapView
的生命週期控管,所以不用額外呼叫這些方法。SupportMapsFragment
是將 Google Maps 加入到 App 中,最簡單的方式。
以下是我寫的範例程式碼,給各位參考~
package tw.dh46.ithome23.sample
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import tw.dh46.ithome23.sample.databinding.ActivityMapsBinding
class MapsActivity : AppCompatActivity() {
private val TAG: String = MapsActivity::class.java.simpleName
private val binding: ActivityMapsBinding by lazy {
ActivityMapsBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.mapView.onCreate(savedInstanceState)
binding.mapView.getMapAsync {
Log.d(TAG, "onCreate: ")
}
}
override fun onStart() {
super.onStart()
binding.mapView.onStart()
}
override fun onResume() {
super.onResume()
binding.mapView.onResume()
}
override fun onPause() {
super.onPause()
binding.mapView.onPause()
}
override fun onStop() {
super.onStop()
binding.mapView.onStop()
}
override fun onDestroy() {
super.onDestroy()
binding.mapView.onDestroy()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.mapView.onSaveInstanceState(outState)
}
override fun onLowMemory() {
super.onLowMemory()
binding.mapView.onLowMemory()
}
}
好不容易寫完,那就來跑跑看吧!
這時候 Build 起來,你應該會跟我一樣,發現 App crash 了,並在 Logcat 看到一堆紅字錯誤。
但就如同前輩們常說的,Logcat 看得到紅字錯誤都還算是好事,至少有一個好除錯的起點。
FATAL EXCEPTION: main
Process: tw.dh46.ithome23.sample, PID: 7357
java.lang.RuntimeException: Unable to start activity
ComponentInfo{tw.dh46.ithome23.sample/tw.dh46.ithome23.sample.MapsActivity}: java.lang.RuntimeException: API key not found.
Check that <meta-data
android:name="com.google.android.geo.API_KEY" android:value="your APIkey"/>
is in the <application> element of AndroidManifest.xml
仔細閱讀了一下錯誤訊息,發現它寫的很直白,就是 SDK 在 AndroidManifest.xml
中找不到他要的 API KEY。
AndroidManifest.xml
中的 Google Play 服務版本號設定根據文件的說法,在 AndroidManifest.xml
的宣告中,應該要再加入以下的 tag。
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
但根據我的測試,其實不加也沒有關係,因為在 Merged 的 Manifest 中,IDE 依然有把這個 tag 給加進來,所以應該是不影響~
好的,以上這就是今天的內容。
雖然 SDK 的使用不用收費,但還是要申請 API Key,這部分我們就明天再繼續吧~
明天見!!