android - BroadcastReciever.onReceive startActivity 不显示活动
问题描述
下面的评论都不适合我。
但是,我找到了解决方法。我需要更改我的 AlarmActivity,看来 keyguardManager.requestDismissKeyguard 非常重要。
代码:
public class AlarmActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
this.setTurnScreenOn(true);
this.setShowWhenLocked(true);
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);
}
}
最初的问题是..
我正在尝试从 BroadcastReciever.onReceive 方法显示一个活动 (startActivity),但它不能始终如一地工作。如果设备处于活动状态但在设备锁定时出现问题,我的代码似乎运行良好。以下代码应符合 minSdkVersion 28。
现有代码使用 AlarmManager.setExactAndAllowWhileIdle 来触发 BroadcastReciever。根据 intent.getExtras 中的某些值,代码应显示:AssessmentAlarmActivity 或 MATActivity。即使设备正在打盹并且在锁定屏幕上,AssessmentAlarmActivity 也需要始终显示。MATActivity 应仅在设备处于活动状态时显示(不必唤醒设备或在锁定屏幕上显示)。
以下代码似乎适用于很多设备。查看 logcat 数据,我看到 BroadcaseReceiver.onReceive 被触发,但有时活动可能需要一分钟才能显示。在某些设备上,活动根本不会显示。我假设以下代码在 intent.addFlags 代码中有不正确的值,但我不确定。
AlarmManager.setExactAndAllowWhileIdle 代码:
private static void setAlarm(Context context, ResponseInfo responseInfo, int requestCode) {
// Create a new PendingIntent and add it to the AlarmManager
Intent intent = new Intent(context, ResponseAlarmReceiver.class);
responseInfo.setRequestCode(requestCode);
intent.putExtras(responseInfo.createBundle());
// Create a new PendingIntent and add it to the AlarmManager
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, responseInfo.getAlarmTime(), pendingIntent);
pendingIntents.put(requestCode, pendingIntent);
}
BroadcastReceiver.onRecieve 代码:
public class ResponseAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// read the ResponseInfo from the extras
ResponseInfo responseInfo = new ResponseInfo();
responseInfo.readBundle(intent.getExtras());
// log requestInfo data
Log.i("ALARM", String.format("Now: %d, responseInfo: %s",
System.currentTimeMillis(), responseInfo.toString()) );
if (responseInfo.getAlarmType() == AlarmType.CANCEL) {
cancelAlarm(context);
}
else {
showAssessmentAlarm(context);
}
}
private static void showAssessmentAlarm(Context context) {
Log.i("ALARM", "showAssessmentAlarm top");
Intent nextIntent = new Intent(context, AssessmentAlarmActivity.class);
nextIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(nextIntent);
Log.i("ALARM", "showAssessmentAlarm bottom");
}
private void cancelAlarm(Context context) {
Log.i("ALARM", "cancelAlarm top");
Intent intent = new Intent(context, MATActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
AndroidManifest.xml 定义的活动:
<activity
android:name=".MATActivity"
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".AssessmentAlarmActivity" android:theme="@android:style/Theme.Dialog" android:screenOrientation="portrait" ></activity>
MATActivity 是一个非常标准的活动,所以我将跳过该代码。AssessmentAlarmActivity 确实有一个特殊的设置并扩展了 AlarmActivity:
public class AlarmActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
// not minSdkVersion 28 complient, but this is what I have tested most
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
}
public class AssessmentAlarmActivity extends AlarmActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.assessment_alarm);
..
}
...
}
解决方案
我认为这是因为后台进程限制。尝试在插入电话(充电)的情况下再次对其进行测试。如果问题解决了,那是因为后台进程限制。
如果您正在制作闹钟或非常重要的事情,您可以使用alarmManager.setAlarmClock()。它将绕过限制。
不要忘记
wakeLock
立即获取 inonReceive
。否则安卓系统可能很快就会进入空闲模式。
注意:您可能只需要第二部分(获取 WakeLock)。但同时实施两者是一种更强大的方式。
推荐阅读
- sql - 在查询中从 nvarchar 读取键值对 XML,返回列中的值
- c# - 仅在某些情况下 LINQ 语句的 OutOfMemory 异常
- ruby-on-rails - 如何在视图中覆盖策略类
- c# - C# wpf 当打开文件时检测应用程序实例是否打开
- amazon-web-services - 使用 Pulumi 将 IAM 托管策略附加到 IAM 用户不起作用
- sql - 如何处理具有 varchar 值以及显示为科学格式的大数字的列?
- c# - 我无法让声音在我的小行星游戏中正常工作?
- ios - 核心图像裁剪和缩放图像大小
- reactjs - 这个怎么用。在react的return函数之外?
- javascript - 模拟传入客户端的函数的 req 和 res 的最佳方法是什么,例如 redis get 函数 - 下面的示例