From 0ca90d17a3e8ba9ef299dc8b8dc962eaef1f1b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C3=87erri?= <64997243+deniscerri@users.noreply.github.com> Date: Sat, 15 Oct 2022 23:23:20 +0200 Subject: [PATCH] added cancel button on download notification and fixed servive bugs when app was killed and reopened --- app/src/main/AndroidManifest.xml | 1 + .../deniscerri/ytdlnis/DownloaderService.java | 8 ++- .../com/deniscerri/ytdlnis/MainActivity.java | 30 +++++++--- .../ytdlnis/page/DownloadsFragment.java | 41 +++++++++++-- .../deniscerri/ytdlnis/page/HomeFragment.java | 29 +++++---- .../receiver/NotificationReceiver.java | 59 +++++++++++++++++++ .../ytdlnis/util/NotificationUtil.java | 14 +++++ 7 files changed, 154 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/receiver/NotificationReceiver.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 44deca19..3b56dea1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -49,6 +49,7 @@ android:name=".DownloaderService" android:enabled="true" android:exported="false" /> + \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/DownloaderService.java b/app/src/main/java/com/deniscerri/ytdlnis/DownloaderService.java index 79700225..95873812 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/DownloaderService.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/DownloaderService.java @@ -124,10 +124,10 @@ public class DownloaderService extends Service { @Override - public boolean onUnbind(Intent intent) { + public void onDestroy() { + super.onDestroy(); stopForeground(true); stopSelf(); - return super.onUnbind(intent); } public class LocalBinder extends Binder implements IDownloaderService { @@ -171,7 +171,9 @@ public class DownloaderService extends Service { YoutubeDL.getInstance().destroyProcessById(downloadProcessID); compositeDisposable.clear(); //stopForeground(true); - if (cancelAll) onDownloadCancelAll(); + if (cancelAll) { + onDownloadCancelAll(); + } }catch(Exception err){ Log.e(TAG, err.getMessage()); } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java index b990a5aa..9623951c 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java @@ -131,6 +131,17 @@ public class MainActivity extends AppCompatActivity{ handleIntents(intent); } + @Override + protected void onDestroy() { + super.onDestroy(); + try { + iDownloaderService.removeActivity(this); + context.getApplicationContext().unbindService(serviceConnection); + }catch (Exception e){ + e.printStackTrace(); + } + } + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); @@ -181,6 +192,7 @@ public class MainActivity extends AppCompatActivity{ if(!listeners.contains(awaitingListener)) listeners.add(awaitingListener); Intent serviceIntent = new Intent(context, DownloaderService.class); serviceIntent.putParcelableArrayListExtra("queue", downloadQueue); + context.getApplicationContext().startService(serviceIntent); context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE); } @@ -195,6 +207,7 @@ public class MainActivity extends AppCompatActivity{ dbManager.addToHistory(v); } dbManager.close(); + downloadsFragment.setDownloading(true); downloadsFragment.initCards(); } } catch (Exception e) { @@ -204,12 +217,11 @@ public class MainActivity extends AppCompatActivity{ public void stopDownloadService(){ if(!isDownloadServiceRunning) return; - iDownloaderService.removeActivity(this); - context.getApplicationContext().unbindService(serviceConnection); - downloaderService.stopForeground(true); - downloaderService.stopSelf(); - NotificationUtil notificationUtil = new NotificationUtil(context.getApplicationContext()); - notificationUtil.cancelDownloadNotification(NotificationUtil.DOWNLOAD_NOTIFICATION_ID); + try { + iDownloaderService.removeActivity(this); + context.getApplicationContext().unbindService(serviceConnection); + context.getApplicationContext().stopService(new Intent(context.getApplicationContext(), DownloaderService.class)); + }catch (Exception ignored){} isDownloadServiceRunning = false; } @@ -226,8 +238,10 @@ public class MainActivity extends AppCompatActivity{ public boolean isDownloadServiceRunning() { ActivityManager.RunningServiceInfo service = getService(DownloaderService.class); if(service != null){ - isDownloadServiceRunning = true; - return true; + if (service.foreground) { + isDownloadServiceRunning = true; + return true; + } } return false; } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/page/DownloadsFragment.java b/app/src/main/java/com/deniscerri/ytdlnis/page/DownloadsFragment.java index f7ec3e71..817d37b2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/page/DownloadsFragment.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/page/DownloadsFragment.java @@ -56,7 +56,7 @@ import java.util.Locale; * A fragment representing a list of Items. */ public class DownloadsFragment extends Fragment implements DownloadsRecyclerViewAdapter.OnItemClickListener, View.OnClickListener{ - + private boolean downloading = false; private View fragmentView; private DBManager dbManager; Context context; @@ -93,6 +93,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView progressBar = fragmentView.findViewWithTag(v.getURL()+v.getDownloadedType()+"##progress"); } }catch(Exception ignored){} + downloading = true; } public void onDownloadProgress(DownloadInfo info) { @@ -116,6 +117,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView dbManager = new DBManager(context); dbManager.clearHistoryItem(v, false); downloadsRecyclerViewAdapter.notifyItemRemoved(position); + downloading = false; }catch(Exception ignored){} } @@ -171,6 +173,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView dbManager.close(); downloadsRecyclerViewAdapter.notifyItemChanged(downloadsObjects.indexOf(item)); } catch (Exception ignored) {} + downloading = false; }catch(Exception ignored){} } @@ -182,16 +185,41 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView downloadsObjects.remove(v); dbManager = new DBManager(context); dbManager.clearHistoryItem(v,false); + dbManager.close(); downloadsRecyclerViewAdapter.setVideoList(downloadsObjects); + + if (downloadsObjects.isEmpty()) initCards(); + downloading = false; }catch (Exception ignored){} } @Override - public void onDownloadCancelAll(DownloadInfo downloadInfo){} + public void onDownloadCancelAll(DownloadInfo downloadInfo){ + try { + dbManager = new DBManager(context); + while (downloadsObjects.size() > 0){ + Video v = downloadsObjects.get(0); + if (v.isQueuedDownload()){ + dbManager.clearHistoryItem(v, false); + downloadsObjects.remove(v); + downloadsRecyclerViewAdapter.setVideoList(downloadsObjects); + }else{ + break; + } + } + dbManager.close(); + if (downloadsObjects.isEmpty()) initCards(); + downloading = false; + }catch (Exception ignored){} + } public void onDownloadServiceEnd() {} }; + public void setDownloading(boolean d){ + downloading = d; + } + public DownloadsFragment() { } @@ -226,9 +254,8 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView selectionChips = fragmentView.findViewById(R.id.downloads_selection_chips); websiteGroup = fragmentView.findViewById(R.id.website_chip_group); uiHandler = new Handler(Looper.getMainLooper()); - - dbManager = new DBManager(context); downloadsObjects = new ArrayList<>(); + downloading = mainActivity.isDownloadServiceRunning(); recyclerView = fragmentView.findViewById(R.id.recycler_view_downloads); downloadsRecyclerViewAdapter = new DownloadsRecyclerViewAdapter(downloadsObjects, this, activity); @@ -247,8 +274,11 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView downloadsRecyclerViewAdapter.clear(); no_results.setVisibility(View.GONE); selectionChips.setVisibility(View.VISIBLE); + + dbManager = new DBManager(context); try{ Thread thread = new Thread(() -> { + if (!downloading) dbManager.clearDownloadingHistory(); downloadsObjects = dbManager.getHistory("", format,website,sort); uiHandler.post(() -> { downloadsRecyclerViewAdapter.setVideoList(downloadsObjects); @@ -264,6 +294,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView websiteGroup.removeAllViews(); }); } + dbManager.close(); }); thread.start(); }catch(Exception e){ @@ -297,6 +328,8 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView searchView.setInputType(InputType.TYPE_CLASS_TEXT); searchView.setQueryHint(getString(R.string.search_history_hint)); + dbManager = new DBManager(context); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java b/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java index 61efa505..aaa8b37d 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java @@ -179,7 +179,9 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On downloading = false; topAppBar.getMenu().findItem(R.id.cancel_download).setVisible(false); - }catch(Exception ignored){} + }catch(Exception e){ + e.printStackTrace(); + } } @@ -257,9 +259,9 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On homeRecyclerViewAdapter.clear(); shimmerCards.startShimmer(); shimmerCards.setVisibility(View.VISIBLE); + Handler uiHandler = new Handler(Looper.getMainLooper()); try { Thread thread = new Thread(() -> { - Handler uiHandler = new Handler(Looper.getMainLooper()); dbManager = new DBManager(context); resultObjects = dbManager.getResults(); String playlistTitle = ""; @@ -272,12 +274,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On resultObjects = infoUtil.getTrending(context); dbManager.addToResults(resultObjects); - uiHandler.post(() -> { - homeRecyclerViewAdapter.setVideoList(resultObjects, true); - shimmerCards.stopShimmer(); - shimmerCards.setVisibility(View.GONE); - }); - } catch (Exception e) { Log.e(TAG, e.toString()); } @@ -291,12 +287,15 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On updateDownloadingStatusOnResult(tmp, "video", false); } } - uiHandler.post(() -> { - shimmerCards.stopShimmer(); - shimmerCards.setVisibility(View.GONE); - }); } } + + uiHandler.post(() -> { + homeRecyclerViewAdapter.setVideoList(resultObjects, true); + shimmerCards.stopShimmer(); + shimmerCards.setVisibility(View.GONE); + }); + dbManager.close(); if (resultObjects != null) { uiHandler.post(this::scrollToTop); @@ -308,6 +307,10 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On thread.start(); } catch (Exception e) { Log.e(TAG, e.toString()); + uiHandler.post(() -> { + shimmerCards.stopShimmer(); + shimmerCards.setVisibility(View.GONE); + }); } } @@ -328,7 +331,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On } }; - if(mainActivity.isDownloadServiceRunning()){ + if(downloading){ topAppBar.getMenu().findItem(R.id.cancel_download).setVisible(true); } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/receiver/NotificationReceiver.java b/app/src/main/java/com/deniscerri/ytdlnis/receiver/NotificationReceiver.java new file mode 100644 index 00000000..800aa158 --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/receiver/NotificationReceiver.java @@ -0,0 +1,59 @@ +package com.deniscerri.ytdlnis.receiver; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import com.deniscerri.ytdlnis.DownloaderService; +import com.deniscerri.ytdlnis.MainActivity; +import com.deniscerri.ytdlnis.service.IDownloaderListener; +import com.deniscerri.ytdlnis.service.IDownloaderService; +import com.deniscerri.ytdlnis.util.NotificationUtil; + +import java.util.ArrayList; + +public class NotificationReceiver extends BroadcastReceiver { + + public DownloaderService downloaderService; + private ArrayList listeners = null; + private IDownloaderService iDownloaderService; + private Context context; + + private final ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + downloaderService = ((DownloaderService.LocalBinder) service).getService(); + iDownloaderService = (IDownloaderService) service; + cancelDownload(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + downloaderService = null; + iDownloaderService = null; + } + }; + + + @Override + public void onReceive(Context c, Intent intent) { + context = c; + String message = intent.getStringExtra("cancel"); + if (message != null){ + Intent serviceIntent = new Intent(context.getApplicationContext(), DownloaderService.class); + serviceIntent.putExtra("rebind", true); + context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE); + } + } + + private void cancelDownload(){ + try { + iDownloaderService.cancelDownload(true); + context.getApplicationContext().unbindService(serviceConnection); + context.getApplicationContext().stopService(new Intent(context.getApplicationContext(), DownloaderService.class)); + }catch (Exception ignored){} + } + +} diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.java b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.java index ab463462..868e6520 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.java @@ -5,12 +5,14 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Build; import androidx.core.app.NotificationCompat; import com.deniscerri.ytdlnis.R; +import com.deniscerri.ytdlnis.receiver.NotificationReceiver; public class NotificationUtil { Context context; @@ -53,6 +55,16 @@ public class NotificationUtil { } public Notification createDownloadServiceNotification(PendingIntent pendingIntent, String title){ + Intent intent = new Intent(context, NotificationReceiver.class); + intent.putExtra("cancel", ""); + + PendingIntent cancelNotificationPendingIntent = PendingIntent.getBroadcast( + context, + 0, + intent, + PendingIntent.FLAG_IMMUTABLE + ); + Notification notification = notificationBuilder .setContentTitle(title) .setOngoing(true) @@ -65,6 +77,8 @@ public class NotificationUtil { .setProgress(PROGRESS_MAX, PROGRESS_CURR, false) .setContentIntent(pendingIntent) .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE) + .clearActions() + .addAction(0, context.getString(R.string.cancel), cancelNotificationPendingIntent) .build(); return notification;