add Stop action to download notifications
This commit is contained in:
parent
ae9364ad7e
commit
8fcf135280
4 changed files with 107 additions and 33 deletions
2
app
2
app
|
@ -1 +1 @@
|
||||||
Subproject commit 32c1770c34ecc5e80c5542aeb64ff11312704cea
|
Subproject commit 46bfbd242a841f770a59ec88f9c7fbd94e5a06da
|
|
@ -10,6 +10,7 @@ import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
|
@ -31,6 +32,8 @@ public class DownloadManager {
|
||||||
|
|
||||||
private List<String> completedDownloads = new ArrayList<String>();
|
private List<String> completedDownloads = new ArrayList<String>();
|
||||||
|
|
||||||
|
private Map<String, String> downloadIdOutpointsMap = new HashMap<String, String>();
|
||||||
|
|
||||||
// maintain a map of uris to writtenBytes, so that we check if it's changed and don't flood RN with update events every 500ms
|
// maintain a map of uris to writtenBytes, so that we check if it's changed and don't flood RN with update events every 500ms
|
||||||
private Map<String, Double> writtenDownloadBytes = new HashMap<String, Double>();
|
private Map<String, Double> writtenDownloadBytes = new HashMap<String, Double>();
|
||||||
|
|
||||||
|
@ -144,7 +147,15 @@ public class DownloadManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startDownload(String id, String filename) {
|
private Intent getDeleteDownloadIntent(String uri) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(LbrynetService.ACTION_DELETE_DOWNLOAD);
|
||||||
|
intent.putExtra("uri", uri);
|
||||||
|
intent.putExtra("nativeDelete", true);
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startDownload(String id, String filename, String outpoint) {
|
||||||
if (filename == null || filename.trim().length() == 0) {
|
if (filename == null || filename.trim().length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -152,20 +163,26 @@ public class DownloadManager {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!isDownloadActive(id)) {
|
if (!isDownloadActive(id)) {
|
||||||
activeDownloads.add(id);
|
activeDownloads.add(id);
|
||||||
|
downloadIdOutpointsMap.put(id, outpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
createNotificationChannel();
|
createNotificationChannel();
|
||||||
createNotificationGroup();
|
createNotificationGroup();
|
||||||
|
|
||||||
|
PendingIntent stopDownloadIntent = PendingIntent.getBroadcast(context, 0, getDeleteDownloadIntent(id), PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
||||||
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
|
||||||
// The file URI is used as the unique ID
|
// The file URI is used as the unique ID
|
||||||
builder.setContentIntent(getLaunchPendingIntent(id, context))
|
builder.setColor(ContextCompat.getColor(context, R.color.lbryGreen))
|
||||||
|
.setContentIntent(getLaunchPendingIntent(id, context))
|
||||||
.setContentTitle(String.format("Downloading %s", truncateFilename(filename)))
|
.setContentTitle(String.format("Downloading %s", truncateFilename(filename)))
|
||||||
.setGroup(GROUP_DOWNLOADS)
|
.setGroup(GROUP_DOWNLOADS)
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
.setProgress(MAX_PROGRESS, 0, false)
|
.setProgress(MAX_PROGRESS, 0, false)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download);
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
|
.setOngoing(true)
|
||||||
|
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Stop", stopDownloadIntent);
|
||||||
|
|
||||||
int notificationId = getNotificationId(id);
|
int notificationId = getNotificationId(id);
|
||||||
downloadIdNotificationIdMap.put(id, notificationId);
|
downloadIdNotificationIdMap.put(id, notificationId);
|
||||||
|
@ -194,9 +211,13 @@ public class DownloadManager {
|
||||||
if (builders.containsKey(notificationId)) {
|
if (builders.containsKey(notificationId)) {
|
||||||
builder = builders.get(notificationId);
|
builder = builders.get(notificationId);
|
||||||
} else {
|
} else {
|
||||||
|
PendingIntent stopDownloadIntent = PendingIntent.getBroadcast(context, 0, getDeleteDownloadIntent(id), PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
|
builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
|
||||||
builder.setContentTitle(String.format("Downloading %s", truncateFilename(filename)))
|
builder.setColor(ContextCompat.getColor(context, R.color.lbryGreen))
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW);
|
.setContentTitle(String.format("Downloading %s", truncateFilename(filename)))
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
.setOngoing(true)
|
||||||
|
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Stop", stopDownloadIntent);
|
||||||
builders.put(notificationId, builder);
|
builders.put(notificationId, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +234,9 @@ public class DownloadManager {
|
||||||
.setContentText(String.format("%s", formatBytes(totalBytes)))
|
.setContentText(String.format("%s", formatBytes(totalBytes)))
|
||||||
.setGroup(GROUP_DOWNLOADS)
|
.setGroup(GROUP_DOWNLOADS)
|
||||||
.setProgress(0, 0, false)
|
.setProgress(0, 0, false)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download_done);
|
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||||
|
.setOngoing(false);
|
||||||
|
builder.mActions.clear();
|
||||||
notificationManager.notify(notificationId, builder.build());
|
notificationManager.notify(notificationId, builder.build());
|
||||||
|
|
||||||
if (downloadIdNotificationIdMap.containsKey(id)) {
|
if (downloadIdNotificationIdMap.containsKey(id)) {
|
||||||
|
@ -258,11 +281,13 @@ public class DownloadManager {
|
||||||
.setContentText(String.format("%s", formatBytes(totalBytes)))
|
.setContentText(String.format("%s", formatBytes(totalBytes)))
|
||||||
.setGroup(GROUP_DOWNLOADS)
|
.setGroup(GROUP_DOWNLOADS)
|
||||||
.setProgress(0, 0, false)
|
.setProgress(0, 0, false)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download_done);
|
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||||
notificationManager.notify(notificationId, builder.build());
|
.setOngoing(false);
|
||||||
|
builder.mActions.clear();
|
||||||
|
notificationManager.notify(notificationId, builder.build());
|
||||||
|
|
||||||
// If there are no more downloads and the group exists, set the icon to stop animating
|
// If there are no more downloads and the group exists, set the icon to stop animating
|
||||||
checkGroupDownloadIcon(notificationManager);
|
checkGroupDownloadIcon(notificationManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,11 +320,22 @@ public class DownloadManager {
|
||||||
return completedDownloads;
|
return completedDownloads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOutpointForDownload(String uri) {
|
||||||
|
if (downloadIdOutpointsMap.containsKey(uri)) {
|
||||||
|
return downloadIdOutpointsMap.get(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteDownloadUri(String uri) {
|
public void deleteDownloadUri(String uri) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
activeDownloads.remove(uri);
|
activeDownloads.remove(uri);
|
||||||
completedDownloads.remove(uri);
|
completedDownloads.remove(uri);
|
||||||
|
|
||||||
|
if (downloadIdOutpointsMap.containsKey(uri)) {
|
||||||
|
downloadIdOutpointsMap.remove(uri);
|
||||||
|
}
|
||||||
if (downloadIdNotificationIdMap.containsKey(uri)) {
|
if (downloadIdNotificationIdMap.containsKey(uri)) {
|
||||||
removeDownloadNotification(uri);
|
removeDownloadNotification(uri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,8 @@ public class LbrynetService extends PythonService {
|
||||||
}
|
}
|
||||||
} else if (ACTION_DELETE_DOWNLOAD.equals(action)) {
|
} else if (ACTION_DELETE_DOWNLOAD.equals(action)) {
|
||||||
String uri = intent.getStringExtra("uri");
|
String uri = intent.getStringExtra("uri");
|
||||||
LbrynetService.this.deleteDownload(uri);
|
boolean nativeDelete = intent.getBooleanExtra("nativeDelete", false);
|
||||||
|
LbrynetService.this.deleteDownload(uri, nativeDelete);
|
||||||
} else if (ACTION_CHECK_DOWNLOADS.equals(action)) {
|
} else if (ACTION_CHECK_DOWNLOADS.equals(action)) {
|
||||||
LbrynetService.this.checkDownloads();
|
LbrynetService.this.checkDownloads();
|
||||||
}
|
}
|
||||||
|
@ -212,8 +213,10 @@ public class LbrynetService extends PythonService {
|
||||||
if (streamManagerReady) {
|
if (streamManagerReady) {
|
||||||
Map<String, Object> params = new HashMap<String, Object>();
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
params.put("page_size", 100);
|
params.put("page_size", 100);
|
||||||
params.put("status", "stopped");
|
params.put("reverse", true);
|
||||||
params.put("comparison", "ne");
|
params.put("sort", "added_on");
|
||||||
|
/*params.put("status", "stopped");
|
||||||
|
params.put("comparison", "ne");*/
|
||||||
|
|
||||||
String fileList = Utils.sdkCall("file_list", params);
|
String fileList = Utils.sdkCall("file_list", params);
|
||||||
if (fileList != null) {
|
if (fileList != null) {
|
||||||
|
@ -266,7 +269,7 @@ public class LbrynetService extends PythonService {
|
||||||
File file = new File(downloadPath);
|
File file = new File(downloadPath);
|
||||||
Intent intent = createDownloadEventIntent(uri, outpoint, item.toString());
|
Intent intent = createDownloadEventIntent(uri, outpoint, item.toString());
|
||||||
intent.putExtra("action", "start");
|
intent.putExtra("action", "start");
|
||||||
downloadManager.startDownload(uri, file.getName());
|
downloadManager.startDownload(uri, file.getName(), outpoint);
|
||||||
|
|
||||||
Context context = getApplicationContext();
|
Context context = getApplicationContext();
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
|
@ -286,10 +289,45 @@ public class LbrynetService extends PythonService {
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteDownload(String uri) {
|
private void deleteDownload(String uri, boolean nativeDelete) {
|
||||||
|
final String outpoint = downloadManager.getOutpointForDownload(uri);
|
||||||
|
if (nativeDelete && outpoint != null) {
|
||||||
|
// send call sdk to delete the file on the corresponding outpoint
|
||||||
|
removeDownloadFromManager(uri);
|
||||||
|
|
||||||
|
(new AsyncTask<Void, Void, String>() {
|
||||||
|
protected String doInBackground(Void... param) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
params.put("outpoint", outpoint);
|
||||||
|
params.put("delete_from_download_dir", true);
|
||||||
|
return Utils.sdkCall("file_delete", params);
|
||||||
|
} catch (ConnectException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(String response) {
|
||||||
|
// after deletion, remove the download from the download manager
|
||||||
|
Intent intent = createDownloadEventIntent(uri, outpoint, null);
|
||||||
|
intent.putExtra("action", "abort");
|
||||||
|
|
||||||
|
Context context = getApplicationContext();
|
||||||
|
if (context != null) {
|
||||||
|
context.sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
} else {
|
||||||
|
removeDownloadFromManager(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeDownloadFromManager(String uri) {
|
||||||
if (downloadManager.isDownloadActive(uri)) {
|
if (downloadManager.isDownloadActive(uri)) {
|
||||||
downloadManager.abortDownload(uri);
|
downloadManager.abortDownload(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadManager.deleteDownloadUri(uri);
|
downloadManager.deleteDownloadUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,23 +397,13 @@ public class LbrynetService extends PythonService {
|
||||||
if (!completed && downloadPath != null) {
|
if (!completed && downloadPath != null) {
|
||||||
downloadManager.clearWrittenBytesForDownload(uri);
|
downloadManager.clearWrittenBytesForDownload(uri);
|
||||||
intent.putExtra("action", "start");
|
intent.putExtra("action", "start");
|
||||||
downloadManager.startDownload(uri, file.getName());
|
downloadManager.startDownload(uri, file.getName(), outpoint);
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
context.sendBroadcast(intent);
|
context.sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check download manager uris and clear downloads that may have been cancelled / deleted
|
|
||||||
/*List<String> activeUris = downloadManager.getActiveDownloads();
|
|
||||||
for (int i = 0; i < activeUris.size(); i++) {
|
|
||||||
String activeUri = activeUris.get(i);
|
|
||||||
if (!itemUris.contains(activeUri)) {
|
|
||||||
downloadManager.abortDownload(activeUri);
|
|
||||||
fileListUris.remove(activeUri); // remove URIs from the session that may have been deleted
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
} catch (JSONException ex) {
|
} catch (JSONException ex) {
|
||||||
// pass
|
// pass
|
||||||
Log.e(TAG, ex.getMessage(), ex);
|
Log.e(TAG, ex.getMessage(), ex);
|
||||||
|
|
|
@ -212,17 +212,28 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac
|
||||||
String outpoint = intent.getStringExtra("outpoint");
|
String outpoint = intent.getStringExtra("outpoint");
|
||||||
String fileInfoJson = intent.getStringExtra("file_info");
|
String fileInfoJson = intent.getStringExtra("file_info");
|
||||||
|
|
||||||
if (uri == null || outpoint == null || fileInfoJson == null) {
|
|
||||||
|
if (uri == null || outpoint == null || (fileInfoJson == null && !"abort".equals(downloadAction))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String eventName = null;
|
||||||
|
WritableMap params = Arguments.createMap();
|
||||||
|
params.putString("uri", uri);
|
||||||
|
params.putString("outpoint", outpoint);
|
||||||
|
|
||||||
|
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
|
||||||
|
if ("abort".equals(downloadAction)) {
|
||||||
|
eventName = "onDownloadAborted";
|
||||||
|
if (reactContext != null) {
|
||||||
|
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String eventName = null;
|
|
||||||
JSONObject json = new JSONObject(fileInfoJson);
|
JSONObject json = new JSONObject(fileInfoJson);
|
||||||
WritableMap fileInfo = JSONObjectToMap(json);
|
WritableMap fileInfo = JSONObjectToMap(json);
|
||||||
WritableMap params = Arguments.createMap();
|
|
||||||
params.putString("uri", uri);
|
|
||||||
params.putString("outpoint", outpoint);
|
|
||||||
params.putMap("fileInfo", fileInfo);
|
params.putMap("fileInfo", fileInfo);
|
||||||
|
|
||||||
if (DownloadManager.ACTION_UPDATE.equals(downloadAction)) {
|
if (DownloadManager.ACTION_UPDATE.equals(downloadAction)) {
|
||||||
|
@ -233,7 +244,6 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac
|
||||||
eventName = (DownloadManager.ACTION_START.equals(downloadAction)) ? "onDownloadStarted" : "onDownloadCompleted";
|
eventName = (DownloadManager.ACTION_START.equals(downloadAction)) ? "onDownloadStarted" : "onDownloadCompleted";
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
|
|
||||||
if (reactContext != null) {
|
if (reactContext != null) {
|
||||||
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
|
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue