aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDocile-Alligator <25734209+Docile-Alligator@users.noreply.github.com>2024-07-19 23:23:40 +0000
committerDocile-Alligator <25734209+Docile-Alligator@users.noreply.github.com>2024-07-19 23:23:40 +0000
commit48049d75750504da8785850d7aaad2e074c9240d (patch)
treed1b2e474ee440c99dec5bb3dd79229e548ae87a6
parentef9c647c78345ec4d7b7a945ef876d72faf0ffd0 (diff)
downloadinfinity-for-reddit-48049d75750504da8785850d7aaad2e074c9240d.tar
infinity-for-reddit-48049d75750504da8785850d7aaad2e074c9240d.tar.gz
infinity-for-reddit-48049d75750504da8785850d7aaad2e074c9240d.tar.bz2
infinity-for-reddit-48049d75750504da8785850d7aaad2e074c9240d.tar.lz
infinity-for-reddit-48049d75750504da8785850d7aaad2e074c9240d.tar.xz
infinity-for-reddit-48049d75750504da8785850d7aaad2e074c9240d.tar.zst
infinity-for-reddit-48049d75750504da8785850d7aaad2e074c9240d.zip
Start migrating DownloadMediaService to JobService.
-rw-r--r--app/src/main/AndroidManifest.xml1
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java20
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java37
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurImageFragment.java17
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurVideoFragment.java18
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java19
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragment.java20
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java435
8 files changed, 334 insertions, 233 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d6d5aa9c..b80426e9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -161,6 +161,7 @@
<service
android:name=".services.DownloadMediaService"
android:enabled="true"
+ android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" />
<activity
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java
index 88668712..fe4778c2 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java
@@ -1,6 +1,9 @@
package ml.docilealligator.infinityforreddit.activities;
import android.Manifest;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
@@ -12,6 +15,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.PersistableBundle;
import android.text.Html;
import android.text.Spanned;
import android.view.Menu;
@@ -355,13 +359,25 @@ public class ViewImageOrGifActivity extends AppCompatActivity implements SetAsWa
private void download() {
isDownloading = false;
- Intent intent = new Intent(this, DownloadMediaService.class);
+ /*Intent intent = new Intent(this, DownloadMediaService.class);
intent.putExtra(DownloadMediaService.EXTRA_URL, mImageUrl);
intent.putExtra(DownloadMediaService.EXTRA_MEDIA_TYPE, isGif ? DownloadMediaService.EXTRA_MEDIA_TYPE_GIF : DownloadMediaService.EXTRA_MEDIA_TYPE_IMAGE);
intent.putExtra(DownloadMediaService.EXTRA_FILE_NAME, mImageFileName);
intent.putExtra(DownloadMediaService.EXTRA_SUBREDDIT_NAME, mSubredditName);
intent.putExtra(DownloadMediaService.EXTRA_IS_NSFW, isNsfw);
- ContextCompat.startForegroundService(this, intent);
+ ContextCompat.startForegroundService(this, intent);*/
+
+ PersistableBundle extras = new PersistableBundle();
+ extras.putString(DownloadMediaService.EXTRA_URL, mImageUrl);
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, isGif ? DownloadMediaService.EXTRA_MEDIA_TYPE_GIF : DownloadMediaService.EXTRA_MEDIA_TYPE_IMAGE);
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, mImageFileName);
+ extras.putString(DownloadMediaService.EXTRA_SUBREDDIT_NAME, mSubredditName);
+ extras.putInt(DownloadMediaService.EXTRA_IS_NSFW, isNsfw ? 1 : 0);
+
+ //TODO: contentEstimatedBytes
+ JobInfo jobInfo = DownloadMediaService.constructJobInfo(this, 5000000, extras);
+ ((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+
Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java
index 7f3cd774..14c544b4 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewVideoActivity.java
@@ -7,6 +7,9 @@ import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES;
import android.Manifest;
import android.app.Dialog;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
@@ -22,6 +25,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.PersistableBundle;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuItem;
@@ -107,7 +111,6 @@ import ml.docilealligator.infinityforreddit.font.TitleFontStyle;
import ml.docilealligator.infinityforreddit.post.FetchPost;
import ml.docilealligator.infinityforreddit.post.Post;
import ml.docilealligator.infinityforreddit.services.DownloadMediaService;
-import ml.docilealligator.infinityforreddit.services.DownloadRedditVideoService;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
@@ -978,7 +981,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
private void download() {
isDownloading = false;
- Intent intent;
+ /*Intent intent;
if (videoType != VIDEO_TYPE_NORMAL) {
intent = new Intent(this, DownloadMediaService.class);
if (post.getPostType() == Post.GIF_TYPE) {
@@ -1001,7 +1004,35 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
intent.putExtra(DownloadRedditVideoService.EXTRA_SUBREDDIT, subredditName);
intent.putExtra(DownloadRedditVideoService.EXTRA_IS_NSFW, isNSFW);
}
- ContextCompat.startForegroundService(this, intent);
+ ContextCompat.startForegroundService(this, intent);*/
+
+ if (videoType != VIDEO_TYPE_NORMAL) {
+ PersistableBundle extras = new PersistableBundle();
+ if (post.getPostType() == Post.GIF_TYPE) {
+ extras.putString(DownloadMediaService.EXTRA_URL, post.getVideoUrl());
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_GIF);
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, post.getSubredditName()
+ + "-" + post.getId() + ".gif");
+ } else {
+ extras.putString(DownloadMediaService.EXTRA_URL, videoDownloadUrl);
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, videoFileName);
+ }
+
+ extras.putString(DownloadMediaService.EXTRA_SUBREDDIT_NAME, subredditName);
+ extras.putInt(DownloadMediaService.EXTRA_IS_NSFW, isNSFW ? 1 : 0);
+
+ //TODO: contentEstimatedBytes
+ JobInfo jobInfo = DownloadMediaService.constructJobInfo(this, 5000000, extras);
+ ((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+ } else {
+ /* intent = new Intent(this, DownloadRedditVideoService.class);
+ intent.putExtra(DownloadRedditVideoService.EXTRA_VIDEO_URL, videoDownloadUrl);
+ intent.putExtra(DownloadRedditVideoService.EXTRA_POST_ID, id);
+ intent.putExtra(DownloadRedditVideoService.EXTRA_SUBREDDIT, subredditName);
+ intent.putExtra(DownloadRedditVideoService.EXTRA_IS_NSFW, isNSFW);*/
+ }
+
Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurImageFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurImageFragment.java
index 4e13c051..5b67f459 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurImageFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurImageFragment.java
@@ -1,6 +1,8 @@
package ml.docilealligator.infinityforreddit.fragments;
import android.Manifest;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -10,6 +12,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.PersistableBundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -221,11 +224,21 @@ public class ViewImgurImageFragment extends Fragment {
private void download() {
isDownloading = false;
- Intent intent = new Intent(activity, DownloadMediaService.class);
+ /*Intent intent = new Intent(activity, DownloadMediaService.class);
intent.putExtra(DownloadMediaService.EXTRA_URL, imgurMedia.getLink());
intent.putExtra(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_IMAGE);
intent.putExtra(DownloadMediaService.EXTRA_FILE_NAME, imgurMedia.getFileName());
- ContextCompat.startForegroundService(activity, intent);
+ ContextCompat.startForegroundService(activity, intent);*/
+
+ PersistableBundle extras = new PersistableBundle();
+ extras.putString(DownloadMediaService.EXTRA_URL, imgurMedia.getLink());
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_IMAGE);
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, imgurMedia.getFileName());
+
+ //TODO: contentEstimatedBytes
+ JobInfo jobInfo = DownloadMediaService.constructJobInfo(activity, 5000000, extras);
+ ((JobScheduler) activity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+
Toast.makeText(activity, R.string.download_started, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurVideoFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurVideoFragment.java
index eb6adac8..47d04de7 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurVideoFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewImgurVideoFragment.java
@@ -1,8 +1,9 @@
package ml.docilealligator.infinityforreddit.fragments;
import android.Manifest;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
@@ -10,6 +11,7 @@ import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -258,11 +260,21 @@ public class ViewImgurVideoFragment extends Fragment {
private void download() {
isDownloading = false;
- Intent intent = new Intent(activity, DownloadMediaService.class);
+ /*Intent intent = new Intent(activity, DownloadMediaService.class);
intent.putExtra(DownloadMediaService.EXTRA_URL, imgurMedia.getLink());
intent.putExtra(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
intent.putExtra(DownloadMediaService.EXTRA_FILE_NAME, imgurMedia.getFileName());
- ContextCompat.startForegroundService(activity, intent);
+ ContextCompat.startForegroundService(activity, intent);*/
+
+ PersistableBundle extras = new PersistableBundle();
+ extras.putString(DownloadMediaService.EXTRA_URL, imgurMedia.getLink());
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, imgurMedia.getFileName());
+
+ //TODO: contentEstimatedBytes
+ JobInfo jobInfo = DownloadMediaService.constructJobInfo(activity, 5000000, extras);
+ ((JobScheduler) activity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+
Toast.makeText(activity, R.string.download_started, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java
index cb60df38..7a462ad4 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryImageOrGifFragment.java
@@ -1,6 +1,8 @@
package ml.docilealligator.infinityforreddit.fragments;
import android.Manifest;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -11,6 +13,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.PersistableBundle;
import android.text.TextUtils;
import android.text.util.Linkify;
import android.view.LayoutInflater;
@@ -373,13 +376,25 @@ public class ViewRedditGalleryImageOrGifFragment extends Fragment {
private void download() {
isDownloading = false;
- Intent intent = new Intent(activity, DownloadMediaService.class);
+ /*Intent intent = new Intent(activity, DownloadMediaService.class);
intent.putExtra(DownloadMediaService.EXTRA_URL, media.hasFallback() ? media.fallbackUrl : media.url); // Retrieve original instead of the one additionally compressed by reddit
intent.putExtra(DownloadMediaService.EXTRA_MEDIA_TYPE, media.mediaType == Post.Gallery.TYPE_GIF ? DownloadMediaService.EXTRA_MEDIA_TYPE_GIF: DownloadMediaService.EXTRA_MEDIA_TYPE_IMAGE);
intent.putExtra(DownloadMediaService.EXTRA_FILE_NAME, media.fileName);
intent.putExtra(DownloadMediaService.EXTRA_SUBREDDIT_NAME, subredditName);
intent.putExtra(DownloadMediaService.EXTRA_IS_NSFW, isNsfw);
- ContextCompat.startForegroundService(activity, intent);
+ ContextCompat.startForegroundService(activity, intent);*/
+
+ PersistableBundle extras = new PersistableBundle();
+ extras.putString(DownloadMediaService.EXTRA_URL, media.hasFallback() ? media.fallbackUrl : media.url); // Retrieve original instead of the one additionally compressed by reddit
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, media.mediaType == Post.Gallery.TYPE_GIF ? DownloadMediaService.EXTRA_MEDIA_TYPE_GIF: DownloadMediaService.EXTRA_MEDIA_TYPE_IMAGE);
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, media.fileName);
+ extras.putString(DownloadMediaService.EXTRA_SUBREDDIT_NAME, subredditName);
+ extras.putInt(DownloadMediaService.EXTRA_IS_NSFW, isNsfw ? 1 : 0);
+
+ //TODO: contentEstimatedBytes
+ JobInfo jobInfo = DownloadMediaService.constructJobInfo(activity, 5000000, extras);
+ ((JobScheduler) activity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+
Toast.makeText(activity, R.string.download_started, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragment.java
index 8a64999e..c716c03b 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/ViewRedditGalleryVideoFragment.java
@@ -1,8 +1,9 @@
package ml.docilealligator.infinityforreddit.fragments;
import android.Manifest;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
@@ -10,6 +11,7 @@ import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -257,13 +259,25 @@ public class ViewRedditGalleryVideoFragment extends Fragment {
private void download() {
isDownloading = false;
- Intent intent = new Intent(activity, DownloadMediaService.class);
+ /*Intent intent = new Intent(activity, DownloadMediaService.class);
intent.putExtra(DownloadMediaService.EXTRA_URL, galleryVideo.url);
intent.putExtra(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
intent.putExtra(DownloadMediaService.EXTRA_FILE_NAME, galleryVideo.fileName);
intent.putExtra(DownloadMediaService.EXTRA_SUBREDDIT_NAME, subredditName);
intent.putExtra(DownloadMediaService.EXTRA_IS_NSFW, isNsfw);
- ContextCompat.startForegroundService(activity, intent);
+ ContextCompat.startForegroundService(activity, intent);*/
+
+ PersistableBundle extras = new PersistableBundle();
+ extras.putString(DownloadMediaService.EXTRA_URL, galleryVideo.url);
+ extras.putInt(DownloadMediaService.EXTRA_MEDIA_TYPE, DownloadMediaService.EXTRA_MEDIA_TYPE_VIDEO);
+ extras.putString(DownloadMediaService.EXTRA_FILE_NAME, galleryVideo.fileName);
+ extras.putString(DownloadMediaService.EXTRA_SUBREDDIT_NAME, subredditName);
+ extras.putInt(DownloadMediaService.EXTRA_IS_NSFW, isNsfw ? 1 : 0);
+
+ //TODO: contentEstimatedBytes
+ JobInfo jobInfo = DownloadMediaService.constructJobInfo(activity, 5000000, extras);
+ ((JobScheduler) activity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
+
Toast.makeText(activity, R.string.download_started, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
index 872ff654..09506159 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
@@ -4,22 +4,21 @@ import static android.os.Environment.getExternalStoragePublicDirectory;
import android.app.Notification;
import android.app.PendingIntent;
-import android.app.Service;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaScannerConnection;
+import android.net.NetworkRequest;
import android.net.Uri;
import android.os.Build;
-import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
+import android.os.PersistableBundle;
import android.provider.MediaStore;
import androidx.core.app.NotificationChannelCompat;
@@ -33,6 +32,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Named;
@@ -48,11 +48,10 @@ import ml.docilealligator.infinityforreddit.utils.NotificationUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
-import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
-public class DownloadMediaService extends Service {
+public class DownloadMediaService extends JobService {
public static final String EXTRA_URL = "EU";
public static final String EXTRA_FILE_NAME = "EFN";
public static final String EXTRA_SUBREDDIT_NAME = "ESN";
@@ -66,6 +65,9 @@ public class DownloadMediaService extends Service {
private static final int ERROR_CANNOT_GET_DESTINATION_DIRECTORY = 0;
private static final int ERROR_FILE_CANNOT_DOWNLOAD = 1;
private static final int ERROR_FILE_CANNOT_SAVE = 2;
+
+ private static int JOB_ID = 20000;
+
@Inject
@Named("download_media")
Retrofit retrofit;
@@ -74,35 +76,89 @@ public class DownloadMediaService extends Service {
SharedPreferences mSharedPreferences;
@Inject
CustomThemeWrapper mCustomThemeWrapper;
+ @Inject
+ Executor mExecutor;
private NotificationManagerCompat notificationManager;
private NotificationCompat.Builder builder;
- private ServiceHandler serviceHandler;
public DownloadMediaService() {
}
+ public static JobInfo constructJobInfo(Context context, long contentEstimatedBytes, PersistableBundle extras) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ return new JobInfo.Builder(JOB_ID++, new ComponentName(context, DownloadMediaService.class))
+ .setUserInitiated(true)
+ .setRequiredNetwork(new NetworkRequest.Builder().build())
+ .setEstimatedNetworkBytes(0, contentEstimatedBytes + 500)
+ .setExtras(extras)
+ .build();
+ } else {
+ return new JobInfo.Builder(JOB_ID++, new ComponentName(context, DownloadMediaService.class))
+ .build();
+ }
+ }
+
@Override
- public IBinder onBind(Intent intent) {
- return null;
+ public void onCreate() {
+ ((Infinity) getApplication()).getAppComponent().inject(this);
+ notificationManager = NotificationManagerCompat.from(this);
}
- // Handler that receives messages from the thread
- private final class ServiceHandler extends Handler {
- private boolean downloadFinished;
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ PersistableBundle intent = params.getExtras();
+ int mediaType = intent.getInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_IMAGE);
+ builder = new NotificationCompat.Builder(this, getNotificationChannelId(mediaType));
+
+ NotificationChannelCompat serviceChannel =
+ new NotificationChannelCompat.Builder(
+ getNotificationChannelId(mediaType),
+ NotificationManagerCompat.IMPORTANCE_LOW)
+ .setName(getNotificationChannel(mediaType))
+ .build();
+ notificationManager.createNotificationChannel(serviceChannel);
- public ServiceHandler(Looper looper) {
- super(looper);
+ int randomNotificationIdOffset = new Random().nextInt(10000);
+ switch (intent.getInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_IMAGE)) {
+ case EXTRA_MEDIA_TYPE_GIF:
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ setNotification(params,
+ NotificationUtils.DOWNLOAD_GIF_NOTIFICATION_ID + randomNotificationIdOffset,
+ createNotification(intent.getString(EXTRA_FILE_NAME)),
+ JobService.JOB_END_NOTIFICATION_POLICY_DETACH);
+ } else {
+ notificationManager.notify(NotificationUtils.DOWNLOAD_GIF_NOTIFICATION_ID + randomNotificationIdOffset,
+ createNotification(intent.getString(EXTRA_FILE_NAME)));
+ }
+ break;
+ case EXTRA_MEDIA_TYPE_VIDEO:
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ setNotification(params,
+ NotificationUtils.DOWNLOAD_VIDEO_NOTIFICATION_ID + randomNotificationIdOffset,
+ createNotification(intent.getString(EXTRA_FILE_NAME)),
+ JobService.JOB_END_NOTIFICATION_POLICY_DETACH);
+ } else {
+ notificationManager.notify(NotificationUtils.DOWNLOAD_VIDEO_NOTIFICATION_ID + randomNotificationIdOffset,
+ createNotification(intent.getString(EXTRA_FILE_NAME)));
+ }
+ break;
+ default:
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ setNotification(params,
+ NotificationUtils.DOWNLOAD_IMAGE_NOTIFICATION_ID + randomNotificationIdOffset,
+ createNotification(intent.getString(EXTRA_FILE_NAME)),
+ JobService.JOB_END_NOTIFICATION_POLICY_DETACH);
+ } else {
+ notificationManager.notify(NotificationUtils.DOWNLOAD_IMAGE_NOTIFICATION_ID + randomNotificationIdOffset,
+ createNotification(intent.getString(EXTRA_FILE_NAME)));
+ }
}
- @Override
- public void handleMessage(Message msg) {
- int randomNotificationIdOffset = msg.arg1;
- Bundle intent = msg.getData();
- downloadFinished = false;
+
+ mExecutor.execute(() -> {
String fileUrl = intent.getString(EXTRA_URL);
String fileName = intent.getString(EXTRA_FILE_NAME);
String subredditName = intent.getString(EXTRA_SUBREDDIT_NAME);
- int mediaType = intent.getInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_IMAGE);
- boolean isNsfw = intent.getBoolean(EXTRA_IS_NSFW, false);
+ boolean isNsfw = intent.getInt(EXTRA_IS_NSFW, 0) == 1;
String mimeType = mediaType == EXTRA_MEDIA_TYPE_VIDEO ? "video/*" : "image/*";
final DownloadProgressResponseBody.ProgressListener progressListener = new DownloadProgressResponseBody.ProgressListener() {
@@ -141,12 +197,11 @@ public class DownloadMediaService extends Service {
boolean separateDownloadFolder = mSharedPreferences.getBoolean(SharedPreferencesUtils.SEPARATE_FOLDER_FOR_EACH_SUBREDDIT, false);
- Response<ResponseBody> response = null;
+ Response<ResponseBody> response;
String destinationFileUriString = null;
boolean isDefaultDestination = true;
try {
- Call<ResponseBody> call = retrofit.create(DownloadFile.class).downloadFile(fileUrl);
- response = call.execute();
+ response = retrofit.create(DownloadFile.class).downloadFile(fileUrl).execute();
if (response.isSuccessful() && response.body() != null) {
String destinationFileDirectory = getDownloadLocation(mediaType, isNsfw);
if (destinationFileDirectory.equals("")) {
@@ -156,13 +211,13 @@ public class DownloadMediaService extends Service {
String directoryPath = separateDownloadFolder && subredditName != null && !subredditName.equals("") ? directory.getAbsolutePath() + "/Infinity/" + subredditName + "/" : directory.getAbsolutePath() + "/Infinity/";
File infinityDir = new File(directoryPath);
if (!infinityDir.exists() && !infinityDir.mkdirs()) {
- downloadFinished(mediaType, randomNotificationIdOffset, mimeType,
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType,
null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
destinationFileUriString = directoryPath + fileName;
} else {
- downloadFinished(mediaType, randomNotificationIdOffset, mimeType,
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType,
null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
@@ -170,7 +225,6 @@ public class DownloadMediaService extends Service {
String dir = mediaType == EXTRA_MEDIA_TYPE_VIDEO ? Environment.DIRECTORY_MOVIES : Environment.DIRECTORY_PICTURES;
destinationFileUriString = separateDownloadFolder && subredditName != null && !subredditName.equals("") ? dir + "/Infinity/" + subredditName + "/" : dir + "/Infinity/";
}
- isDefaultDestination = true;
} else {
isDefaultDestination = false;
DocumentFile picFile;
@@ -178,7 +232,7 @@ public class DownloadMediaService extends Service {
if (separateDownloadFolder && subredditName != null && !subredditName.equals("")) {
dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory));
if (dir == null) {
- downloadFinished(mediaType, randomNotificationIdOffset, mimeType,
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType,
null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
@@ -186,7 +240,7 @@ public class DownloadMediaService extends Service {
if (dir == null) {
dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory)).createDirectory(subredditName);
if (dir == null) {
- downloadFinished(mediaType, randomNotificationIdOffset, mimeType,
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType,
null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
@@ -194,7 +248,7 @@ public class DownloadMediaService extends Service {
} else {
dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory));
if (dir == null) {
- downloadFinished(mediaType, randomNotificationIdOffset, mimeType,
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType,
null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
@@ -210,211 +264,42 @@ public class DownloadMediaService extends Service {
}
picFile = dir.createFile(mimeType, fileName);
if (picFile == null) {
- downloadFinished(mediaType, randomNotificationIdOffset, mimeType,
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType,
null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
destinationFileUriString = picFile.getUri().toString();
}
} else {
- downloadFinished(mediaType, randomNotificationIdOffset, mimeType, null,
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType, null,
ERROR_FILE_CANNOT_DOWNLOAD);
+ return;
}
} catch (IOException e) {
e.printStackTrace();
+ downloadFinished(params, mediaType, randomNotificationIdOffset, mimeType, null,
+ ERROR_FILE_CANNOT_DOWNLOAD);
+ return;
}
try {
- if (response != null && response.body() != null) {
- Uri destinationFileUri = writeResponseBodyToDisk(response.body(), isDefaultDestination, destinationFileUriString,
- fileName, mediaType);
- downloadFinished(mediaType, randomNotificationIdOffset,
- mimeType, destinationFileUri, NO_ERROR);
- }
+ Uri destinationFileUri = writeResponseBodyToDisk(response.body(), isDefaultDestination, destinationFileUriString,
+ fileName, mediaType);
+ downloadFinished(params, mediaType, randomNotificationIdOffset,
+ mimeType, destinationFileUri, NO_ERROR);
} catch (IOException e) {
e.printStackTrace();
- downloadFinished(mediaType, randomNotificationIdOffset,
+ downloadFinished(params, mediaType, randomNotificationIdOffset,
mimeType, null, ERROR_FILE_CANNOT_SAVE);
}
- }
-
- private Uri writeResponseBodyToDisk(ResponseBody body, boolean isDefaultDestination,
- String destinationFileUriString, String destinationFileName,
- int mediaType) throws IOException {
- ContentResolver contentResolver = getContentResolver();
- if (isDefaultDestination) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
- InputStream inputStream = body.byteStream();
- OutputStream outputStream = new FileOutputStream(destinationFileUriString);
- byte[] fileReader = new byte[4096];
-
- long fileSize = body.contentLength();
- long fileSizeDownloaded = 0;
-
- while (true) {
- int read = inputStream.read(fileReader);
-
- if (read == -1) {
- break;
- }
-
- outputStream.write(fileReader, 0, read);
-
- fileSizeDownloaded += read;
- }
-
- outputStream.flush();
- } else {
- ContentValues contentValues = new ContentValues();
- contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, destinationFileName);
- String mimeType;
- switch (mediaType) {
- case EXTRA_MEDIA_TYPE_VIDEO:
- mimeType = "video/mpeg";
- break;
- case EXTRA_MEDIA_TYPE_GIF:
- mimeType = "image/gif";
- break;
- default:
- mimeType = "image/jpeg";
- }
- contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
- contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, destinationFileUriString);
- contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);
-
- final Uri contentUri = mediaType == EXTRA_MEDIA_TYPE_VIDEO ? MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) : MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
- Uri uri = contentResolver.insert(contentUri, contentValues);
-
- if (uri == null) {
- throw new IOException("Failed to create new MediaStore record.");
- }
-
- OutputStream stream = contentResolver.openOutputStream(uri);
-
- if (stream == null) {
- throw new IOException("Failed to get output stream.");
- }
-
- InputStream in = body.byteStream();
- byte[] buf = new byte[1024];
- int len;
- while ((len = in.read(buf)) > 0) {
- stream.write(buf, 0, len);
- }
- contentValues.clear();
- contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
- contentResolver.update(uri, contentValues, null, null);
- destinationFileUriString = uri.toString();
- }
- } else {
- try (OutputStream stream = contentResolver.openOutputStream(Uri.parse(destinationFileUriString))) {
- if (stream == null) {
- throw new IOException("Failed to get output stream.");
- }
-
- InputStream in = body.byteStream();
-
- byte[] buf = new byte[1024];
- int len;
- while ((len = in.read(buf)) > 0) {
- stream.write(buf, 0, len);
- }
- }
- }
- return Uri.parse(destinationFileUriString);
- }
-
- private void downloadFinished(int mediaType, int randomNotificationIdOffset, String mimeType, Uri destinationFileUri, int errorCode) {
- if (downloadFinished) {
- return;
- }
+ });
- downloadFinished = true;
- if (errorCode != NO_ERROR) {
- switch (errorCode) {
- case ERROR_CANNOT_GET_DESTINATION_DIRECTORY:
- updateNotification(mediaType, R.string.downloading_image_or_gif_failed_cannot_get_destination_directory,
- -1, randomNotificationIdOffset, null, null);
- break;
- case ERROR_FILE_CANNOT_DOWNLOAD:
- updateNotification(mediaType, R.string.downloading_media_failed_cannot_download_media,
- -1, randomNotificationIdOffset, null, null);
- break;
- case ERROR_FILE_CANNOT_SAVE:
- updateNotification(mediaType, R.string.downloading_media_failed_cannot_save_to_destination_directory,
- -1, randomNotificationIdOffset, null, null);
- break;
- }
- } else {
- MediaScannerConnection.scanFile(
- DownloadMediaService.this, new String[]{destinationFileUri.toString()}, null,
- (path, uri) -> {
- updateNotification(mediaType, R.string.downloading_media_finished, -1,
- randomNotificationIdOffset, destinationFileUri, mimeType);
- }
- );
- }
- stopForeground(false);
- }
+ return true;
}
@Override
- public void onCreate() {
- ((Infinity) getApplication()).getAppComponent().inject(this);
- notificationManager = NotificationManagerCompat.from(this);
- // Start up the thread running the service. Note that we create a
- // separate thread because the service normally runs in the process's
- // main thread, which we don't want to block. We also make it
- // background priority so CPU-intensive work doesn't disrupt our UI.
- HandlerThread thread = new HandlerThread("ServiceStartArguments",
- Process.THREAD_PRIORITY_BACKGROUND);
- thread.start();
-
- // Get the HandlerThread's Looper and use it for our Handler
- serviceHandler = new ServiceHandler(thread.getLooper());
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- int mediaType = intent.getIntExtra(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_IMAGE);
- builder = new NotificationCompat.Builder(this, getNotificationChannelId(mediaType));
-
- NotificationChannelCompat serviceChannel =
- new NotificationChannelCompat.Builder(
- getNotificationChannelId(mediaType),
- NotificationManagerCompat.IMPORTANCE_LOW)
- .setName(getNotificationChannel(mediaType))
- .build();
- notificationManager.createNotificationChannel(serviceChannel);
-
- int randomNotificationIdOffset = new Random().nextInt(10000);
- switch (intent.getIntExtra(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_IMAGE)) {
- case EXTRA_MEDIA_TYPE_GIF:
- startForeground(
- NotificationUtils.DOWNLOAD_GIF_NOTIFICATION_ID + randomNotificationIdOffset,
- createNotification(intent.getStringExtra(EXTRA_FILE_NAME))
- );
- break;
- case EXTRA_MEDIA_TYPE_VIDEO:
- startForeground(
- NotificationUtils.DOWNLOAD_VIDEO_NOTIFICATION_ID + randomNotificationIdOffset,
- createNotification(intent.getStringExtra(EXTRA_FILE_NAME))
- );
- break;
- default:
- startForeground(
- NotificationUtils.DOWNLOAD_IMAGE_NOTIFICATION_ID + randomNotificationIdOffset,
- createNotification(intent.getStringExtra(EXTRA_FILE_NAME))
- );
- }
-
- Message msg = serviceHandler.obtainMessage();
- Bundle bundle = intent.getExtras();
- msg.setData(bundle);
- msg.arg1 = randomNotificationIdOffset;
- serviceHandler.sendMessage(msg);
-
- return START_NOT_STICKY;
+ public boolean onStopJob(JobParameters params) {
+ return false;
}
private Notification createNotification(String fileName) {
@@ -511,4 +396,118 @@ public class DownloadMediaService extends Service {
return mSharedPreferences.getString(SharedPreferencesUtils.IMAGE_DOWNLOAD_LOCATION, "");
}
}
+
+ private Uri writeResponseBodyToDisk(ResponseBody body, boolean isDefaultDestination,
+ String destinationFileUriString, String destinationFileName,
+ int mediaType) throws IOException {
+ ContentResolver contentResolver = getContentResolver();
+ if (isDefaultDestination) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ InputStream inputStream = body.byteStream();
+ OutputStream outputStream = new FileOutputStream(destinationFileUriString);
+ byte[] fileReader = new byte[4096];
+
+ long fileSize = body.contentLength();
+ long fileSizeDownloaded = 0;
+
+ while (true) {
+ int read = inputStream.read(fileReader);
+
+ if (read == -1) {
+ break;
+ }
+
+ outputStream.write(fileReader, 0, read);
+
+ fileSizeDownloaded += read;
+ }
+
+ outputStream.flush();
+ } else {
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, destinationFileName);
+ String mimeType;
+ switch (mediaType) {
+ case EXTRA_MEDIA_TYPE_VIDEO:
+ mimeType = "video/mpeg";
+ break;
+ case EXTRA_MEDIA_TYPE_GIF:
+ mimeType = "image/gif";
+ break;
+ default:
+ mimeType = "image/jpeg";
+ }
+ contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
+ contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, destinationFileUriString);
+ contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);
+
+ final Uri contentUri = mediaType == EXTRA_MEDIA_TYPE_VIDEO ? MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) : MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
+ Uri uri = contentResolver.insert(contentUri, contentValues);
+
+ if (uri == null) {
+ throw new IOException("Failed to create new MediaStore record.");
+ }
+
+ OutputStream stream = contentResolver.openOutputStream(uri);
+
+ if (stream == null) {
+ throw new IOException("Failed to get output stream.");
+ }
+
+ InputStream in = body.byteStream();
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ stream.write(buf, 0, len);
+ }
+ contentValues.clear();
+ contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
+ contentResolver.update(uri, contentValues, null, null);
+ destinationFileUriString = uri.toString();
+ }
+ } else {
+ try (OutputStream stream = contentResolver.openOutputStream(Uri.parse(destinationFileUriString))) {
+ if (stream == null) {
+ throw new IOException("Failed to get output stream.");
+ }
+
+ InputStream in = body.byteStream();
+
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ stream.write(buf, 0, len);
+ }
+ }
+ }
+ return Uri.parse(destinationFileUriString);
+ }
+
+ private void downloadFinished(JobParameters parameters, int mediaType, int randomNotificationIdOffset, String mimeType, Uri destinationFileUri, int errorCode) {
+ if (errorCode != NO_ERROR) {
+ switch (errorCode) {
+ case ERROR_CANNOT_GET_DESTINATION_DIRECTORY:
+ updateNotification(mediaType, R.string.downloading_image_or_gif_failed_cannot_get_destination_directory,
+ -1, randomNotificationIdOffset, null, null);
+ break;
+ case ERROR_FILE_CANNOT_DOWNLOAD:
+ updateNotification(mediaType, R.string.downloading_media_failed_cannot_download_media,
+ -1, randomNotificationIdOffset, null, null);
+ break;
+ case ERROR_FILE_CANNOT_SAVE:
+ updateNotification(mediaType, R.string.downloading_media_failed_cannot_save_to_destination_directory,
+ -1, randomNotificationIdOffset, null, null);
+ break;
+ }
+ } else {
+ MediaScannerConnection.scanFile(
+ DownloadMediaService.this, new String[]{destinationFileUri.toString()}, null,
+ (path, uri) -> {
+ updateNotification(mediaType, R.string.downloading_media_finished, -1,
+ randomNotificationIdOffset, destinationFileUri, mimeType);
+ }
+ );
+ }
+ jobFinished(parameters, false);
+ }
}