我的应用中发生了一个非常奇怪的错误。我正在构建一个警报APP,我正在使用SQLite存储警报数据和广播接收器来管理警报管理器调用。
在某些情况下,onReceive的代码奇怪地表现不一样。当接收器收到广播时,我尝试启动一个Activity,几乎90%的情况一切顺利,我设法启动Activity,但在某些情况下,接收器执行指令非常奇怪" startActivity(i)&# 34;但没有任何反应。
重现BUG真的很难,在我的调试过程中,我已经学会了我所提到的内容,但是对于我来说,理解在大多数情况下对startActivity()的调用是如何工作的,在某些情况下确实很困难。不行。我已经搜索了Stack社区,但是没有人接受这种问题,每个人在启动活动时都遇到了问题,因为他们没有设置标志,或者因为他们没有在清单中注册接收器。下面我发布了代码。
public class AlarmReceiver extends WakefulBroadcastReceiver {
// The app's AlarmManager, which provides access to the system alarm services.
private AlarmManager alarmMgr;
// The pending intent that is triggered when the alarm fires.
private PendingIntent alarmIntent;
@Override
public void onReceive(Context context, Intent intent) {
Utils.logToFile("Received Alarm ,I am in onReceive(), ALARM ID: "+intent.getExtras().getInt(Constants.ALARM_ID));
Intent intent = new Intent(context, StopAlarm.class);
Bundle b = new Bundle();
b.putInt(Constants.ALARM_ID, intent.getExtras().getInt(Constants.ALARM_ID));
if(intent.getExtras().containsKey(Constants.SNOOZE_ALARM)){
b.putString(Constants.SNOOZE_ALARM, intent.getExtras().getString(Constants.SNOOZE_ALARM));
}
i.putExtras(b);
//this flag is needed to start an Activity from a BroadcastReceiver
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
//this method reads from the DB and sets the next alarm
//I tried commenting this method so that no DB action is
//performed and still the bug happened
setAlarm(context.getApplicationContext());
//this method just logs data into a file that I have created to keep track of events
//since not always the device is connected with LogCat
Utils.logToFile("Received Alarm, Intent(context, StopAlarm.class);");
}
我是否需要设置任何其他标志?在某些情况下,startActivity(intent)如何表现不正确?
修改
<activity
android:label="@string/app_name"
android:name="package.activity.StopAlarm"
android:windowSoftInputMode="stateAlwaysHidden"
android:screenOrientation="sensorPortrait">
</activity>
<receiver android:name="package.receivers.AlarmReceiver" />
答案 0 :(得分:3)
我终于通过创建IntentService并从IntentService启动活动并将两个标志设置为Intent来解决问题。执行此操作后,我将从DB读取的代码放在从IntentService启动的活动中。我已经测试了近60倍的行为,并且在所有测试中,应用程序的行为都正确。我发布下面的代码。
public class MyAlarmReceiver extends WakefulBroadcastReceiver {
// The app's AlarmManager, which provides access to the system alarm services.
private static AlarmManager alarmMgr;
// The pending intent that is triggered when the alarm fires.
private static PendingIntent alarmIntent;
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AlarmIntentService.class);
Bundle b = new Bundle();
b.putInt(Constants.ALARM_ID, intent.getExtras().getInt(Constants.ALARM_ID));
if(intent.getExtras().containsKey(Constants.SNOOZE_ALARM)){
b.putString(Constants.SNOOZE_ALARM, intent.getExtras().getString(Constants.SNOOZE_ALARM));
}
i.putExtras(b);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startWakefulService(context, i);
}
这是我需要实施的IntentService
public class AlarmIntentService extends IntentService {
public AlarmIntentService() {
super("AlarmIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Intent i = new Intent(this, StopAlarm.class);
Bundle b = new Bundle();
b.putInt(Constants.ALARM_ID, intent.getExtras().getInt(Constants.ALARM_ID));
if(intent.getExtras().containsKey(Constants.SNOOZE_ALARM)){
b.putString(Constants.SNOOZE_ALARM, intent.getExtras().getString(Constants.SNOOZE_ALARM));
}
i.putExtras(b);
//THESE ARE THE FLAGS NEEDED TO START THE ACTIVITY AND TO PREVENT THE BUG
//(CLEAR_TASK is crucial for the bug and new task is needed to start activity from outside of an activity)
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
MyAlarmReceiver.completeWakefulIntent(intent);
}
}
这是IntentService启动的活动。在这里,我设置了下一个警报。
public class StopAlarm extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stop_alarm);
//this method reads from the DB and sets the next alarm
MyAlarmReceiver.setAlarm(getApplicationContext());
...
答案 1 :(得分:1)
我有类似的问题。根据我的经验,问题是,startActivity(i)是异步的。因此在这种情况下,程序将同时调用onCreate(),onStart()等活动,但也调用QlokAlarmReceiver.completeWakefulIntent(intent)(无需等待活动关闭),这将释放wakeLock。因此,设备可以在执行onCreate()或onStart()上的活动时进入休眠状态。
鲁宾,我知道,我的答案与你的解决方案相矛盾,但我的日志清楚地表明了这样的事件顺序: - 调用startActivity - onCreate of the activity called - completeWakefulIntent(intent);在活动的onStart的日志之间调用
我的解决方法是在调用startActivity之前启动一个带有例如20秒超时的唤醒锁,然后在onCreate中启动另一个wakeLock,它将在onDestroy方法中释放。 我不确定我的解决方案是否符合最佳做法,但到目前为止我还没有找到更好的解决方案。