无法在安卓 10 [ 安卓 Q ] 中启动活动背景



我使用 android 10[android Q, galaxy 10],

我使用安卓工作室 3.3,

使用AVD,并制作了API 29 [Android 10]虚拟电话。

在虚拟机上, 我执行我的应用程序,之后,我启动其他应用程序,如日历,计算器。 因此,我的应用活动进入后台模式。

当我在广播接收器收到消息时。 我称之为startActivity。

在这里,代码 -->public class myReceiver 扩展了 BroadcastReceiver {}

public void onReceive(Context context, Intent intent)
{
Intent intentRun = new Intent(context, LoginSuccess.class);
intentRun.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intentRun);
}

但登录成功活动不显示。 [当我的应用处于后台模式时]

使用相同的代码,登录成功活动显示得很好 当我的应用处于前台模式时。

调用堆栈捕获图像

上图显示了调用堆栈 就在我调用广播接收器中的开始活动之前。

我已经阅读了android 10后台活动问题的指南。 [developer.android.com/~~某处位置]

在指导线上,

我开始知道 如果活动存在于调用堆栈中,则可以启动它 即使在后台模式下。

上面的代码, 它尝试启动最近调用堆栈中存在的活动。

为什么启动活动调用在后台模式下失败? [也许没有失败,但无论如何没有激活到前台]

在 Android Q 中,如果您的应用不包含以下链接中列出的例外情况,则无法从后台自动启动活动。

https://developer.android.com/guide/components/activities/background-starts

可能的解决方案:

1-您可以选择仅显示服务通知,然后单击即可开始待处理的意图

2-您可以使用全屏意图立即显示您的意图,如其他答案所示并由Google建议。

对于全屏意图解决方案,如官方文档中所述

系统 UI 可能会选择显示提醒通知,而不是 在用户使用设备时启动此意图。

3-要在后台自动启动活动,在我看来,最可能的解决方案是在清单文件中添加"SYSTEM_ALERT_WINDOW"。并在应用程序第一次打开时请求用户许可一次。(用户可以手动授予此权限 - (设置-应用程序-您的应用程序-高级 - 绘制其他应用程序((

请求权限的示例代码:

在清单中:

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

在应用程序中的某个地方:

public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE= 2323;
//if the user already granted the permission or the API is below Android 10 no need to ask for permission
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
!Settings.canDrawOverlays(getContext()))
{RequestPermission()}
private void RequestPermission() {
// Check if Android M or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getActivity().getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(getContext())) {
PermissionDenied();
}
else
{
// Permission Granted-System will work
}
}
}
}

我使用以下逻辑打开活动。 与谷歌一样,博客说如果您想在后台服务中打开活动以在Android 10或更高版本上使用通知。

在清单中:

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

例:

private void startActivity() {
Uri sound = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.siren);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
AudioAttributes attributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
String CHANNEL_ID = BuildConfig.APPLICATION_ID.concat("_notification_id");
String CHANNEL_NAME = BuildConfig.APPLICATION_ID.concat("_notification_name");
assert notificationManager != null;
NotificationChannel mChannel = notificationManager.getNotificationChannel(CHANNEL_ID);
if (mChannel == null) {
mChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
mChannel.setSound(sound, attributes);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setSmallIcon(R.drawable.logo)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.login))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(openScreen(Constants.NOTIFICATION_ID), true)
.setAutoCancel(true)
.setOngoing(true);
Notification notification = builder.build();
notificationManager.notify(Constants.NOTIFICATION_ID, notification);
} else {
startActivity(new Intent(BackgroundService.this, LoginActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
private PendingIntent openScreen(int notificationId) {
Intent fullScreenIntent = new Intent(this, LoginActivity.class);
fullScreenIntent.putExtra(Constants.NOTIFICATION_IDS, notificationId);
return PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}

如果您有 root 权限,您只需在 shell 中使用 am 命令即可:

public static final void switchAcitivty (final Context context) throws IOException {
final Runtime runtime = Runtime.getRuntime();
final String intentCommand =  "su -c am start -n yourpackage/.MainActivity -a android.intent.action.VIEW";
Log.i("TAG", intentCommand);
runtime.exec(intentCommand);
}

它在没有root权限的情况下被阻止(静默,这很烦人(。

很奇怪,但从前台服务启动活动在发布版本中有效。在调试版本中不起作用(通过 Android Studio 调试时(。

最新更新