文章目錄
- 1. main
- 2. Android 谷歌地圖
- 3. 源碼
- Reference
1. main
在國內選擇的SDK可以是高德、百度、騰訊、xxxx等,但在國外,你首選是谷歌,因此要進行Google地圖的開發你首先要解決下面三個問題
VPN
Google賬號
信用卡American Express(美國運通卡)Discover(美國發現卡)JCB(Japan Credit Bureau,日本國際信用卡)MasterCard(萬事達)VISA(維薩)
2. Android 谷歌地圖
https://developers.google.cn/maps/documentation/android-sdk?hl=zh-cn
一、設置Google Cloud 項目二、項目配置① 設置SDK② 配置API密鑰③ 配置AndroidManifest.xml三、添加地圖四、定位當前① 請求定位權限② 我的位置控件③ 獲取當前位置五、配置地圖① xml配置地圖② 代碼配置地圖③ 地圖點擊事件④ 管理Marker六、地址位置編碼① 坐標轉地址② 地址轉坐標七、源碼
3. 源碼
這里zhi貼上GoogleMapActivity的完整代碼:
@SuppressLint("NewApi")
class GoogleMapActivity : AppCompatActivity(), OnMapReadyCallback, Geocoder.GeocodeListener {private lateinit var binding: ActivityGoogleMapBinding// 地圖private lateinit var map: GoogleMap// Places API 的入口點。private lateinit var placesClient: PlacesClient// 融合位置信息提供程序的入口點。private lateinit var fusedLocationProviderClient: FusedLocationProviderClient// 最后已知位置private var lastKnownLocation: Location? = null// 標記private var marker: Marker? = null// 地理編碼器private var geocoder: Geocoder? = null// 地址結果private var addressesLiveData: MutableLiveData<List<Address>> = MutableLiveData()companion object {private val TAG = GoogleMapActivity::class.java.simpleName// 默認縮放private const val DEFAULT_ZOOM = 15// 權限請求碼private const val LOCATION_PERMISSION_REQUEST_CODE = 9527// 未授予位置權限時使用的默認位置(澳大利亞悉尼)和默認縮放。private val defaultLocation = LatLng(-33.8523341, 151.2106085)}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()binding = ActivityGoogleMapBinding.inflate(layoutInflater)setContentView(binding.root)ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)insets}initView()}/*** 初始化視圖*/private fun initView() {// 構造 PlacesClientPlaces.initialize(applicationContext, BuildConfig.MAPS_API_KEY)placesClient = Places.createClient(this)// 構造 FusedLocationProviderClient。fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragmentmapFragment.getMapAsync(this)}/*** 檢查權限*/private fun checkPermission() {// 檢查當前是否擁有精確位置或粗略位置權限if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {// 權限已授予,可以進行定位操作Log.d(TAG, "checkPermission: 權限已授予")configMap()} else {Log.d(TAG, "checkPermission: 請求權限")// 請求權限ActivityCompat.requestPermissions(this,arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION),LOCATION_PERMISSION_REQUEST_CODE)}}/*** 地圖就緒*/override fun onMapReady(googleMap: GoogleMap) {map = googleMap// 檢查權限checkPermission()}/*** 地圖配置*/@SuppressLint("MissingPermission")private fun configMap() {Log.d(TAG, "configMap: 地圖配置")// 初始化地理編碼器geocoder = Geocoder(this)// 編碼結果addressesLiveData.observe(this) { addresses ->// 獲取地址信息if (!addresses.isNullOrEmpty()) {val address = addresses[0]Log.d(TAG, "Address: ${address.latitude} ${address.longitude} ${address.countryName} ${address.adminArea} ${address.locality} ${address.thoroughfare} ${address.subThoroughfare}")}}map.apply {isMyLocationEnabled = true // 地圖上啟用“我的位置”圖層// 當前位置圖標的點擊事件setOnMyLocationButtonClickListener {Log.d(TAG, "configMap: 點擊位置圖標")// 移除標點marker?.remove()marker = nullreturn@setOnMyLocationButtonClickListener false}// 定位后的藍點點擊事件setOnMyLocationClickListener { location ->Log.d(TAG, "configMap: 點擊我的位置 $location")Toast.makeText(this@GoogleMapActivity, "Current location:\n$location", Toast.LENGTH_LONG).show()}// 地圖點擊事件setOnMapClickListener { latLng ->changeMapCenter(latLng)}// 地圖設置uiSettings.apply {isZoomControlsEnabled = true // 顯示縮放按鈕isMyLocationButtonEnabled = true // 顯示定位按鈕isCompassEnabled = true // 顯示指南針isMapToolbarEnabled = true // 顯示地圖工具欄isRotateGesturesEnabled = true // 允許旋轉手勢isScrollGesturesEnabled = true // 允許滾動手勢isTiltGesturesEnabled = true // 允許傾斜手勢isZoomGesturesEnabled = true // 允許縮放手勢isScrollGesturesEnabledDuringRotateOrZoom = true // 允許在旋轉或縮放時滾動手勢isIndoorLevelPickerEnabled = true // 顯示室內層選擇器}}// 獲取當前位置getCurrentLocation()}/*** 獲取當前位置*/@SuppressLint("MissingPermission")private fun getCurrentLocation() {Log.d(TAG, "getCurrentLocation: 獲取當前位置")fusedLocationProviderClient.lastLocation.addOnCompleteListener { task ->// 獲取當前位置未成功if (!task.isSuccessful) {Log.d(TAG, "Current location is null. Using defaults.")Log.e(TAG, "Exception: %s", task.exception)// 設置默認位置changeMapCenter(defaultLocation)return@addOnCompleteListener}lastKnownLocation = task.resultif (lastKnownLocation == null) return@addOnCompleteListener// 移動地圖到當前位置changeMapCenter(LatLng(lastKnownLocation!!.latitude, lastKnownLocation!!.longitude))}}/*** 改變地圖中心*/private fun changeMapCenter(latLng: LatLng) {// 移除標點marker?.remove()// 添加標點marker = map.addMarker(MarkerOptions().title("Marker") // 設置標題.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_google)) // 設置自定義圖標.alpha(0.7f) // 設置透明度.position(latLng) // 設置位置)// 獲取詳細位置信息// getDetailAddress(latLng)// 獲取默認經緯度的地址信息getDetailLatLng()// 地圖中移動到經緯度處map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM.toFloat()))}/*** 獲取默認經緯度的地址信息*/private fun getDetailLatLng(address: String = "悉尼歌劇院") {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {geocoder?.getFromLocationName(address, 1, this@GoogleMapActivity)} else {addressesLiveData.postValue(geocoder?.getFromLocationName(address, 1))}}/*** 獲取詳情位置信息,獲取國內位置會出現異常*/private fun getDetailAddress(latLng: LatLng) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {geocoder?.getFromLocation(latLng.latitude, latLng.longitude, 1, this@GoogleMapActivity)} else {addressesLiveData.postValue(geocoder?.getFromLocation(latLng.latitude, latLng.longitude, 1))}}/*** 權限請求結果*/override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {LOCATION_PERMISSION_REQUEST_CODE -> {// 如果請求被取消,則結果數組為空if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 權限被授予,可以進行定位操作Log.d(TAG, "onRequestPermissionsResult: 權限被授予")configMap()} else {// 權限被拒絕,無法進行定位操作Log.d(TAG, "onRequestPermissionsResult: 權限被拒絕")Toast.makeText(this, "拒絕將無法使用定位功能", Toast.LENGTH_SHORT).show()finish()}}}}/*** 地理編碼結果,經緯度坐標轉地址*/override fun onGeocode(addresses: MutableList<Address>) {addressesLiveData.postValue(addresses)}
}
Reference
https://blog.csdn.net/qq_38436214/article/details/140985527
https://developers.google.cn/maps/documentation/android-sdk?hl=zh-cn