当前位置:   article > 正文

Android 在后台无法启动Activity_此应用没有可供打开的activity 小黑屋

此应用没有可供打开的activity 小黑屋

前言

前几天接触的一个闹钟APP项目,闹钟触发从后台启动一个activity,执行之后的响铃操作,但是却失效了,闹钟并没有按时响铃。最后发现是系统拦截了从后台启动的Activity。

具体原因

  • 一、AndroidQ从后台启动Activity的限制
    Android 10 (API 级别 29) 及更高版本对后台应用可启动 Activity进行限制。Android10中, 当App的Activity不在前台时,其启动Activity会被系统拦截,导致无法启动。

  • 二、后台弹出界面、锁屏显示权限(小米等部分国产手机)
    小米手机有个特殊的权限,“后台弹出界面(允许应用在后台弹出界面)”,默认是拒绝的,如下图所示.
    小米手机权限页面
    华为手机没有这个权限,目前vivo/oppo/小米手机有这个“后台弹出界面”权限.

  • 其他原因,有待更新,暂时没有遇见

解决方案

  • 一、针对Android10的问题

    方案1
    官方给予的折中方案是使用全屏Intent(full-screen intent), 既创建通知栏通知时, 加入full-screen intent 设置。示例代码如下(基于官方文档修改):

Intent fullScreenIntent = new Intent(this, CallActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
        fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
NotificationCompat.Builder notificationBuilder =
        new NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Incoming call")
    .setContentText("(919) 555-1234")
    //以下为关键的3行
    .setPriority(NotificationCompat.PRIORITY_HIGH)
    .setCategory(NotificationCompat.CATEGORY_CALL)
    .setFullScreenIntent(fullScreenPendingIntent, true);
    
NotificationManager notifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notifyManager.notify(notifyId, builder.build());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

注意:在Target SDk为29及以上时,需要在AndroidManifest上增加USE_FULL_SCREEN_INTENT申明

//AndroidManifest中
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
  • 1
  • 2

方案2
向用户申请 SYSTEM_ALERT_WINDOW权限,系统就不会拦截该程序后台启动的Activity。
示例代码如下:

//AndroidManifest中
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  • 1
  • 2
//检查是否已经授予权限
if (!Settings.canDrawOverlays(this)) {
    //若未授权则请求权限
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
    intent.setData(Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, 0);
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

其中,Settings.canDrawOverlays(this)方法是在API level 23也就是Android M中新加入的用于检查当前是否拥有出现在“出现在其他应用上”权限的方法。在6.0以前的系统版本,悬浮窗权限是默认开启的,直接使用即可。

  • 二、针对后台弹出界面锁屏显示权限的问题

应用检查后台启动权限的方法如下:

public static boolean canBackgroundStart(Context context) {
        AppOpsManager ops = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        try {
            int op = 10021; // >= 23
            // ops.checkOpNoThrow(op, uid, packageName)
            Method method = ops.getClass().getMethod("checkOpNoThrow", new Class[]
                    {int.class, int.class, String.class}
            );
            Integer result = (Integer) method.invoke(ops, op, Process.myUid(), context.getPackageName());
            return result == AppOpsManager.MODE_ALLOWED;
        } catch (Exception e) {
            Log.e(TAG, "not support", e);
        }
        return false;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

该方法是申请“后台弹出页面”权限白名单时小米官方给出的检查后台启动权限的方法。或跳转到权限设置页面,请求用户打开相应权限。
欢迎阅读另一篇,跳转手机权限管理页面

小白初来乍到,多多指教

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/247510
推荐阅读
相关标签
  

闽ICP备14008679号