Je suis confronté à un problème d'ouverture du fichier téléchargé après un téléchargement réussi via l'API DownloadManager. Dans mon code:
Uri uri=Uri.parse("http://www.nasa.gov/images/content/206402main_jsc2007e113280_hires.jpg");
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.mkdirs();
lastDownload = mgr.enqueue(new DownloadManager.Request(uri)
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |
DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle("app update")
.setDescription("New version 1.1")
.setShowRunningNotification(true)
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "a.apk"));
Cursor c=mgr.query(new DownloadManager.Query().setFilterById(lastDownload));
if(c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)) == 8) {
try {
mgr.openDownloadedFile(c.getLong(c.getColumnIndex(DownloadManager.COLUMN_ID)));
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("MGR", "Error");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("MGR", "Error");
}
}
Le problème est quand if(c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))==8)
est-il évoqué. J'ai obtenu le statut -1 et une exception. Existe-t-il un meilleur moyen, comment ouvrir des fichiers téléchargés avec DownloadManager API
? Dans mon exemple, je télécharge une grande image, dans une situation réelle, je téléchargerais un fichier APK
et je dois afficher une boîte de dialogue d'installation immédiatement après la mise à jour.
Edit: J'ai compris que status = 8 est après un téléchargement réussi. Vous pouvez avoir une approche différente de "vérification du téléchargement réussi"
Merci
Vous devez enregistrer un récepteur lorsque le téléchargement est terminé:
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
et un gestionnaire BroadcastReciever
BroadcastReceiver onComplete=new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
// Do Something
}
};
Achetez au lieu de tout arnaquer, je vous suggère de vérifier ceci .
MODIFIER:
À titre de suggestion, je ne recommanderais pas encore d'utiliser l'API 9: http://developer.Android.com/resources/dashboard/platform-versions.html
Il existe des moyens de contourner cela, en créant votre propre gestionnaire de téléchargement, comme je l'ai fait, parce que nous ne voulions pas aliéner la plupart des utilisateurs de notre base Android, pour cela, vous aurez besoin de: Créer AsyncTask qui gère le téléchargement du fichier.
et je recommanderai de créer une boîte de dialogue de téléchargement (si vous dites que c'est un gros fichier, je le ferais apparaître dans la zone de notification).
et que vous devrez gérer l'ouverture du fichier:
protected void openFile(String fileName) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(new File(fileName)),
"MIME-TYPE");
startActivity(install);
}
Problème
API Android DownloadManager - ouverture du fichier après le téléchargement?
Solution
/**
* Used to download the file from url.
* <p/>
* 1. Download the file using Download Manager.
*
* @param url Url.
* @param fileName File Name.
*/
public void downloadFile(final Activity activity, final String url, final String fileName) {
try {
if (url != null && !url.isEmpty()) {
Uri uri = Uri.parse(url);
activity.registerReceiver(attachmentDownloadCompleteReceive, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setMimeType(getMimeType(uri.toString()));
request.setTitle(fileName);
request.setDescription("Downloading attachment..");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
DownloadManager dm = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
dm.enqueue(request);
}
} catch (IllegalStateException e) {
Toast.makeText(activity, "Please insert an SD card to download file", Toast.LENGTH_SHORT).show();
}
}
/**
* Used to get MimeType from url.
*
* @param url Url.
* @return Mime Type for the given url.
*/
private String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
type = mime.getMimeTypeFromExtension(extension);
}
return type;
}
/**
* Attachment download complete receiver.
* <p/>
* 1. Receiver gets called once attachment download completed.
* 2. Open the downloaded file.
*/
BroadcastReceiver attachmentDownloadCompleteReceive = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
openDownloadedAttachment(context, downloadId);
}
}
};
/**
* Used to open the downloaded attachment.
*
* @param context Content.
* @param downloadId Id of the downloaded file to open.
*/
private void openDownloadedAttachment(final Context context, final long downloadId) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
String downloadLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
String downloadMimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
if ((downloadStatus == DownloadManager.STATUS_SUCCESSFUL) && downloadLocalUri != null) {
openDownloadedAttachment(context, Uri.parse(downloadLocalUri), downloadMimeType);
}
}
cursor.close();
}
/**
* Used to open the downloaded attachment.
* <p/>
* 1. Fire intent to open download file using external application.
*
* 2. Note:
* 2.a. We can't share fileUri directly to other application (because we will get FileUriExposedException from Android7.0).
* 2.b. Hence we can only share content uri with other application.
* 2.c. We must have declared FileProvider in manifest.
* 2.c. Refer - https://developer.Android.com/reference/Android/support/v4/content/FileProvider.html
*
* @param context Context.
* @param attachmentUri Uri of the downloaded attachment to be opened.
* @param attachmentMimeType MimeType of the downloaded attachment.
*/
private void openDownloadedAttachment(final Context context, Uri attachmentUri, final String attachmentMimeType) {
if(attachmentUri!=null) {
// Get Content Uri.
if (ContentResolver.SCHEME_FILE.equals(attachmentUri.getScheme())) {
// FileUri - Convert it to contentUri.
File file = new File(attachmentUri.getPath());
attachmentUri = FileProvider.getUriForFile(activity, "com.freshdesk.helpdesk.provider", file);;
}
Intent openAttachmentIntent = new Intent(Intent.ACTION_VIEW);
openAttachmentIntent.setDataAndType(attachmentUri, attachmentMimeType);
openAttachmentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
context.startActivity(openAttachmentIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(context, context.getString(R.string.unable_to_open_file), Toast.LENGTH_LONG).show();
}
}
}
Initialiser les détails de FileProvider
Déclarer FileProvider dans AndroidManifest
<provider
Android:name="Android.support.v4.content.FileProvider"
Android:authorities="com.freshdesk.helpdesk.provider"
Android:exported="false"
Android:grantUriPermissions="true">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/file_path"/>
</provider>
Ajoutez le fichier suivant "res -> xml -> file_path.xml"
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<external-path name="attachment_file" path="."/>
</paths>
Remarque
Pourquoi utiliser FileProvider
Provblem avec l'utilisation de "DownloadManager.getUriForDownloadedFile (long id)"
Référence
rappelez-vous d'ajouter <uses-permission Android:name="Android.permission.REQUEST_INSTALL_PACKAGES" />
à votre fichier AndroidMannifest.xml