从广播接收器拨打电话时出现上下文错误
Context Error when making call from Broadcast Receiver
我的应用程序检查 onResume 中的日期以查看是否需要调用 MainActivity 中名为 changeReminder 的方法。也就是说,如果日期与存储的日期不同,则调用 changeReminder(也从其他方法调用 changeReminder,例如刷新按钮)。 changeReminder 依次调用 Reminder class,它将在创建实例时创建一个新提醒。
现在,我正在向应用添加闹钟、广播接收器和通知。因为更改提醒是从 MainActivity 调用的,所以我在我的 BroadcastReceiver class 中创建了一个 activity 的实例,但是因为提醒 class 需要上下文(它有总是来自 MainActivity) 它抛出错误。在这种情况下,有没有办法从广播接收器成功传递上下文?我想我在下面包含了相关代码,但如果需要我可以添加更多...
触发警报后的日志:
05-02 13:23:00.712 15511-15511/com.mycompany.dudesmyreminders I/System.out﹕ onReceive
05-02 13:23:00.722 15511-15511/com.mycompany.dudesmyreminders I/System.out﹕ start changeReminder
05-02 13:23:00.722 15511-15511/com.mycompany.dudesmyreminders I/System.out﹕ start Reminder
05-02 13:23:00.752 15511-15511/com.mycompany.dudesmyreminders E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.mycompany.dudesmyreminders, PID: 15511
java.lang.RuntimeException: Unable to start receiver com.mycompany.dudesmyreminders.ReminderReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2726)
at android.app.ActivityThread.access00(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:267)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at com.mycompany.dudesmyreminders.dbDataSource.open(dbDataSource.java:39)
at com.mycompany.dudesmyreminders.Reminder.<init>(Reminder.java:37)
at com.mycompany.dudesmyreminders.MainActivity.changeReminder(MainActivity.java:283)
at com.mycompany.dudesmyreminders.ReminderReceiver.onReceive(ReminderReceiver.java:23)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2712)
at android.app.ActivityThread.access00(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
Main 中的警报管理器Activity onCreate:
//Alarm manager for notifications....
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
System.out.println("Hour = " + Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, Calendar.getInstance().get(Calendar.MINUTE) + 2);
System.out.println("Minute = " + Calendar.getInstance().get(Calendar.MINUTE));
calendar.set(Calendar.SECOND, 0);
Intent intent1 = new Intent(MainActivity.this, ReminderReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
广播接收器:
public class ReminderReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//throw new UnsupportedOperationException("Not yet implemented");
System.out.println("onReceive");
MainActivity ma = new MainActivity();
ma.changeReminder(context);
String message = ma.getStoredPreference("CurrentMessage");
NewReminderNotification.notify(context,message,1);
}
}
主菜单中的 changeReminder Activity:
public void changeReminder(Context context) {
System.out.println("start changeReminder");
Reminder reminder = new Reminder(this);
// Save the message to the Shared Preferences file
int altitude = getStoredPreferenceInt(SEEKBAR_CURRENT_INT);
savePreference("CurrentMessage", reminder.determineReminder(altitude));
savePreferenceInt(DBDATA_ID, (int) reminder.dbData.getId());
//populates the reminder dbData for current session
//DBDATA_ID is only changed in the line above
dbDataCurrentReminder = datasource.getDB_Row_FromID(dbRTable, (long) getStoredPreferenceInt(DBDATA_ID));
//display the message just saved
DisplaySavedMessage();
// save the current date to Preferences
saveDate();
setToggles(0);
}
提醒构造函数:
public Reminder(Context context) {
System.out.println("start Reminder");
ds = new dbDataSource(context);
ds.open();
DatabaseVersion = ds.DatabaseVersion;
}
尝试将 changeReminder(Context context)
方法块放入您的广播接收器而不是 Activity
并删除此行
MainActivity ma = new MainActivity();
ma.changeReminder(ma.getApplicationContext());
并成功
changeReminder(context); //you already have a context
另外 idk 如果你知道但是你调用 this
的任何地方你都可以调用你的 Context
除非它需要一个 Activity
class 实例..这是指this
你调用了 changeReminder
也把这个方法 getStoredPreference("CurrentMessage");
块放在你的 Receiver
class 或一个单例中 class
您的代码存在一些问题。
MainActivity ma = new MainActivity();
首先,永远 自己创建一个 Activity
、Service
或 ContentProvider
的实例。这些只能由框架实例化,而不是你。这就是您的实例不起作用的原因。
其次,不要在主应用程序线程上执行磁盘 I/O 或网络 I/O,因为在 I/O 进行时您的 UI 将被冻结。在主应用程序线程上调用了 BroadcastReceiver
的 onReceive()
,而您正在尝试(徒劳地)在该线程上执行数据库 I/O。
Is there a way to successfully pass the context from the Broadcast Receiver in this case?
欢迎您将方法设为 static
方法。
但是,更好的解决方案是将此代码移动到 IntentService
中。首先,它为您提供了一个安全的、受管理的后台线程来完成这项工作。其次,它与您应该使用的 WakefulBroadcastReceiver
一起工作,以确保设备可以保持唤醒状态足够长的时间供您执行此数据库 I/O。始终将 WakefulBroadcastReceiver
、我的 WakefulIntentService
或您自己的 WakeLock
与 RTC_WAKEUP
或 ELAPSED_REALTIME_WAKEUP
警报一起使用。
我的应用程序检查 onResume 中的日期以查看是否需要调用 MainActivity 中名为 changeReminder 的方法。也就是说,如果日期与存储的日期不同,则调用 changeReminder(也从其他方法调用 changeReminder,例如刷新按钮)。 changeReminder 依次调用 Reminder class,它将在创建实例时创建一个新提醒。
现在,我正在向应用添加闹钟、广播接收器和通知。因为更改提醒是从 MainActivity 调用的,所以我在我的 BroadcastReceiver class 中创建了一个 activity 的实例,但是因为提醒 class 需要上下文(它有总是来自 MainActivity) 它抛出错误。在这种情况下,有没有办法从广播接收器成功传递上下文?我想我在下面包含了相关代码,但如果需要我可以添加更多...
触发警报后的日志:
05-02 13:23:00.712 15511-15511/com.mycompany.dudesmyreminders I/System.out﹕ onReceive
05-02 13:23:00.722 15511-15511/com.mycompany.dudesmyreminders I/System.out﹕ start changeReminder
05-02 13:23:00.722 15511-15511/com.mycompany.dudesmyreminders I/System.out﹕ start Reminder
05-02 13:23:00.752 15511-15511/com.mycompany.dudesmyreminders E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.mycompany.dudesmyreminders, PID: 15511
java.lang.RuntimeException: Unable to start receiver com.mycompany.dudesmyreminders.ReminderReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2726)
at android.app.ActivityThread.access00(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:267)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at com.mycompany.dudesmyreminders.dbDataSource.open(dbDataSource.java:39)
at com.mycompany.dudesmyreminders.Reminder.<init>(Reminder.java:37)
at com.mycompany.dudesmyreminders.MainActivity.changeReminder(MainActivity.java:283)
at com.mycompany.dudesmyreminders.ReminderReceiver.onReceive(ReminderReceiver.java:23)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2712)
at android.app.ActivityThread.access00(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5696)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
Main 中的警报管理器Activity onCreate:
//Alarm manager for notifications....
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
System.out.println("Hour = " + Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, Calendar.getInstance().get(Calendar.MINUTE) + 2);
System.out.println("Minute = " + Calendar.getInstance().get(Calendar.MINUTE));
calendar.set(Calendar.SECOND, 0);
Intent intent1 = new Intent(MainActivity.this, ReminderReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
广播接收器:
public class ReminderReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//throw new UnsupportedOperationException("Not yet implemented");
System.out.println("onReceive");
MainActivity ma = new MainActivity();
ma.changeReminder(context);
String message = ma.getStoredPreference("CurrentMessage");
NewReminderNotification.notify(context,message,1);
}
}
主菜单中的 changeReminder Activity:
public void changeReminder(Context context) {
System.out.println("start changeReminder");
Reminder reminder = new Reminder(this);
// Save the message to the Shared Preferences file
int altitude = getStoredPreferenceInt(SEEKBAR_CURRENT_INT);
savePreference("CurrentMessage", reminder.determineReminder(altitude));
savePreferenceInt(DBDATA_ID, (int) reminder.dbData.getId());
//populates the reminder dbData for current session
//DBDATA_ID is only changed in the line above
dbDataCurrentReminder = datasource.getDB_Row_FromID(dbRTable, (long) getStoredPreferenceInt(DBDATA_ID));
//display the message just saved
DisplaySavedMessage();
// save the current date to Preferences
saveDate();
setToggles(0);
}
提醒构造函数:
public Reminder(Context context) {
System.out.println("start Reminder");
ds = new dbDataSource(context);
ds.open();
DatabaseVersion = ds.DatabaseVersion;
}
尝试将 changeReminder(Context context)
方法块放入您的广播接收器而不是 Activity
并删除此行
MainActivity ma = new MainActivity();
ma.changeReminder(ma.getApplicationContext());
并成功
changeReminder(context); //you already have a context
另外 idk 如果你知道但是你调用 this
的任何地方你都可以调用你的 Context
除非它需要一个 Activity
class 实例..这是指this
你调用了 changeReminder
也把这个方法 getStoredPreference("CurrentMessage");
块放在你的 Receiver
class 或一个单例中 class
您的代码存在一些问题。
MainActivity ma = new MainActivity();
首先,永远 自己创建一个 Activity
、Service
或 ContentProvider
的实例。这些只能由框架实例化,而不是你。这就是您的实例不起作用的原因。
其次,不要在主应用程序线程上执行磁盘 I/O 或网络 I/O,因为在 I/O 进行时您的 UI 将被冻结。在主应用程序线程上调用了 BroadcastReceiver
的 onReceive()
,而您正在尝试(徒劳地)在该线程上执行数据库 I/O。
Is there a way to successfully pass the context from the Broadcast Receiver in this case?
欢迎您将方法设为 static
方法。
但是,更好的解决方案是将此代码移动到 IntentService
中。首先,它为您提供了一个安全的、受管理的后台线程来完成这项工作。其次,它与您应该使用的 WakefulBroadcastReceiver
一起工作,以确保设备可以保持唤醒状态足够长的时间供您执行此数据库 I/O。始终将 WakefulBroadcastReceiver
、我的 WakefulIntentService
或您自己的 WakeLock
与 RTC_WAKEUP
或 ELAPSED_REALTIME_WAKEUP
警报一起使用。