Android system permissions are divided into many categories. But when it comes to permission request at runtime from Android 6.0 onward, system permissions are categorized into two categories: Normal and Dangerous:
- Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the permission automatically. List of normal permission can be found HERE.
- Dangerous permissions can give the app access to the user's confidential data. If your app lists a normal permission in its manifest, the system grants the permission automatically. If you list a dangerous permission, the user has to explicitly give approval to your app. List of dangerous permissions is available HERE.
Firstly, just look at AndroidManifest.xml file of this project:
AndroidManifest.xml
As you can see, first permission <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.devexchanges.downloadingfile">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
android.permission.INTERNET
is a normal permission and the seconds one android.permission.WRITE_EXTERNAL_STORAGE
is a dangerous permission. Therefore in the following example, we would request the user to grant it at runtime.
Check and request a runtime permission
checkSelfPermission()
method of ActivityCompat
class, then if permission has not been granted, prompt user by use requestPermissions()
method:
private void requestStoragePermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE);
} else {
Log.i("Main", "Storage permissions have already been granted. Download the file");
downloadFile();
}
}
When running this project, you'll have this alert dialog:
Handle user action after request permission
onRequestPermissionsResult()
. In this project, if user granted the permission, an IMG file will be downloaded to your device:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_STORAGE) {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
downloadFile();
} else {
Toast.makeText(this, "You now can not download the file!", Toast.LENGTH_SHORT).show();
}
}
}
private void downloadFile() {
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Request request = new Request(Uri.parse(DOWNLOAD_URL));
//Get download file name
String fileExtenstion = MimeTypeMap.getFileExtensionFromUrl(DOWNLOAD_URL);
String name = URLUtil.guessFileName(DOWNLOAD_URL, null, fileExtenstion);
//Save file to destination folder
request.setDestinationInExternalPublicDir("/Downloads", name);
enqueue = downloadManager.enqueue(request);
}
Of course, the permission request will be invoked when you click the "Start Download" button, so you call requestStoragePermission()
method here. Remember to check Build.VERSION_CODES
to request this runtime permission:
public void onClick(View view) {
int currentApiVersion = android.os.Build.VERSION.SDK_INT;
if (currentApiVersion >= Build.VERSION_CODES.M) {
requestStoragePermission();
} else {
downloadFile();
}
}
Running this project, If user denied the permission, app will show a Toast
:
And if user granted this permission, your file will be downloaded by
DownloadManager
:
Moreover, user also can grant runtime permission for your app in Settings of their device: