5

I am trying to export the results of a factorial calculation in a txt file. I found this code that looked quite straight forward from this article here. However I'm getting the error on the title. What am I doing wrong?

I have typed this into the manifest:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

And this is my code related to saving:

    public void save(View v) {
     if(numOnRAM!=-1) {
         EditText text = (EditText) findViewById(R.id.resultTextBox);
         String data = text.getText().toString();
         generateNoteOnSD(this,"fact"+numOnRAM+"Results.txt", data);
     }
}

public void generateNoteOnSD(Context context, String sFileName, String sBody) {
    try {
        File root = new File(Environment.getExternalStorageDirectory(), "Notes");
        if (!root.exists()) {
            root.mkdirs();
        }
        File gpxfile = new File(root, sFileName);
        FileWriter writer = new FileWriter(gpxfile);
        writer.append(sBody);
        writer.flush();
        writer.close();
        Toast.makeText(context, "File "+sFileName+" saving success!", Toast.LENGTH_LONG).show();

    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();//After adding this 
//toast message did I realise the error thar occurs.

    }
}
Nick
  • 241
  • 1
  • 2
  • 10
  • Is the result of `root.mkdirs()` successful? And what API are you targeting? If it's API 23 or above [you'll need to request permissions at runtime](https://developer.android.com/training/permissions/requesting.html) – Michael Dodd Nov 17 '17 at 11:53
  • @MichaelDodd Im sorry but I've just started learning android. How to find out if `root.mkdirs()` is succesful? How to find out what API I am targeting after I created the project? Thank you. – Nick Nov 17 '17 at 11:57
  • [mkdirs()](https://docs.oracle.com/javase/7/docs/api/java/io/File.html#mkdirs()) returns a boolean, `true` if the directories were created, `false` if not. You can find your API target level in your app's `build.gradle` file. – Michael Dodd Nov 17 '17 at 11:59
  • @MichaelDodd Is it this one `targetSdkVersion 26`? I cant find any new directory. – Nick Nov 17 '17 at 12:01
  • Yes. That means you'll need to request permission to write to external stoage at runtime. – Michael Dodd Nov 17 '17 at 12:02
  • @MichaelDodd What would I have to do in order to achieve it? – Nick Nov 17 '17 at 12:02

3 Answers3

11

As discussed in the comments, you need to request permissions at runtime to allow your app to write to external storage. You can check if your app has the permission already by using checkSelfPermission(). For example:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
    // Do the file write
} else {
    // Request permission from the user
    ActivityCompat.requestPermissions(this, 
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
    ...
}

In order to handle this permission request, you'll also need to implement onRequestPermissionsResult() from OnRequestPermissionsResultCallback, for example:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case 0:
            // Re-attempt file write
    }
}

Read the documentation for full information.

Michael Dodd
  • 10,102
  • 12
  • 51
  • 64
5

I think you have to request permission on runtime. Please check the code below:

 final private int REQUEST_CODE_ASK_PERMISSIONS = 123;

      private void requestPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
            ActivityCompat
                    .requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_ASK_PERMISSIONS);
        }
    }

        @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE_ASK_PERMISSIONS:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission Granted
                    Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT)
                            .show();
                } else {
                    // Permission Denied
                    Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT)
                            .show();
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
Eby Cloudins
  • 111
  • 8
0

For anyone having the same issue, you can remove the android:MaxSdkVersion attribute from the merged manifest as follows.

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    tools:remove="android:maxSdkVersion" />