Wear OS 权限屏幕从不显示在应用程序的第一个 运行 上 - 而是黑屏

Wear OS Permissions screen never shows on first run of app - black screen instead

我正在使用 中的以下代码在我的 Wear OS 应用程序的 onResume() 方法中检查和请求权限。

(我已经尝试过各种自写的检查和请求代码,并得到了相同的结果,但这段代码似乎是一个简洁的小函数,易于扩展。)

public boolean checkAndRequestPermissions() {

    Log.d("checkAndRequestPermissions", "starting check");

    int internet = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE);
    int loc_coarse = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
    int loc_fine = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();

    if (internet != PackageManager.PERMISSION_GRANTED) {
        Log.d("checkAndRequestPermissions", "INTERNET missing");
        listPermissionsNeeded.add(Manifest.permission.ACCESS_NETWORK_STATE);
    }
    if (loc_coarse != PackageManager.PERMISSION_GRANTED) {
        Log.d("checkAndRequestPermissions", "COARSE_LOCATION missing");
        listPermissionsNeeded.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    }
    if (loc_fine != PackageManager.PERMISSION_GRANTED) {
        Log.d("checkAndRequestPermissions", "FINE_LOCATION missing");
        listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }

    if (!listPermissionsNeeded.isEmpty()) {
        Log.d("checkAndRequestPermissions", "Requesting missing permissions");
        ActivityCompat.requestPermissions((Activity) this, listPermissionsNeeded.toArray
                (new String[listPermissionsNeeded.size()]), 1);
        return false;
    }
    return true;
}

当我的应用程序首次安装并 运行 时 - 无论是在模拟器上还是在真实设备上 - 应用程序启动,运行s 到 onCreate 没有问题,进入onResume 并调用上述方法。 (我在 onCreateonResume 中添加了很多调试输出以查看进度,一切正常)

我可以看到权限检查,可以看到 COARSE_LOCATIONFINE_LOCATION 都被发现像预期的那样丢失了(ACCESS_NETWORK_STATE 似乎默认启用)。

然后我看到应用程序即将请求权限。

此时我的应用程序进入onPause,大概是为了显示权限请求对话框,但随后一切都停止了。

logcat 中没有更多内容,设备显示屏变黑并保持黑色。

这是 logcat 在我的应用程序调试中显示的内容:

D/onCreate: starting
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
W/3words_for_wea: Accessing hidden method Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; (light greylist, reflection)
W/3words_for_wea: Accessing hidden method Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V (light greylist, reflection)
    Accessing hidden method Ldalvik/system/CloseGuard;->warnIfOpen()V (light greylist, reflection)
D/onCreate: set up bindings and animations
D/onCreate: set up on click listeners
D/onCreate: end of onCreate
D/onResume: onResume - last w3wAddress = 
D/checkAndRequestPermissions: starting check
D/checkAndRequestPermissions: COARSE_LOCATION missing
    FINE_LOCATION missing
    Requesting missing permissions
D/OpenGLRenderer: HWUI GL Pipeline
D/onPause: onPause
D/: HostConnection::get() New Host Connection established 0xdbc22500, tid 4031
I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
    android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/OpenGLRenderer: Swap behavior 0
D/EGL_emulation: eglCreateContext: 0xdb09c3a0: maj 2 min 0 rcv 2
D/EGL_emulation: eglMakeCurrent: 0xdb09c3a0: ver 2 0 (tinfo 0xe7e56ab0)
D/EGL_emulation: eglMakeCurrent: 0xdb09c3a0: ver 2 0 (tinfo 0xe7e56ab0)

如果我 return 到设备主屏幕并重新打开应用程序,权限请求对话框会立即打开,我可以授予权限,应用程序将按预期启动。

我观察到的另一个奇怪之处是,当设备处于这种 'black screen but on' 状态时,我无法从 Android Studio 重新启动应用程序。 Android studio 仍然认为该应用程序是 运行ning(对于 运行ning 应用程序,我在 IDE 工具栏中显示了预期的停止和重新启动按钮),但是单击restart-with-stop 或 restart-auto 按钮什么都不做。

但是,如果我将 logcat 视图从调试切换到详细,logcat 会清空。如果我 Return 到调试 logcat 它仍然是空的,所以就好像有什么东西真的崩溃了,但我的应用程序没有它的日志。

如果我查看 system_process logcat,而不是我的应用程序,我会看到不断重复的消息,如下所示:

1874-1995/system_process I/GnssLocationProvider: WakeLock acquired by sendMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@97cf332)
1874-1898/system_process I/GnssLocationProvider: WakeLock released by handleMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@97cf332)

请注意,在确认授予所需权限之前,运行 没有任何需要请求权限的内容。

什么可能导致黑屏死机,我该如何预防?

我已设法通过采用 'best practice approach' 要求用户交互来提示权限请求来解决此问题 - 尽管这似乎并不适合显示 primary/only 目的的应用程序您的位置!

为了实现这一点,我的应用程序不再尝试从 onCreate()onResume 请求权限,而是在尚未授予权限时在屏幕上显示一个突出的按钮。当用户点击按钮时,上面的权限检查和请求代码是 运行.

为了使这更容易一些,我修改了上面的代码并按如下方式重载了方法,以便我可以调用相同的代码来检查和请求或仅根据需要检查权限。

public boolean checkAndRequestPermissions() {
    checkAndRequestPermissions(false);
}

public boolean checkAndRequestPermissions(boolean checkOnly) {

    Log.d("checkAndRequestPermissions", "starting check");

    int internet = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE);
    int loc_coarse = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
    int loc_fine = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();

    if (internet != PackageManager.PERMISSION_GRANTED) {
        Log.d("checkAndRequestPermissions", "INTERNET missing");
        listPermissionsNeeded.add(Manifest.permission.ACCESS_NETWORK_STATE);
    }
    if (loc_coarse != PackageManager.PERMISSION_GRANTED) {
        Log.d("checkAndRequestPermissions", "COARSE_LOCATION missing");
        listPermissionsNeeded.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    }
    if (loc_fine != PackageManager.PERMISSION_GRANTED) {
        Log.d("checkAndRequestPermissions", "FINE_LOCATION missing");
        listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }

    if (!listPermissionsNeeded.isEmpty() && !checkOnly) {
        Log.d("checkAndRequestPermissions", "Requesting missing permissions");
        ActivityCompat.requestPermissions((Activity) this, listPermissionsNeeded.toArray
                (new String[listPermissionsNeeded.size()]), 1);
        return false;
    }
    return true;
}