1

I have an android app that I have just changed from using:

String path = Environment.getExternalStorageDirectory();

to:

String path = context.getExternalFilesDir(null);

Both of these memory locations are "external" ( I am testing on phones both with and without SD card slots).

My previous version worked perfectly with no errors, the new code occassionally throws a null pointer exception:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getExternalFilesDir(java.lang.String)' on a null object reference

The fact that it only does this periodically sujects that sometimes the external portion of the built in memory is not mounted, but the previous version was using the same memory?

Really not sure what could cause this issue, any help appreciated.

Some code:

public class UploadGPSAlarmReceiver extends BroadcastReceiver {

    private static final String TAG = "MicRecordUploadAlarm";

    TransferUtility mTransferUtility;
    Encryption mEncryption;
    Context mContext;
    String encryptedPath;
    static String folder = "/GPS/";

    @Override
    public void onReceive(Context context, Intent intent) {

        Log.d(TAG, "onReceive: ");

        mContext = context;
        mEncryption = new Encryption();
        mTransferUtility = Util.getTransferUtility(mContext);

        Calendar c = Calendar.getInstance();
        //System.out.println("Current time => " + c.getTime());

        SimpleDateFormat df = new SimpleDateFormat("ddMMyyyy");
        String formattedDate = df.format(c.getTime());

        String path = mContext.getExternalFilesDir(null) + "/videoDIARY/Location/";

        File directory = new File(path);


        if(!directory.exists()){
            directory.mkdirs();
        }

} 

The BroadcastReceiver is called from my Main activity, in a method which is called during onCreate:

Intent intent = new Intent(this, UploadGPSAlarmReceiver.class);

Because this only happens periodically, and from the helpful comments below ( thanks everyone! ), I am deducing that what is happening is my app is launched, everything runs smoothly, my app moves into the background a day or so later, and when the BroadcastReceiver is fired the Main Activity that the context is passed from is no longer instantiated and the app crashes because context is null.

I can think of a few ways of dealing with this, but would be interested in peoples opinions for the best way of doing it? I could make Main Activity a static instance? I could get Application context instead of using Activity context?

Geordie Wicks
  • 1,065
  • 1
  • 11
  • 27
  • It looks like `context` is sometimes null. How and where do you obtain a Context object? – Dmitry Akishin Oct 04 '17 at 23:42
  • I have added some code @DmitryAkishin....the context is passed from where the BroadcastReceiver is called....am I doing something wrong? – Geordie Wicks Oct 04 '17 at 23:48
  • Just add a null check on the Context – OneCricketeer Oct 04 '17 at 23:51
  • @cricket_007, yeah I have thought about adding null checking, but having to check context for null everywhere you use it seems a bit crazy, especially because it is explictly passed to the method it is being used in.... I figured I must be doing something wrong somewhere – Geordie Wicks Oct 04 '17 at 23:53
  • Show where it's passed. You don't need it everywhere, but wherever it's passed from, it's apparently not set – OneCricketeer Oct 04 '17 at 23:56
  • Are you passing something like `MainActivity.this`, `getContext()`, `getBaseContext()`, `getApplicationContext()` ? – Barns Oct 05 '17 at 00:12
  • @Barns52 Well it's a BroadcastReceiver so `onReceive()` is invoked by the system, not manually. So it looks like the null context is sometimes passed as an argument. – Dmitry Akishin Oct 05 '17 at 00:18
  • @GeordieWicks Try getting context from an Application extention [like this](https://stackoverflow.com/questions/987072/using-application-context-everywhere) – Dmitry Akishin Oct 05 '17 at 00:24
  • @DmitryAkishin, yeah that sounds very doable... no problems making a static instance of MainActivity? – Geordie Wicks Oct 05 '17 at 00:36
  • I found this comment that might help: >It may be an Application Context, but it is a restricted version of that Context. In the Android source code for Context this is referred to as ReceiverRestrictedContext and this Context doesn't allow certain operations like registerReceiver() and bindService(). If you really need an Application Context in onReceive() then you need to call context.getApplicationContext() – David Wasser May 23 '12 at 16:08 > > > – Barns Oct 05 '17 at 00:37
  • thanks @Barns52..... that is the question, should I use Application context, or make the calling activity static so context does not disappear? Not sure what is the best way to do it. – Geordie Wicks Oct 05 '17 at 00:39
  • 1
    Yes, `context.getApplicationContext()` might do the trick. Better try that before writing your own Application class. Btw @GeordieWicks why would you want a static instance of MainActivity? – Dmitry Akishin Oct 05 '17 at 00:41
  • I would stay away from static, because from what you said in your edit and what I have read the context you receive might be no longer valid. I would try the context.getApplicationContext() and see if that solves your issue. – Barns Oct 05 '17 at 00:41
  • As a side note, you should **never** make Activities static as you leak memory this way. If you want Context, write a custom Application class, declare it in the Manifest, and get Context from it. – Dmitry Akishin Oct 05 '17 at 00:46
  • @DmitryAkishin, wouldn't using context.getApplicationContext() run into the exact same problem? Its using the same context that is passed to the Broadcast Receiver, so it doesn't matter if you're calling getApplicationContext, or getExternalFilesDir, you would still get a null pointer error? – Geordie Wicks Oct 05 '17 at 00:59
  • @GeordieWicks Well, as @Barns52 pointed out, the passed context is a restricted version of Context and maybe trying to call ` getExternalFilesDir` leads to an NPE. And maybe `context.getApplicationContext()` will solve this. – Dmitry Akishin Oct 05 '17 at 01:09
  • @DmitryAkishin, thanks a lot, I'll try it out and get back to everyone! I really appreciate the responses :) – Geordie Wicks Oct 05 '17 at 01:17

0 Answers0