You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求位置权限时App崩溃:Task is not yet complete异常排查

安卓App位置权限请求时崩溃问题排查与解决

问题背景

开发一个包含两个Activity的简易安卓App:主Activity有一个TextView(显示占位符或地图返回的坐标)和跳转按钮,通过registerForActivityResult跳转到MapActivity;MapActivity是可放置标记的地图页面,提交后将坐标返回主Activity显示。但App请求用户位置权限时发生崩溃,抛出IllegalStateException: Task is not yet complete异常。

崩溃日志

2022-09-16 00:28:51.357 10442-10442/com.example.ymapstest E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.ymapstest, PID: 10442
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ymapstest/com.example.ymapstest.MapActivity}: java.lang.IllegalStateException: Task is not yet complete
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.IllegalStateException: Task is not yet complete
        at com.google.android.gms.common.internal.Preconditions.checkState(com.google.android.gms:play-services-basement@@18.0.0:2)
        at com.google.android.gms.tasks.zzw.zzf(com.google.android.gms:play-services-tasks@@18.0.1:1)
        at com.google.android.gms.tasks.zzw.getResult(com.google.android.gms:play-services-tasks@@18.0.1:1)
        at com.example.ymapstest.MapActivity.getLastLocation(MapActivity.kt:61)
        at com.example.ymapstest.MapActivity.onCreate(MapActivity.kt:35)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

相关代码

MainActivity代码

class MainActivity : AppCompatActivity() {
    private var launcher: ActivityResultLauncher<Intent>? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val textView: TextView = findViewById(R.id.tv_message)
        launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            result: ActivityResult ->
            if (result.resultCode == RESULT_OK) {
                val latitude = result.data?.getDoubleExtra("latitude", 0.0).toString()
                val longitude = result.data?.getDoubleExtra("longitude", 0.0).toString()
                textView.text = getString(R.string.address, latitude, longitude)
            }
        }
    }

    fun onClickToMap(view: View) {
        launcher?.launch(Intent(this, MapActivity::class.java))
    }
} 

MapActivity代码

class MapActivity : AppCompatActivity(), InputListener{

    private lateinit var mapView: MapView
    private val mapAPI = "my api key here"
    private val REQUEST_CODE = 101
    var userInput: Point = Point(0.0, 0.0)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        MapKitFactory.setApiKey(mapAPI)
        MapKitFactory.initialize(this)
        setContentView(R.layout.activity_map)
        val userLocation = Point(getLastLocation().latitude, getLastLocation().longitude)

        mapView = findViewById(R.id.mapview)
        mapView.map.move(
            CameraPosition(userLocation, 11.0f, 0.0f, 0.0f),
            Animation(Animation.Type.SMOOTH, 300f), null)
    }

    fun onClick(view: View) {
        if (userInput.equals(Point(0.0, 0.0))) {
            Toast.makeText(this, "You didnt place the point", Toast.LENGTH_LONG).show()
        } else {
            val intent = Intent()
            intent.putExtra("latitude", userInput.latitude)
            intent.putExtra("longitude", userInput.longitude)
            setResult(RESULT_OK, intent)
        }
    }

    private fun getLastLocation(): Location {
        val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
            requestLocationPermission()
            return fusedLocationProviderClient.lastLocation.result
        } else {
            return fusedLocationProviderClient.lastLocation.result
        }
    }

    private fun requestLocationPermission() {
        if (ContextCompat.checkSelfPermission(this, "android.permission.ACCESS_FINE_LOCATION")!= PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_CODE)
        }
    }

    override fun onStop() {
        super.onStop()
        mapView.onStop()
        MapKitFactory.getInstance().onStop()
    }

    override fun onStart() {
        super.onStart()
        mapView.onStart()
        MapKitFactory.getInstance().onStart()
    }

    override fun onMapTap(map: Map, point: Point) {
        mapView.map.mapObjects.clear()
        mapView.map.mapObjects.addPlacemark(point, ImageProvider.fromResource(this, R.drawable.ic_pin))
        userInput = point
    }
}

