Samet
Samet

Reputation: 917

When my app is not running (only when not running), why does my BroadcastReceiver give me a nullpointer exception?

I will try to sum up simply because my original code is long. Suppose that My broadcast receiver is like this :

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();
       }
}

In my AndroidManifest.xml, The BroadcastReceiver has the IntentFilter "android.provider.Telephony.SMS_RECEIVED".

My ListActivityClass extends ListActivity, contains a myadapter which is an ArrayAdapter, like : myadapter = new CustomAdapter (this,com.test.SMSBroadcastReceiver.phonenumber_array,com.test.SMSBroadcastReceiver.message_array)

So my problem is : I send an sms from eclipse to emulator. whenever myadapter.notifyDataSetChanged(); is called in my BroadcastReceiver when my application is not running(completely stoped, no process launched, no activities) , I get a nullpointer exception.

When I remove myadapter.notifyDataSetChanged(); the problem is gone.

When the app is running, there is no problem as well, my application gets correctly the new sms received and displays it in the list.

So my guess was = When the app is running, the BroadcastReceiver can detect the myadapter, because the app is in memory, so it can notify changes. when the app isn't running, it is not in memory so BroadcastReceiver can't see any myadapter, so it gives a nullpointer exception. it makes sense. So I tried to check : if the process is in memory, notify changes, else, don't notify ( because my applications gets all the sms received onCreate(), so it is not necessary.

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();
    }

But nothing changed. I still have a nullpointer exception when app is not running.

The worst thing is, I tried to replace phonenumber_array by phonenumber_array.add(0,"somephonenumber"); and message_array.add(0,"somemessage"); to check if a BroadcastReceiver runs in the backround even if the app is closed, my thoughts were correct. After the null pointer exception, I launched the app, and somephonenumber and somemessage were both present.

What do I miss? Does a BroadcastReceiver runs in background, or only when application launches? what is wrong?

Upvotes: 0

Views: 694

Answers (2)

Jin35
Jin35

Reputation: 8612

You can create static boolean variable onScreen and set it to true in onResume method, and set to false in onPause method. It is the easiest way to understand if application is on the screen

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1007584

First, static data members (and the comment-suggested replacement, Application) only live as long as your process lives. Your process may go away microseconds after onReceive() completes.

If you want to use static data members as a cache, that's fine, but durable data needs to live on the filesystem (database, flat file, etc.).

Second, myadapter should not be a static data member. You are leaking memory.

Either:

  • Move this BroadcastReceiver to be registered by the activity via registerReceiver(), or

  • Have this BroadcastReceiver send another ordered broadcast to be picked up by the running activity (if it is in the foreground), as is described in this blog post and is demonstrated in this sample project

Upvotes: 1

Related Questions