Comme je suis nouveau dans Android Development, j'essaie de faire une application simple en utilisant DownloadManager.
Voici le code
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback{
Button btn;
private long referenceID;
private DownloadManager downloadManager;
private static final int PERMISSION_REQUEST_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (checkPermission())
{
/*** If Storage Permission Is Given, Check External storage is available for read and write***/
Uri image_uri = Uri.parse("https://unifiedclothes.com/Unifiedclothes/App_Gallery/thumb_8_121432471036-1432471036-SC-505.jpg");
referenceID = DownloadImage(image_uri);
} else {
requestPermission();
}
}
else{
Toast.makeText(MainActivity.this,"Permission Is Granted..",Toast.LENGTH_SHORT).show();
}
}
});
registerReceiver(receiver,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)){
DownloadManager.Query ImageDownloadQuery = new DownloadManager.Query();
//set the query filter to our previously Enqueued download
ImageDownloadQuery.setFilterById(referenceID);
//Query the download manager about downloads that have been requested.
Cursor cursor = downloadManager.query(ImageDownloadQuery);
if(cursor.moveToFirst()){
Toast.makeText(MainActivity.this,DownloadStatus(cursor),Toast.LENGTH_SHORT).show();
}
}
}
};
private String DownloadStatus(Cursor cursor){
//column for download status
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursor.getInt(columnIndex);
//column for reason code if the download failed or paused
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int reason = cursor.getInt(columnReason);
String statusText = "";
String reasonText = "";
switch(status){
case DownloadManager.STATUS_FAILED:
statusText = "STATUS_FAILED";
switch(reason){
case DownloadManager.ERROR_CANNOT_RESUME:
reasonText = "ERROR_CANNOT_RESUME";
break;
case DownloadManager.ERROR_DEVICE_NOT_FOUND:
reasonText = "ERROR_DEVICE_NOT_FOUND";
break;
case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
reasonText = "ERROR_FILE_ALREADY_EXISTS";
break;
case DownloadManager.ERROR_FILE_ERROR:
reasonText = "ERROR_FILE_ERROR";
break;
case DownloadManager.ERROR_HTTP_DATA_ERROR:
reasonText = "ERROR_HTTP_DATA_ERROR";
break;
case DownloadManager.ERROR_INSUFFICIENT_SPACE:
reasonText = "ERROR_INSUFFICIENT_SPACE";
break;
case DownloadManager.ERROR_TOO_MANY_REDIRECTS:
reasonText = "ERROR_TOO_MANY_REDIRECTS";
break;
case DownloadManager.ERROR_UNHANDLED_HTTP_CODE:
reasonText = "ERROR_UNHANDLED_HTTP_CODE";
break;
case DownloadManager.ERROR_UNKNOWN:
reasonText = "ERROR_UNKNOWN";
break;
}
break;
case DownloadManager.STATUS_PAUSED:
statusText = "STATUS_PAUSED";
switch(reason){
case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
reasonText = "PAUSED_QUEUED_FOR_WIFI";
break;
case DownloadManager.PAUSED_UNKNOWN:
reasonText = "PAUSED_UNKNOWN";
break;
case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
reasonText = "PAUSED_WAITING_FOR_NETWORK";
break;
case DownloadManager.PAUSED_WAITING_TO_RETRY:
reasonText = "PAUSED_WAITING_TO_RETRY";
break;
}
break;
case DownloadManager.STATUS_PENDING:
statusText = "STATUS_PENDING";
break;
case DownloadManager.STATUS_SUCCESSFUL:
statusText = "Image Saved Successfully";
//reasonText = "Filename:\n" + filename;
Toast.makeText(MainActivity.this, "Download Status:" + "\n" + statusText + "\n" + reasonText, Toast.LENGTH_SHORT).show();
break;
}
return statusText + reasonText;
}
private long DownloadImage(Uri uri){
long downloadReference;
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
//Setting title of request
request.setTitle("Image Download");
//Setting description of request
request.setDescription("Image download using DownloadManager.");
request.setDestinationInExternalPublicDir(getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/NewFile","sample2.jpg");
//request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
downloadReference = downloadManager.enqueue(request);
return downloadReference;
}
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(MainActivity.this, Android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
private void requestPermission() {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Uri image_uri = Uri.parse("https://www.dccomics.com/sites/default/files/Char_GetToKnow_Batman80_5ca54cb83a27a6.53173051.png");
referenceID = DownloadImage(image_uri);
}
else {
Toast.makeText(MainActivity.this, "Permission Denied... \n You Should Allow External Storage Permission To Download Images.", Toast.LENGTH_LONG).show();
}
}
}
}
Cela fonctionne bien lorsque je l'exécute sur n'importe quel appareil inférieur à l'API 29 (mon appareil de test était le Nexus 5X, l'émulateur ApI 28). Mais lorsque je l'exécute sur le Nexus 5X, l'API 29, l'application se bloque. Voici les journaux:
2019-09-24 20:51:46.354 11322-11344/? E/DatabaseUtils: Writing exception to parcel
Java.lang.IllegalStateException: Not one of standard directories: /storage/emulated/0/Android/data/com.blz.prisoner.downloadmanager/files/Pictures/NewFile
at com.Android.providers.downloads.DownloadProvider.call(DownloadProvider.Java:651)
at Android.content.ContentProvider.call(ContentProvider.Java:2152)
at Android.content.ContentProvider$Transport.call(ContentProvider.Java:477)
at Android.content.ContentProviderNative.onTransact(ContentProviderNative.Java:277)
at Android.os.Binder.execTransactInternal(Binder.Java:1021)
at Android.os.Binder.execTransact(Binder.Java:994)
2019-09-24 20: 51: 46.355 15023-15023/com.blz.prisoner.downloadmanager D/AndroidRuntime: arrêt de la machine virtuelle
--------- beginning of crash
2019-09-24 20:51:46.360 15023-15023/com.blz.prisoner.downloadmanager E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.blz.prisoner.downloadmanager, PID: 15023
Java.lang.IllegalStateException: Not one of standard directories: /storage/emulated/0/Android/data/com.blz.prisoner.downloadmanager/files/Pictures/NewFile
at Android.os.Parcel.createException(Parcel.Java:2079)
at Android.os.Parcel.readException(Parcel.Java:2039)
at Android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.Java:188)
at Android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.Java:140)
at Android.content.ContentProviderProxy.call(ContentProviderNative.Java:658)
at Android.content.ContentProviderClient.call(ContentProviderClient.Java:558)
at Android.content.ContentProviderClient.call(ContentProviderClient.Java:546)
at Android.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.Java:567)
at com.blz.prisoner.downloadmanager.MainActivity.DownloadImage(MainActivity.Java:206)
at com.blz.prisoner.downloadmanager.MainActivity.access$200(MainActivity.Java:29)
at com.blz.prisoner.downloadmanager.MainActivity$1.onClick(MainActivity.Java:60)
at Android.view.View.performClick(View.Java:7140)
at Android.view.View.performClickInternal(View.Java:7117)
at Android.view.View.access$3500(View.Java:801)
at Android.view.View$PerformClick.run(View.Java:27351)
at Android.os.Handler.handleCallback(Handler.Java:883)
at Android.os.Handler.dispatchMessage(Handler.Java:100)
at Android.os.Looper.loop(Looper.Java:214)
at Android.app.ActivityThread.main(ActivityThread.Java:7356)
at Java.lang.reflect.Method.invoke(Native Method)
at com.Android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.Java:492)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:930)
Je pense que le problème est en ligne "request.setDestinationInExternalPublicDir (getExternalFilesDir (Environment.DIRECTORY_PICTURES) +" /NewFile","sample2.jpg"); "in DownloadImage (Uri uri)) fonction. Comment résoudre le problème??
Un autre problème est que lorsque j'exécute l'application sur l'appareil en dessous de l'API 29, elle fonctionne bien, mais lorsque je clique sur la notification après avoir terminé le téléchargement, elle n'ouvre pas l'image sur la galerie/sur le dossier où elle a été enregistrée.
changer compileSdkVersion
et targetSdkVersion
de 29 à 28 a résolu mon problème.
J'ai résolu juste en utilisant:
setDestinationInExternalFilesDir(context, relativePath, filename);
Au lieu de:
setDestinationInExternalPublicDir(relativePath, filename);
Mon chemin relatif est:
Environment.getExternalStorageDirectory().getPath() + "MyExternalStorageAppPath"
J'ai également dans mon manifeste:
Android:requestLegacyExternalStorage="true"
Pour utiliser la gestion du stockage hérité (stockage partagé) au lieu de la nouvelle gestion du stockage (stockage étendu) utilisée à partir de Android 10 et supérieur).