Skip to content

Commit

Permalink
Fix #480: Refactor permission request for writing to external storage
Browse files Browse the repository at this point in the history
- Extracted permission handling logic into a reusable method.
- Added support for Android R+ to avoid unnecessary permission requests.
- Displayed a rationale dialog when permission is not granted.
  • Loading branch information
miltonials authored and Binnette committed Dec 12, 2024
1 parent 8fa107e commit fdf0a8b
Showing 1 changed file with 49 additions and 24 deletions.
73 changes: 49 additions & 24 deletions app/src/main/java/net/osmtracker/activity/TrackDetail.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
import net.osmtracker.util.MercatorProjection;

import android.Manifest;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Paint;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import androidx.core.app.ActivityCompat;
Expand Down Expand Up @@ -237,32 +239,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
startActivity(i);
break;
case R.id.trackdetail_menu_export:
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
// TODO: explain why we need permission.
Log.w(TAG, "we should explain why we need write permission");

} else {

// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
RC_WRITE_PERMISSIONS);
break;
}

} else {
if (writeExternalStoragePermissionGranted()) {
exportTrack();
break;
}
break;
case R.id.trackdetail_menu_osm_upload:
i = new Intent(this, OpenStreetMapUpload.class);
i.putExtra(TrackContentProvider.Schema.COL_TRACK_ID, trackId);
Expand All @@ -272,6 +252,51 @@ public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}

/**
* Checks if the external storage write permission is granted.
* If not, it requests the permission and may display a rationale dialog explaining why it is needed.
*
* <p>For devices running Android R (API level 30) and above, this permission is not required,
* so the method will return {@code true} immediately.</p>
*
* @return {@code true} if the write permission is already granted or not required (Android R+),
* {@code false} otherwise.
*/
private boolean writeExternalStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return true;
}
else if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
new AlertDialog.Builder(this)
.setTitle("Permission required")
.setMessage("To export the GPX trace we need to write on the storage.")
.setPositiveButton("Accept", (dialog, which) -> {
// Request the permission again
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
RC_WRITE_PERMISSIONS);
})
.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss())
.show();
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
RC_WRITE_PERMISSIONS);
}
}

return ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}


/**
* Invoke the export track task after external write permissions request.
Expand Down

0 comments on commit fdf0a8b

Please sign in to comment.