在后台运行时显示弹出窗口?

27

我想从扩展Service类的类中打开一个活动。当应用程序不在前台/未使用时,我执行此任务。我可以在日志中看到我的服务类使用Intent.FLAG_ACTIVITY_NEW_TASK标志触发了启动活动。但是该活动没有打开。但是当服务在前台/正在使用应用程序时触发相同的活动时,该活动会打开。

经过一些搜索,我发现我需要在应用程序设置中的其他权限部分手动授予权限“在后台运行时显示弹出窗口android”。

在其他应用程序上显示的权限SYSTEM_ALERT_WINDOW仅提供访问“显示弹出窗口”的权限。

Other permissions

在上面的图像中,SYSTEM_ALERT_WINDOW将只授予您访问“显示弹出窗口”的权限,如果应用程序处于前台/正在使用,则这很好用,但是如果授予红色标记的权限,则可以直接从扩展Service类的类中打开任何活动。

如何检查或要求用户授予“在后台运行时显示弹出窗口”权限?还是此权限受限制?

我看到WhatsApp等应用程序默认已选中此选项。


1
请查看此答案:https://dev59.com/ZFkS5IYBdhLWcg3wHDLU#40355440 - Aswin P Ashok
1
这个回答解决了你的问题吗?如何在Android中以编程方式授予“绘制其他应用程序”权限? - Aswin P Ashok
抱歉@AswinPAshok,我已经在使用上述解决方案,但那不是我要找的。无论如何,非常感谢您的回复。 :) 我已经编辑了问题并附上了一张图片以获得更好的清晰度。 - Sidharth MA
1
@SidharthMA 不好意思,根据我的搜索结果,在运行时我们无法更改权限,唯一的解决方案是向用户显示HeadsUp通知并要求他启用它,但是对于那些我们无法授权的用户来说,我们需要另一种权限来显示HeadsUp通知(即显示浮动通知)。 - Shayan Pourvatan
3
@SidharthMA,我知道像Uber、Facebook这样的白名单应用默认开启了它。 - Bhavin Chauhan
显示剩余5条评论
4个回答

9
这是小米设备开发人员经常遇到的问题, 目前我们的解决方案是将用户重定向到“其他权限”屏幕,让用户手动授予权限:
if ("xiaomi" == Build.MANUFACTURER.toLowerCase(Locale.ROOT)) {
    val intent = Intent("miui.intent.action.APP_PERM_EDITOR")
    intent.setClassName("com.miui.securitycenter",
            "com.miui.permcenter.permissions.PermissionsEditorActivity")
    intent.putExtra("extra_pkgname", getPackageName())
    startActivity(intent)
}

您可以使用Settings.canDrawOverlays(this)来测试用户是否已经授予显示弹出窗口的权限,这意味着该应用程序可以在系统ui上绘制。
另外两个权限无法确定用户是否已经授予它们:
  1. 在后台运行时显示弹出窗口:这个权限允许应用程序在后台运行时绘制到系统ui上,例如服务广播
  2. 在锁屏界面显示:这个权限允许应用即使在屏幕锁定的情况下也能够运行,例如社交应用(WhatsApp、Viber、Messnger等)

1
请参考@Kasun Thilina的聪明回答来解决这个问题:“现在的问题是你无法检查用户是否授予权限”。 - cobberboy
1
如何检查用户是否被授予权限? - Mohd Sakib Syed

6

由于没有官方方法可以检查“在后台运行时显示弹出窗口”权限,我使用了一个小技巧来检查权限。

检查应用程序是否可以绘制覆盖层,如下所示,然后如果设备是小米,则导航用户到特定的设置屏幕,如下所示。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                if ("xiaomi".equals(Build.MANUFACTURER.toLowerCase(Locale.ROOT))) {
                    final Intent intent =new Intent("miui.intent.action.APP_PERM_EDITOR");
                    intent.setClassName("com.miui.securitycenter",
                            "com.miui.permcenter.permissions.PermissionsEditorActivity");
                    intent.putExtra("extra_pkgname", getPackageName());
                    new AlertDialog.Builder(this)
                            .setTitle("Please Enable the additional permissions")
                            .setMessage("You will not receive notifications while the app is in background if you disable these permissions")
                            .setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
                                    startActivity(intent);
                                }
                            })
                            .setIcon(android.R.drawable.ic_dialog_info)
                            .setCancelable(false)
                            .show();
                }else {
                    Intent overlaySettings = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
                    startActivityForResult(overlaySettings, OVERLAY_REQUEST_CODE);
                }
            }
        }

Settings.canDrawOverlays(this) 这会确保授予“显示弹出窗口”吗? - Arul

0
请尝试以下代码。
 Intent rIntent = context.getPackageManager()
                    .getLaunchIntentForPackage(context.getPackageName() );
            PendingIntent intent = PendingIntent.getActivity(
                    context, 0,
                    rIntent, PendingIntent.FLAG_CANCEL_CURRENT);
            AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            manager.set(AlarmManager.RTC, System.currentTimeMillis(), intent);
            System.exit(2);

嗨,解决方案可以工作,但我更喜欢有权限。谢谢 :) - Sidharth MA
为什么需要调用 "System.exit(2);",以及为什么参数是2? - android developer
System.exit() 终止当前运行的 Java 虚拟机。该参数用作状态码;按照惯例,非零状态码表示异常终止。因此,exit(0) 通常用于表示成功终止。而其他参数如 1、2、-1 都表示不成功的终止,它们之间没有区别。 - littlebear333
2
如何检查权限是否已经被授予? - Muhammad chhota

0
我通过遵循这个要点https://gist.github.com/0awawa0/65bf88e43159750f596da194ed923522成功解决了我的项目。
@ReactMethod()
    public void isMiuiCanDisplayOverlay(Promise ps){
        boolean isXiaomi = XiaomiUtilities.isMIUI();
        boolean isGranted = XiaomiUtilities.isPermissionGranted(reactContext,XiaomiUtilities.OP_BACKGROUND_START_ACTIVITY);
        if(isXiaomi){
            ps.resolve(isGranted);
        }else{
            ps.resolve(true);
        }
    }
    @ReactMethod()
    public void openMiuiDisplayOverlayPermission(Promise ps){
        boolean isXiaomi = XiaomiUtilities.isMIUI();
        try{
            if(isXiaomi){
                XiaomiUtilities.goToMiuiPermissionActivity_V8(reactContext);
                ps.resolve(true);
            }else{
                ps.resolve(false);
            }
        }catch (Exception e){
            String version = XiaomiUtilities.getMiuiVersion();
            Log.d(LOG_TAG,"Cannot open Miui Display Pop-up window while running in background" + version + e.toString());
        }
    }

    

code above I created in react native to bridge to javascript

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接