added asyndownloader to use DownloadManager when possible
This commit is contained in:
parent
13c90e6c4a
commit
dbd4c467f8
@ -21,8 +21,8 @@
|
||||
package org.fdroid.fdroid.net;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
@ -38,6 +38,7 @@ import org.fdroid.fdroid.data.SanitizedFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
@ -193,11 +194,17 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener {
|
||||
Utils.DebugLog(TAG, "Downloading apk from " + remoteAddress + " to " + localFile);
|
||||
|
||||
try {
|
||||
if (canUseDownloadManager(new URL(remoteAddress))) {
|
||||
// If we can use Android's DownloadManager, let's use it, because
|
||||
// of better OS integration, reliability, and async ability
|
||||
dlWrapper = new AsyncDownloader(context, this, curApk.apkName, remoteAddress, localFile);
|
||||
} else {
|
||||
Downloader downloader = DownloaderFactory.create(context, remoteAddress, localFile);
|
||||
dlWrapper = new AsyncDownloadWrapper(downloader, this);
|
||||
}
|
||||
|
||||
dlWrapper.download();
|
||||
return true;
|
||||
|
||||
} catch (IOException e) {
|
||||
onErrorDownloading(e.getLocalizedMessage());
|
||||
}
|
||||
@ -205,6 +212,17 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if we can use Android's DownloadManager to download the APK, instead of
|
||||
* a downloader returned from DownloadFactory.
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
private boolean canUseDownloadManager(URL url) {
|
||||
return Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO
|
||||
&& !DownloaderFactory.isOnionAddress(url);
|
||||
}
|
||||
|
||||
private void sendMessage(String type) {
|
||||
sendProgressEvent(new ProgressListener.Event(type));
|
||||
}
|
||||
|
134
F-Droid/src/org/fdroid/fdroid/net/AsyncDownloader.java
Normal file
134
F-Droid/src/org/fdroid/fdroid/net/AsyncDownloader.java
Normal file
@ -0,0 +1,134 @@
|
||||
package org.fdroid.fdroid.net;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import org.fdroid.fdroid.data.SanitizedFile;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A downloader that uses Android's DownloadManager to perform a download.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
public class AsyncDownloader extends AsyncDownloadWrapper {
|
||||
private final Context context;
|
||||
private final DownloadManager dm;
|
||||
private SanitizedFile localFile;
|
||||
private String remoteAddress;
|
||||
private String appName;
|
||||
private Listener listener;
|
||||
|
||||
private long downloadId = -1;
|
||||
|
||||
/**
|
||||
* Normally the listener would be provided using a setListener method.
|
||||
* However for the purposes of this async downloader, it doesn't make
|
||||
* sense to have an async task without any way to notify the outside
|
||||
* world about completion. Therefore, we require the listener as a
|
||||
* parameter to the constructor.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public AsyncDownloader(Context context, Listener listener, String appName, String remoteAddress, SanitizedFile localFile) {
|
||||
super(null, listener);
|
||||
this.context = context;
|
||||
this.appName = appName;
|
||||
this.remoteAddress = remoteAddress;
|
||||
this.listener = listener;
|
||||
this.localFile = localFile;
|
||||
|
||||
if (appName == null || appName.trim().length() == 0) {
|
||||
this.appName = remoteAddress;
|
||||
}
|
||||
|
||||
dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download() {
|
||||
// set up download request
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(remoteAddress));
|
||||
request.setTitle(appName);
|
||||
|
||||
if (listener != null) {
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
|
||||
intentFilter.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);
|
||||
context.registerReceiver(downloadReceiver, intentFilter);
|
||||
}
|
||||
|
||||
downloadId = dm.enqueue(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytesRead() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalBytes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attemptCancel() {
|
||||
if (downloadId >= 0) dm.remove(downloadId);
|
||||
}
|
||||
|
||||
// Broadcast receiver to receive broadcasts from the download manager
|
||||
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (listener == null) return; // no point if no-one is listening
|
||||
|
||||
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
|
||||
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
|
||||
if (id == downloadId) {
|
||||
context.unregisterReceiver(this);
|
||||
|
||||
// clear the notification
|
||||
dm.remove(id);
|
||||
|
||||
try {
|
||||
// write the downloaded file to the expected location
|
||||
ParcelFileDescriptor fd = dm.openDownloadedFile(id);
|
||||
InputStream is = new FileInputStream(fd.getFileDescriptor());
|
||||
OutputStream os = new FileOutputStream(localFile);
|
||||
byte[] buffer = new byte[1024];
|
||||
int count = 0;
|
||||
while ((count = is.read(buffer, 0, buffer.length)) > 0) {
|
||||
os.write(buffer, 0, count);
|
||||
}
|
||||
os.close();
|
||||
|
||||
listener.onDownloadComplete();
|
||||
} catch (IOException e) {
|
||||
listener.onErrorDownloading(e.getLocalizedMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(intent.getAction())) {
|
||||
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
|
||||
if (id == downloadId) {
|
||||
// TODO - display app details screen for this app
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -51,7 +51,7 @@ public class DownloaderFactory {
|
||||
return "bluetooth".equalsIgnoreCase(url.getProtocol());
|
||||
}
|
||||
|
||||
private static boolean isOnionAddress(URL url) {
|
||||
static boolean isOnionAddress(URL url) {
|
||||
return url.getHost().endsWith(".onion");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user