Search code examples
javaandroidfileonactivityresultfilepicker

Android app in java crashes when trying to open a text file


I am trying to make a simple text editor for Android in Java. I run into a problem, when tring to open a file.

In this line of my code

File file = new File(getExternalFilesDir(filepath), filename);

I got a null pointer exception:

 java.lang.NullPointerException: name == null
        at java.io.File.<init>(File.java:150)
        at java.io.File.<init>(File.java:124)
        at my.app.texteditor.MainActivity$1.onClick(MainActivity.java:31)

and my app crashes, leaving the filepicker on my android device open.

For me (after some time of trying to debug my code) it seems that the

protected void onActivityResult(int requestCode, int resultCode, Intent data)

function is never called and thus the filepath and filename are never assigned, which generates the exception. Hovever I am not sure whether I detected the problem correctly and I dont know how to fix it.

Here is the (full) code of my main activity - the one where I am trying to open a file:

package my.app.texteditor;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

import java.io.File;

public class MainActivity extends AppCompatActivity {
    String filepath, filename, folder;
    private static final int PICKFILE_RESULT_CODE = 1;
    private static int PICKER_RESULT = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button OpenButton = (Button) findViewById(R.id.OpenButton);
        OpenButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent getContent = new Intent(Intent.ACTION_GET_CONTENT);
                getContent.setType("text/*");
                startActivityForResult(getContent, PICKFILE_RESULT_CODE);
                
                    File file = new File(getExternalFilesDir(filepath), filename);
                    Intent openIntent = new Intent(MainActivity.this, ShowFile.class);
                    openIntent.putExtra("my.app.file", file);
                    startActivity(openIntent);

            }
        });

        Button NewButton = (Button) findViewById(R.id.NewButton);
        NewButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent newIntent = new Intent(MainActivity.this, ShowFile.class);
                startActivity(newIntent);
            }
        });

        if (!StorageHandler.isExternalStorageAvailable() || StorageHandler.isExternalStorageReadOnly()) {
            OpenButton.setEnabled(false);
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        PICKER_RESULT = resultCode;
        if (requestCode == PICKFILE_RESULT_CODE) {
            if (resultCode == RESULT_OK) {
                filepath = data.getData().getPath();
                filename = data.getData().getLastPathSegment();
                int lastPos = filepath.length() - filename.length();
                folder = filepath.substring(0, lastPos);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }


}

When I put this part of my code:

File file = new File(getExternalFilesDir(filepath), filename);
Intent openIntent = new Intent(MainActivity.this, ShowFile.class);
openIntent.putExtra("my.app.file", file);
startActivity(openIntent);

in an if statement, so it will be executed only if the PICKER_RESULT variable is changed in onActivityResult function - like this:

 if(PICKER_RESULT!=-1) {
                    File file = new File(getExternalFilesDir(filepath), filename);
                    Intent openIntent = new Intent(MainActivity.this, ShowFile.class);
                    openIntent.putExtra("my.app.file", file);
                    startActivity(openIntent);
                }

then my android device opens the filepicker, app DOES NOT crash, but I am not able to open a file - the PICKER_RESULT is still set to -1.

So my quesion is, why is the onActivityResult function never called?


Solution

  • You're trying to use the result of the activity in the onClick event handler. This won't work because the activity is started asynchronously. The event handler will keep running until the end, and only then the activity starts.

    All of the code that depends on the activity result should be in onActivityResult (or a method that's called from it)

    startActivityForResult(getContent, PICKFILE_RESULT_CODE);
    
    // MOVE THIS TO onActivityResult                
    File file = new File(getExternalFilesDir(filepath), filename);
    Intent openIntent = new Intent(MainActivity.this, ShowFile.class);
    openIntent.putExtra("my.app.file", file);
    startActivity(openIntent);