问题根源

  1. 异步任务同步获取结果:fusedLocationProviderClient.lastLocation返回的是Task<Location>,这是一个异步操作,直接调用.result会在任务未完成时抛出Task is not yet complete异常。
  2. 权限处理逻辑错误:请求权限后立即尝试获取位置,此时用户还未完成权限授权操作,权限状态仍为未授予,同时异步位置任务也未执行。
  3. 缺少Activity关闭逻辑:MapActivity提交坐标后未调用finish(),导致Activity无法返回主Activity。

修复方案

1. 异步处理位置获取

使用Task的监听器方法addOnSuccessListener和addOnFailureListener异步获取位置结果,避免同步阻塞。

2. 正确处理权限回调

重写onRequestPermissionsResult方法,在用户授予权限后再执行位置获取逻辑;若用户拒绝权限,可设置默认位置或提示用户。

3. 补充Activity关闭逻辑

在提交坐标后调用finish()关闭MapActivity,确保结果返回主Activity。

修复后的MapActivity代码

class MapActivity : AppCompatActivity(), InputListener {

    private lateinit var mapView: MapView
    private val mapAPI = "my api key here"
    private val REQUEST_CODE = 101
    var userInput: Point = Point(0.0, 0.0)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        MapKitFactory.setApiKey(mapAPI)
        MapKitFactory.initialize(this)
        setContentView(R.layout.activity_map)

        mapView = findViewById(R.id.mapview)
        // 先初始化地图到默认位置,后续获取到位置后再移动
        val defaultLocation = Point(55.751244, 37.618423) // 莫斯科坐标作为默认
        mapView.map.move(
            CameraPosition(defaultLocation, 11.0f, 0.0f, 0.0f),
            Animation(Animation.Type.SMOOTH, 300f), null)

        // 检查权限并尝试获取位置
        checkLocationPermissionAndFetchLocation()
    }

    fun onClick(view: View) {
        if (userInput.equals(Point(0.0, 0.0))) {
            Toast.makeText(this, "You didn't place the point", Toast.LENGTH_LONG).show()
        } else {
            val intent = Intent()
            intent.putExtra("latitude", userInput.latitude)
            intent.putExtra("longitude", userInput.longitude)
            setResult(RESULT_OK, intent)
            finish() // 关闭Activity返回主页面
        }
    }

    private fun checkLocationPermissionAndFetchLocation() {
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            // 权限已授予,异步获取位置
            fetchLastLocation()
        } else {
            // 权限未授予,发起请求
            ActivityCompat.requestPermissions(
                this,
                arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
                REQUEST_CODE
            )
        }
    }

    private fun fetchLastLocation() {
        val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
        fusedLocationProviderClient.lastLocation.addOnSuccessListener { location: Location? ->
            location?.let {
                val userLocation = Point(it.latitude, it.longitude)
                // 移动地图到用户位置
                mapView.map.move(
                    CameraPosition(userLocation, 11.0f, 0.0f, 0.0f),
                    Animation(Animation.Type.SMOOTH, 300f), null)
            } ?: run {
                // 位置获取失败,提示用户
                Toast.makeText(this, "Failed to get your location", Toast.LENGTH_SHORT).show()
            }
        }.addOnFailureListener { exception ->
            // 处理获取位置失败的情况
            Toast.makeText(this, "Location fetch error: ${exception.message}", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授予权限,获取位置
                fetchLastLocation()
            } else {
                // 用户拒绝权限,提示或使用默认位置
                Toast.makeText(this, "Location permission denied, using default location", Toast.LENGTH_SHORT).show()
            }
        }
    }

    override fun onStop() {
        super.onStop()
        mapView.onStop()
        MapKitFactory.getInstance().onStop()
    }

    override fun onStart() {
        super.onStart()
        mapView.onStart()
        MapKitFactory.getInstance().onStart()
    }

    override fun onMapTap(map: Map, point: Point) {
        mapView.map.mapObjects.clear()
        mapView.map.mapObjects.addPlacemark(point, ImageProvider.fromResource(this, R.drawable.ic_pin))
        userInput = point
    }
}

内容的提问来源于stack exchange,提问作者Eugene Mihailukov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:40:25