位置访问时无法捕获的异常

Posted

技术标签:

【中文标题】位置访问时无法捕获的异常【英文标题】:Uncatchable exception on location access 【发布时间】:2018-08-31 15:08:23 【问题描述】:

我正在尝试让我的 android Wear 表盘确定设备的当前位置。这以前有效,但在卸载并重新安装软件包后,它就失败了。我认为我做的一切都是正确的,而且它已经像那样工作了。我不知道问题是什么,甚至不知道如何抓住它。以下是相关代码:

class MyWatchFaceService : CanvasWatchFaceService() 
    override fun onCreateEngine(): Engine 
        return Engine()
    

    inner class Engine : CanvasWatchFaceService.Engine() 
        private lateinit var fusedLocationClient: FusedLocationProviderClient
        private var lastKnownLocation: Location? = null

        override fun onCreate(holder: SurfaceHolder) 
            super.onCreate(holder)
            fusedLocationClient = LocationServices.getFusedLocationProviderClient(this@MyWatchFaceService)
            updateLocation()
        

        fun updateLocation() 
            Logger.getAnonymousLogger().info("updateLocation")
            try 
                fusedLocationClient.lastLocation
                        .addOnSuccessListener  location: Location? ->
                            if (location != null) 
                                // Location available, use it and update later
                                Logger.getAnonymousLogger().info("- location available")
                                lastKnownLocation = location
                            
                        
                        .addOnFailureListener ex: Exception ->
                            Logger.getAnonymousLogger().warning("- location NOT accessible (inner): " + ex.toString())
                        
             catch (ex: SecurityException) 
                // Nothing we can do, no location available
                Logger.getAnonymousLogger().warning("- location NOT accessible: " + ex.toString())
            
            Logger.getAnonymousLogger().info("updateLocation (end)")
        
    

然后我在日志中找到这个:

03-22 09:41:59.521 7390-7390/de.unclassified.watchface1 I/null: updateLocation
03-22 09:41:59.536 7390-7390/de.unclassified.watchface1 I/null: updateLocation (end)
03-22 09:41:59.830 7390-7405/de.unclassified.watchface1 E/AndroidRuntime: FATAL EXCEPTION: GoogleApiHandler
                                                                          Process: de.unclassified.watchface1, PID: 7390
                                                                          java.lang.SecurityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.
                                                                              at android.os.Parcel.readException(Parcel.java:1684)
                                                                              at android.os.Parcel.readException(Parcel.java:1637)
                                                                              at com.google.android.gms.internal.zzeu.zza(Unknown Source)
                                                                              at com.google.android.gms.internal.zzcfa.zzif(Unknown Source)
                                                                              at com.google.android.gms.internal.zzcfd.getLastLocation(Unknown Source)
                                                                              at com.google.android.gms.internal.zzcfk.getLastLocation(Unknown Source)
                                                                              at com.google.android.gms.location.zzg.zza(Unknown Source)
                                                                              at com.google.android.gms.common.api.internal.zze.zza(Unknown Source)
                                                                              at com.google.android.gms.common.api.internal.zzbo.zzb(Unknown Source)
                                                                              at com.google.android.gms.common.api.internal.zzbo.zzaiw(Unknown Source)
                                                                              at com.google.android.gms.common.api.internal.zzbo.onConnected(Unknown Source)
                                                                              at com.google.android.gms.common.internal.zzac.onConnected(Unknown Source)
                                                                              at com.google.android.gms.common.internal.zzn.zzakr(Unknown Source)
                                                                              at com.google.android.gms.common.internal.zze.zzw(Unknown Source)
                                                                              at com.google.android.gms.common.internal.zzi.zzaks(Unknown Source)
                                                                              at com.google.android.gms.common.internal.zzh.handleMessage(Unknown Source)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                              at android.os.Looper.loop(Looper.java:154)
                                                                              at android.os.HandlerThread.run(HandlerThread.java:61)
03-22 09:41:59.843 7390-7405/de.unclassified.watchface1 I/Process: Sending signal. PID: 7390 SIG: 9

所以它确实调用了我的updateLocation 函数,然后再次离开,然后出现异常。但据我所知,这并不是调用我的代码。它从何而来?它没有包含源文件的堆栈跟踪。

包已经拥有所有相关权限,和以前一样,还有一些其他任务的权限。

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

那么这里发生了什么,为什么 try/catch 和失败监听器都没有做某事?

【问题讨论】:

您需要询问Runtime permission Error: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION的可能重复 【参考方案1】:

COARSE Location 很危险,因此,Google 会强制您在运行时请求它,仅在 Android Manifest 中声明是不够的。示例请参考此链接:https://developer.android.com/training/permissions/requesting.html

这里有一个快速代码:

if (ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.ACCESS_FINE_LOCATION)
    != PackageManager.PERMISSION_GRANTED) 
   ActivityCompat.requestPermissions(thisActivity,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                0x0)

您应该同时申请 Fine 和 Coarse 权限。

【讨论】:

我不需要很好的位置,只需要计算日出/日落。但是这段代码不起作用。我没有活动,只有服务。如何向服务请求权限? 您必须使用 Activity 来请求权限。如果您的应用程序不包含任何活动,只需创建一个空白(无 UI),请求权限,然后完成它。请注意,您可以向任何活动请求许可,只需确保在您开始服务之前获得许可。【参考方案2】:

在您启动服务之前,或者更好地为用户提供该服务之前,您需要确保他们允许向您提供他们的粗略/精细位置,因此您需要在 Activity 中为他们提供选项。

这样想,您的服务在background 中运行,并且您需要用户的许可才能完成您的工作,并且您不能假设服务运行时用户在场。因此,当用户在场时,即 Activity 正在运行时,您必须要求该权限。

【讨论】:

实际上,表盘似乎总是从前台开始。但这不是一项活动,它只是一项可见的交互式服务。我是 Android 编程新手,所以这有点令人困惑。 如果你在 Wear OS 上尝试这个,你可能想看看here,因为它有点不同。 有趣的图片但是没有代码,所以我不能很好地使用。 您是否尝试过创建活动并在其中请求权限? (按照指南的建议在您的服务中启动活动)。

以上是关于位置访问时无法捕获的异常的主要内容,如果未能解决你的问题,请参考以下文章

捕获访问冲突异常?

[转]System.DllNotFoundException: 无法加载 DLL“*.dll”: 内存位置访问无效。 (异常来自 HRESULT:0x800703E6)

C#如何捕获异常并检查它是否包含字符串?

带有消息“SQLSTATE [42000]”的未捕获异常“PDOException”:语法错误或访问冲突:

数据访问对象 (DAO) 中的方法应该抛出还是捕获其异常? [关闭]

SpringWeb 系列教程 RestTemplate 4xx/5xx 异常信息捕获