zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

安卓获取当前地理位置(基于GPS和网络)

安卓网络 基于 获取 当前 GPS 地理位置
2023-09-27 14:27:30 时间

背景

安卓开发经常需要获取地理位置,所以对获取地理位置做了下整理,方便大家使用。

解决方案:

  1. Manifest文件添加权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  1. 添加依赖
    implementation "com.google.code.gson:gson:2.8.5"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
    implementation "org.jetbrains.kotlinx:kotlinx
    implementation 'com.afollestad:assent:2.3.1'
  1. 主要代码:
    LocationUtils.kt
object LocationUtils {
    private val TAG = LocationUtils::class.java.simpleName

    /**
     * 获取地理位置,先根据GPS获取,再根据网络获取
     *
     * @return
     */
    @SuppressLint("MissingPermission")
    fun getLocation(context: Context, callback: Callback) {
        val locationListener: LocationListener = getLocationListener(callback)

        try {
            val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
            if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {  //从gps获取经纬度
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0f, locationListener)
            } else {//从网络获取经纬度
                getLocationByNetwork(context, callback)
            }

        } catch (e: Exception) {
            Log.e(TAG, e.message)
        }
    }

    private fun getLocationListener(callback: Callback): LocationListener {
        return object : LocationListener {

            // Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
            override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
                Log.d(TAG, "onStatusChanged")
            }

            // Provider被enable时触发此函数,比如GPS被打开
            override fun onProviderEnabled(provider: String) {
                Log.d(TAG, "onProviderEnabled")

            }

            // Provider被disable时触发此函数,比如GPS被关闭
            override fun onProviderDisabled(provider: String) {
                Log.d(TAG, "onProviderDisabled")

            }

            //当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
            override fun onLocationChanged(location: Location) {
                callback.onLocationChanged(location)
            }
        }
    }

    /**
     * 判断是否开启了GPS或网络定位开关
     *
     * @return
     */
    fun isLocationProviderEnabled(context: Context): Boolean {
        var result = false
        val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
                || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
            result = true
        }
        return result
    }

    /**
     * 获取地理位置,先根据GPS获取,再根据网络获取
     *
     * @return
     */
    @SuppressLint("MissingPermission")
    private fun getLocationByNetwork(context: Context, callback: Callback) {
        val locationListener: LocationListener = getLocationListener(callback)

        val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        try {
            if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f, locationListener)
            }
        } catch (e: Exception) {
            Log.e(TAG, e.message)
        }
    }
}

interface Callback {
    fun onLocationChanged(location: Location)
}

调用样例(Kotlin):

class MainActivity : AppCompatActivity() {

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

    private fun locate() {
        locationTv.text = ""
        runWithPermissions(Permission.ACCESS_FINE_LOCATION) {
            if (LocationUtils.isLocationProviderEnabled(this@MainActivity)) {
                progressBar.visibility = VISIBLE
                showLocationWithToast()
            } else {
                showAlert("本应用需要获取地理位置,请打开获取位置的开关", this)
            }
        }
    }

    private fun showLocationWithToast() {
        LocationUtils.getLocation(this@MainActivity, object : Callback {
            override fun onLocationChanged(location: Location) {
                onGetLocation(location)
            }
        })
    }

    private fun onGetLocation(location: Location) {
        GlobalScope.launch(Dispatchers.IO) {
            val result = getAddressInfo(location)
            launch(Dispatchers.Main) {
                result?.let {
                    locationTv.text = it.toString()
                    progressBar.visibility = GONE
                }
            }
        }
    }
}

备注

  1. 上面代码中使用了第三方库assent来动态申请权限
  2. 采用了coroutines来执行异步任务
  3. 采用了百度web api来根据地理位置查询地址信息(ak需要自己申请)
    效果图:

Demo源代码

https://gitee.com/hspbc/geolocationDemo/tree/master/demo

关于我

厦门大学计算机专业 | 前华为工程师
Java | 安卓 | 前端 | 小程序 | 鸿蒙
公众号:蓝不蓝编程
​​