我会简单地总结一下因为我的原始代码很长。假设我的广播接收器是这样的:
public class SMSBroadcastReceiver extends BroadcastReceiver {
static ArrayList<String> phonenumber_array = new ArrayList<String>();
static ArrayList<String> message_array = new ArrayList<String>();
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
SmsMessage[] sms = new SmsMessage[pdus.length];
for (int i = 0; i < sms.length; i++) {
sms[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
phonenumber_array.add(0,sms[i].getOriginatingAddress());
message_array.add(0,sms[i].getMessageBody());
com.test.ListActivityClass.myadapter.notifyDataSetChanged();
}
}
在我的AndroidManifest.xml中,BroadcastReceiver有IntentFilter“android.provider.Telephony.SMS_RECEIVED”。
我的ListActivityClass扩展了ListActivity,包含一个myadapter,它是一个ArrayAdapter,如:myadapter = new CustomAdapter(this,com.test.SMSBroadcastReceiver.phonenumber_array,com.test.SMSBroadcastReceiver.message_array)
所以我的问题是:我从eclipse发送短信到模拟器。每当myadapter.notifyDataSetChanged();我的BroadcastReceiver在我的应用程序没有运行时被调用(完全停止,没有进程启动,没有活动),我得到一个nullpointer异常。
当我删除myadapter.notifyDataSetChanged();问题消失了。
当应用程序运行时,也没有问题,我的应用程序正确收到新的短信并将其显示在列表中。
所以我的猜测是=当应用程序运行时,BroadcastReceiver可以检测到myadapter,因为应用程序在内存中,因此它可以通知更改。当应用程序没有运行时,它不在内存中,因此BroadcastReceiver无法看到任何myadapter,因此它给出了一个nullpointer异常。这说得通。 所以我试着检查:如果进程在内存中,通知更改,否则,不要通知(因为我的应用程序获取了onCreate()收到的所有短信,所以没有必要。
ActivityManager activityManager = (ActivityManager) context
.getSystemService(context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningProcInfo = activityManager
.getRunningAppProcesses(); for (int i1 = 0; i1 <
runningProcInfo.size(); i1++) {
if (runningProcInfo.get(i1).processName.equals("com.test")) {
com.test.ListActivityClass.myadapter.notifyDataSetChanged();
}
但没有改变。当app未运行时,我仍然有一个nullpointer异常。
最糟糕的是,我试图用phonenumber_array.add替换phonenumber_array(0,“somephonenumber”);和message_array.add(0,“somemessage”);即使应用程序关闭,检查BroadcastReceiver是否在后台运行,我的想法是正确的。在空指针异常之后,我启动了应用程序,并且somephonenumber和somemessage都存在。
我想念什么? BroadcastReceiver是在后台运行,还是仅在应用程序启动时运行?怎么了?
答案 0 :(得分:1)
首先,只要您的流程存在,静态数据成员(以及评论建议的替换,Application
)才会生效。 onReceive()
完成后,您的流程可能会消失几个小时。
如果你想使用静态数据成员作为缓存,那很好,但是持久的数据需要存在于文件系统(数据库,平面文件等)上。
其次,myadapter
不应该是静态数据成员。你正在泄露记忆。
或者:
通过BroadcastReceiver
或
registerReceiver()
以供活动注册
让BroadcastReceiver
发送另一个有序广播,由正在运行的活动(如果它在前台)接收,如this blog post中所述,并在{{3}中进行了演示}}
答案 1 :(得分:0)
您可以创建静态布尔变量onScreen
并在true
方法中将其设置为onResume
,并在false
方法中设置为onPause
。这是了解应用程序是否在屏幕上的最简单方法