iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
1
Mobile Development

程式初學:Android與Kotlin系列 第 23

Day 23--天氣app(九)取得所在位置 part 1

  • 分享至 

  • xImage
  •  

要看天氣的話,理想的操作應該是app打開就可以看到目前所在地的情況

那就需要再來了解一下如何取得手機所在位置
先用一個小專案練習

build.gradle

首先在build.gradle加入

implementation "com.google.android.gms:play-services-location:17.0.0"

AndroidManifest.xml

[取得裝置位置]的權限 https://developers.google.com/maps/documentation/android-sdk/location?hl=zh-tw

  • android.permission.ACCESS_COARSE_LOCATION - 允許 API 使用 Wi-Fi 或行動數據 (或兩者皆有) 判斷裝置的位置。API 傳回的位置準確度大約以城市街區為單位。
  • android.permission.ACCESS_FINE_LOCATION - 允許 API 透過可用的定位服務供應商 (包括全球定位系統 (GPS)) 以及 Wi-Fi 和行動數據,盡可能精確判斷位置
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

因爲須要使用網路取得裝置位置
所以也要加入[取得網路的權限]

<uses-permission android:name="android.permission.INTERNET" />

權限檢查與請求

建立一個檢查是否有提供位置權限的函數

 private fun checkPermission(): Boolean {
        
        if (
            ActivityCompat.checkSelfPermission(
                this,
                android.Manifest.permission.ACCESS_COARSE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED ||
            ActivityCompat.checkSelfPermission(
                this,
                android.Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            return true
        }
        return false
    }

若CheckPermission()回傳沒有提供位置權限,則須要請求權限
建立一個請求權限的函數

var PERMISSION_ID = 1000    //可隨意自訂一個唯一的整數

fun requestPermission(){
        
        ActivityCompat.requestPermissions(
          this,
            arrayOf(android.Manifest.permission.ACCESS_COARSE_LOCATION,android.Manifest.permission.ACCESS_FINE_LOCATION),
            PERMISSION_ID
        )
    }

debug用
可override onRequestPermissionsResult,以查看位置權限的取得狀態

override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        if (requestCode == PERMISSION_ID) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.d("Debug:", "You have the Permission")
            }
        }
    }

檢查位置服務

fun isLocationEnabled():Boolean{
        //this function will return to us the state of the location service
        //if the gps or the network provider is enabled then it will return true otherwise it will return false
        var locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
            LocationManager.NETWORK_PROVIDER)
    }

取得位置

先建立延遲初始的變數

    lateinit var fusedLocationProviderClient: FusedLocationProviderClient
    lateinit var locationRequest: LocationRequest

於onCreate()初始化

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

    }

建立取得最新位置的函數

fun getLastLocation(){
        if(checkPermission()){
            if(isLocationEnabled()){
                fusedLocationProviderClient.lastLocation.addOnCompleteListener {task->
                    var location:Location? = task.result
                    if(location == null){
                        newLocationData()
                    }else{
                        Log.d("Debug:" ,"Your Location:"+ location.longitude)
                        textView.text = "You Current Location is : Long: "+ location.longitude + " , Lat: " + location.latitude + "\n" + getCityName(location.latitude,location.longitude)
                    }
                }
            }else{
                Toast.makeText(this,"Please Turn on Your device Location",Toast.LENGTH_SHORT).show()
            }
        }else{
            requestPermission()
        }
    }
    
    fun newLocationData(){
        var locationRequest =  LocationRequest()
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        locationRequest.interval = 0
        locationRequest.fastestInterval = 0
        locationRequest.numUpdates = 1
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
        fusedLocationProviderClient!!.requestLocationUpdates(
            locationRequest,locationCallback,Looper.myLooper()
        )
    }


    private val locationCallback = object : LocationCallback(){
        override fun onLocationResult(locationResult: LocationResult) {
            var lastLocation: Location = locationResult.lastLocation
            Log.d("Debug:","your last last location: "+ lastLocation.longitude.toString())
            textView.text = "You Last Location is : Long: "+ lastLocation.longitude + " , Lat: " + lastLocation.latitude + "\n" + getCityName(lastLocation.latitude,lastLocation.longitude)
        }
    }

在newLocation()這裡,雖然已做了檢查,編譯器還是有提示錯誤
請教學長說,這樣應該還是可以編譯過,或是照編譯器的提示給annotation忽略這個錯誤@SuppressLint("MissingPermission")

取得城市名稱

前面已經取得位置的經緯度,接着要把這部份轉換爲城市名稱

private fun getCityName(lat: Double, long: Double): String {
        var cityName: String = ""
        var countryName = ""
        var geoCoder = Geocoder(this, Locale.getDefault())
        var Adress = geoCoder.getFromLocation(lat, long, 3)

        cityName = Adress.get(0).adminArea
        countryName = Adress.get(0).countryName
        Log.d("Debug:", "Your City: " + cityName + " ; your Country " + countryName)
        return cityName
    }

Debug用

目前已大致完成,若要檢查app是否有取得位置權限,可覆寫onRequestPermissionsResult,再到logcat查看

override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        if (requestCode == PERMISSION_ID) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.d("Debug:", "You have the Permission")
            }
        }
    }

還有很多詳細的不了解...,不過想要先在天氣app中加入這個功能
先用了再說,之後再研究各部分的用意吧

https://www.itranslater.com/qa/details/2121832870753862656


上一篇
Day 22--天氣app(八)觀察者模式,匿名函數,lambda表示式
下一篇
Day 24--天氣app(十)取得所在位置 part 2
系列文
程式初學:Android與Kotlin30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言