itsAdzy
itsAdzy

Reputation: 33

Null Pointer Exception when writing to a File - Android Studio

My app crashes every time I go to send the data gathered by the sensor. The error I am given is as follows:

06-20 14:50:00.784  22983-22983/com.example.adam.proj2 E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
        at com.example.adam.proj2.SensorActivity.onClick(SensorActivity.java:124)
        at android.view.View.performClick(View.java:3549)
        at android.view.View$PerformClick.run(View.java:14393)
        at android.os.Handler.handleCallback(Handler.java:605)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:4944)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
        at dalvik.system.NativeStart.main(Native Method)

Here is the code for gathering the sensor data:

 public void onSensorChanged(SensorEvent event) {
    float x = event.values[0];
    ArrayList<Float> enrolAcc = new ArrayList<>();
    ArrayList<Float> authAcc = new ArrayList<>();
    TextView textEnrol = (TextView) findViewById(R.id.textView);
    if (choice == 1) {
        mPreviousAcc = mCurrentAcc;
        mCurrentAcc = (float) Math.sqrt((double) (x * x));
        float delta = mCurrentAcc - mPreviousAcc;
        mDiffAcc = mDiffAcc * 0.9f + delta;
        if (enrolAcc.size() < 100) {
            enrolAcc.add(x);

        } else {
            enrolAcc.remove(0);
            enrolAcc.add(x);
        }
        walkData = enrolAcc.toString();
        textEnrol.setText(walkData);
    }

Here is the code for writing to the file (this happens onClick of a button):

 public void onClick(View v) {
    switch (v.getId()) {
        case R.id.enrolBtn:
            choice = 1;
            Toast.makeText(this, "Enrolment Mode Selected", Toast.LENGTH_SHORT).show();
            break;
        case R.id.authBtn:
            choice = 2;
            Toast.makeText(this, "Authentication Service Starting", Toast.LENGTH_SHORT).show();
            break;
        case R.id.sendBtn:
            choice = 3;
            String baseDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
            String fileName = "Walk Data.csv";
            String filePath = baseDir + File.separator + fileName;
            File f = new File(filePath);
            FileOutputStream out = null;
            try {
                out = new FileOutputStream(f);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            try {
                out.write(walkData.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            android.net.Uri u1 = Uri.fromFile(f);
            Intent sendIntent = new Intent(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_STREAM, u1);
            sendIntent.setType("text/html");
            startActivity(sendIntent);
            break;
    }
}

From what I can see the exception is generated by the out.write method? The array list holding the sensor values is stored in the walkData string so that the string can be then written in the csv file stored on the external device storage. I would like the data to be in CSV format.

I am stumped and cannot figure out how to prevent this, any help would be much appreciated.

Upvotes: 2

Views: 2935

Answers (2)

TDG
TDG

Reputation: 6161

You get the error because you are trying to write to a READ ONLY file.
The line out = new FileOutputStream(f) throws an exception: java.io.FileNotFoundException: /storage/sdcard/Walk Data.csv: open failed: EROFS (Read-only file system), but you actually ignore it, so out = NULL and then you get the other exception.
Move your file to a place where you can write to it -

    String fileName = "Walk Data.csv";
    String baseDir = getFilesDir() + "/" + fileName;
    File f = new File(baseDir);

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 692043

Look at the code:

        try {
            out = new FileOutputStream(f);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            out.write(walkData.getBytes());

The exception is thrown at the last line. So, what could possibly be wrong at that line?

out could be null. out will be null if the file is not found, since you catch that exception and pretend nothing wrong happened at the line before, leaving out as null. You shouldn't try to use outif you just failed to initialize it. The try block should ensclose all the lines using out, and not just the line initializing it.

walkDatacould also be null. But since we don't know where it comes from, we can't say. Use your debugger to know which is null. And whatever the answer is, fix your exception handling code. It should look like

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(f);
            out.write(walkData.getBytes());

            android.net.Uri u1 = Uri.fromFile(f);
            Intent sendIntent = new Intent(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_STREAM, u1);
            sendIntent.setType("text/html");
            startActivity(sendIntent);
        } catch (IOException e) {
            // TODO signal the error to the user. Printing a stack trace is not enough
        }
        finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // TODO signal the error to the user. Printing a stack trace is not enough
                }
             }
        }

Upvotes: 0

Related Questions