Skip to content

Commit f042b89

Browse files
Add an option to download all media in an imgur album in ViewImgurMediaActivity.
1 parent 4799a09 commit f042b89

File tree

6 files changed

+117
-20
lines changed

6 files changed

+117
-20
lines changed

app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImgurMediaActivity.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package ml.docilealligator.infinityforreddit.activities;
22

3+
import android.app.job.JobInfo;
4+
import android.app.job.JobScheduler;
5+
import android.content.Context;
36
import android.content.SharedPreferences;
47
import android.graphics.Typeface;
58
import android.graphics.drawable.ColorDrawable;
@@ -48,6 +51,7 @@
4851
import ml.docilealligator.infinityforreddit.font.TitleFontStyle;
4952
import ml.docilealligator.infinityforreddit.fragments.ViewImgurImageFragment;
5053
import ml.docilealligator.infinityforreddit.fragments.ViewImgurVideoFragment;
54+
import ml.docilealligator.infinityforreddit.services.DownloadMediaService;
5155
import ml.docilealligator.infinityforreddit.utils.APIUtils;
5256
import ml.docilealligator.infinityforreddit.utils.JSONUtils;
5357
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
@@ -297,6 +301,10 @@ private void setToolbarTitle(int position) {
297301

298302
@Override
299303
public boolean onCreateOptionsMenu(Menu menu) {
304+
getMenuInflater().inflate(R.menu.view_imgur_media_activity, menu);
305+
for (int i = 0; i < menu.size(); i++) {
306+
Utils.setTitleWithCustomFontToMenuItem(typeface, menu.getItem(i), null);
307+
}
300308
return true;
301309
}
302310

@@ -305,6 +313,13 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
305313
if (item.getItemId() == android.R.id.home) {
306314
finish();
307315
return true;
316+
} else if (item.getItemId() == R.id.action_download_all_imgur_album_media_view_imgur_media_activity) {
317+
//TODO: contentEstimatedBytes
318+
JobInfo jobInfo = DownloadMediaService.constructImgurAlbumDownloadAllMediaJobInfo(this, 5000000L * images.size(), images);
319+
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
320+
321+
Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show();
322+
return true;
308323
}
309324

310325
return false;

app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewRedditGalleryActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
223223
return true;
224224
} else if (item.getItemId() == R.id.action_download_all_gallery_media_view_reddit_gallery_activity) {
225225
//TODO: contentEstimatedBytes
226-
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllImagesJobInfo(this, 5000000, post);
226+
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllMediaJobInfo(this, 5000000L * gallery.size(), post);
227227
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
228228

229229
Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show();

app/src/main/java/ml/docilealligator/infinityforreddit/bottomsheetfragments/PostOptionsBottomSheetFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
136136
if (mPost.getPostType() == Post.GALLERY_TYPE) {
137137
binding.downloadAllTextViewPostOptionsBottomSheetFragment.setVisibility(View.VISIBLE);
138138
binding.downloadAllTextViewPostOptionsBottomSheetFragment.setOnClickListener(view -> {
139-
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllImagesJobInfo(mBaseActivity, 5000000, mPost);
139+
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllMediaJobInfo(mBaseActivity, 5000000, mPost);
140140
((JobScheduler) mBaseActivity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
141141

142142
dismiss();

app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import android.os.Environment;
2121
import android.os.PersistableBundle;
2222
import android.provider.MediaStore;
23-
import android.util.Log;
2423

2524
import androidx.core.app.NotificationChannelCompat;
2625
import androidx.core.app.NotificationCompat;
@@ -35,6 +34,7 @@
3534
import java.io.InputStream;
3635
import java.io.OutputStream;
3736
import java.util.ArrayList;
37+
import java.util.List;
3838
import java.util.Random;
3939
import java.util.concurrent.Executor;
4040

@@ -69,6 +69,7 @@ public class DownloadMediaService extends JobService {
6969
public static final String EXTRA_IS_NSFW = "EIN";
7070
public static final String EXTRA_REDGIFS_ID = "EGI";
7171
public static final String EXTRA_STREAMABLE_SHORT_CODE = "ESSC";
72+
public static final String EXTRA_IS_ALL_GALLERY_MEDIA = "EIAGM";
7273
public static final int EXTRA_MEDIA_TYPE_IMAGE = 0;
7374
public static final int EXTRA_MEDIA_TYPE_GIF = 1;
7475
public static final int EXTRA_MEDIA_TYPE_VIDEO = 2;
@@ -82,7 +83,8 @@ public class DownloadMediaService extends JobService {
8283
private static final int ERROR_FILE_CANNOT_DOWNLOAD = 1;
8384
private static final int ERROR_FILE_CANNOT_SAVE = 2;
8485
private static final int ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK = 3;
85-
private static final int ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK = 4;
86+
private static final int ERROR_CANNOT_FETCH_STREAMABLE_VIDEO_LINK = 4;
87+
private static final int ERROR_INVALID_ARGUMENT = 5;
8688

8789
private static int JOB_ID = 20000;
8890

@@ -125,13 +127,13 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
125127
extras.putString(EXTRA_FILE_NAME, post.getSubredditName()
126128
+ "-" + post.getId() + ".jpg");
127129
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
128-
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
130+
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
129131
} else if (post.getPostType() == Post.GIF_TYPE) {
130132
extras.putString(EXTRA_URL, post.getVideoUrl());
131133
extras.putInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_GIF);
132134
extras.putString(EXTRA_FILE_NAME, post.getSubredditName() + "-" + post.getId() + ".gif");
133135
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
134-
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
136+
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
135137
} else if (post.getPostType() == Post.VIDEO_TYPE) {
136138
if (post.isStreamable()) {
137139
if (post.isLoadRedgifsOrStreamableVideoSuccess()) {
@@ -160,21 +162,21 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
160162

161163
extras.putInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_VIDEO);
162164
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
163-
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
165+
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
164166
} else if (post.getPostType() == Post.GALLERY_TYPE) {
165167
Post.Gallery media = post.getGallery().get(galleryIndex);
166168
if (media.mediaType == Post.Gallery.TYPE_VIDEO) {
167169
extras.putString(EXTRA_URL, media.url);
168170
extras.putInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_VIDEO);
169171
extras.putString(EXTRA_FILE_NAME, media.fileName);
170172
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
171-
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
173+
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
172174
} else {
173175
extras.putString(EXTRA_URL, media.hasFallback() ? media.fallbackUrl : media.url); // Retrieve original instead of the one additionally compressed by reddit
174176
extras.putInt(EXTRA_MEDIA_TYPE, media.mediaType == Post.Gallery.TYPE_GIF ? EXTRA_MEDIA_TYPE_GIF: EXTRA_MEDIA_TYPE_IMAGE);
175177
extras.putString(EXTRA_FILE_NAME, media.fileName);
176178
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
177-
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
179+
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
178180
}
179181
}
180182

@@ -193,11 +195,11 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
193195
}
194196
}
195197

196-
public static JobInfo constructGalleryDownloadAllImagesJobInfo(Context context, long contentEstimatedBytes, Post post) {
198+
public static JobInfo constructGalleryDownloadAllMediaJobInfo(Context context, long contentEstimatedBytes, Post post) {
197199
PersistableBundle extras = new PersistableBundle();
198200
if (post.getPostType() == Post.GALLERY_TYPE) {
199201
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
200-
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
202+
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
201203

202204
ArrayList<Post.Gallery> gallery = post.getGallery();
203205

@@ -234,6 +236,7 @@ public static JobInfo constructGalleryDownloadAllImagesJobInfo(Context context,
234236
extras.putString(EXTRA_ALL_GALLERY_IMAGE_URLS, concatUrlsBuilder.toString());
235237
extras.putString(EXTRA_ALL_GALLERY_IMAGE_MEDIA_TYPES, concatMediaTypesBuilder.toString());
236238
extras.putString(EXTRA_ALL_GALLERY_IMAGE_FILE_NAMES, concatFileNamesBuilder.toString());
239+
extras.putBoolean(EXTRA_IS_ALL_GALLERY_MEDIA, true);
237240
}
238241

239242
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
@@ -276,6 +279,58 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
276279
}
277280
}
278281

282+
public static JobInfo constructImgurAlbumDownloadAllMediaJobInfo(Context context, long contentEstimatedBytes, List<ImgurMedia> imgurMedia) {
283+
PersistableBundle extras = new PersistableBundle();
284+
285+
StringBuilder concatUrlsBuilder = new StringBuilder();
286+
StringBuilder concatMediaTypesBuilder = new StringBuilder();
287+
StringBuilder concatFileNamesBuilder = new StringBuilder();
288+
289+
for (int i = 0; i < imgurMedia.size(); i++) {
290+
ImgurMedia media = imgurMedia.get(i);
291+
292+
if (media.getType() == ImgurMedia.TYPE_VIDEO) {
293+
concatUrlsBuilder.append(media.getLink()).append(" ");
294+
concatMediaTypesBuilder.append(EXTRA_MEDIA_TYPE_VIDEO).append(" ");
295+
concatFileNamesBuilder.append(media.getFileName()).append(" ");
296+
} else {
297+
concatUrlsBuilder.append(media.getLink()).append(" "); // Retrieve original instead of the one additionally compressed by reddit
298+
concatMediaTypesBuilder.append(EXTRA_MEDIA_TYPE_IMAGE).append(" ");
299+
concatFileNamesBuilder.append(media.getFileName()).append(" ");
300+
}
301+
}
302+
303+
if (concatUrlsBuilder.length() > 0) {
304+
concatUrlsBuilder.deleteCharAt(concatUrlsBuilder.length() - 1);
305+
}
306+
307+
if (concatMediaTypesBuilder.length() > 0) {
308+
concatMediaTypesBuilder.deleteCharAt(concatMediaTypesBuilder.length() - 1);
309+
}
310+
311+
if (concatFileNamesBuilder.length() > 0) {
312+
concatFileNamesBuilder.deleteCharAt(concatFileNamesBuilder.length() - 1);
313+
}
314+
315+
extras.putString(EXTRA_ALL_GALLERY_IMAGE_URLS, concatUrlsBuilder.toString());
316+
extras.putString(EXTRA_ALL_GALLERY_IMAGE_MEDIA_TYPES, concatMediaTypesBuilder.toString());
317+
extras.putString(EXTRA_ALL_GALLERY_IMAGE_FILE_NAMES, concatFileNamesBuilder.toString());
318+
319+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
320+
return new JobInfo.Builder(JOB_ID++, new ComponentName(context, DownloadMediaService.class))
321+
.setUserInitiated(true)
322+
.setRequiredNetwork(new NetworkRequest.Builder().clearCapabilities().build())
323+
.setEstimatedNetworkBytes(0, contentEstimatedBytes + 500)
324+
.setExtras(extras)
325+
.build();
326+
} else {
327+
return new JobInfo.Builder(JOB_ID++, new ComponentName(context, DownloadMediaService.class))
328+
.setOverrideDeadline(0)
329+
.setExtras(extras)
330+
.build();
331+
}
332+
}
333+
279334
public static JobInfo constructJobInfo(Context context, long contentEstimatedBytes, PersistableBundle extras) {
280335
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
281336
return new JobInfo.Builder(JOB_ID++, new ComponentName(context, DownloadMediaService.class))
@@ -296,7 +351,6 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
296351
public void onCreate() {
297352
((Infinity) getApplication()).getAppComponent().inject(this);
298353
notificationManager = NotificationManagerCompat.from(this);
299-
Log.i("asdfasdf", "s " + JOB_ID);
300354
}
301355

302356
@Override
@@ -314,7 +368,10 @@ public boolean onStartJob(JobParameters params) {
314368
notificationManager.createNotificationChannel(serviceChannel);
315369

316370
int randomNotificationIdOffset = new Random().nextInt(10000);
317-
String notificationTitle = extras.containsKey(EXTRA_FILE_NAME) ? extras.getString(EXTRA_FILE_NAME) : getString(R.string.download_all_gallery_media_notification_title);
371+
String notificationTitle = extras.containsKey(EXTRA_FILE_NAME) ?
372+
extras.getString(EXTRA_FILE_NAME) :
373+
(extras.getBoolean(EXTRA_IS_ALL_GALLERY_MEDIA, false) ?
374+
getString(R.string.download_all_gallery_media_notification_title) : getString(R.string.download_all_imgur_album_media_notification_title));
318375
switch (extras.getInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_IMAGE)) {
319376
case EXTRA_MEDIA_TYPE_GIF:
320377
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
@@ -352,7 +409,7 @@ public boolean onStartJob(JobParameters params) {
352409

353410
mExecutor.execute(() -> {
354411
String subredditName = extras.getString(EXTRA_SUBREDDIT_NAME);
355-
boolean isNsfw = extras.getInt(EXTRA_IS_NSFW, 0) == 1;
412+
boolean isNsfw = extras.getBoolean(EXTRA_IS_NSFW, false);
356413

357414
if (extras.containsKey(EXTRA_ALL_GALLERY_IMAGE_URLS)) {
358415
// Download all images in a gallery post
@@ -452,14 +509,23 @@ private boolean downloadMedia(JobParameters params, String fileUrl, PersistableB
452509
// Only Redgifs and Streamble video can go inside this if clause.
453510
String redgifsId = intent.getString(EXTRA_REDGIFS_ID, null);
454511
String streamableShortCode = intent.getString(EXTRA_STREAMABLE_SHORT_CODE, null);
512+
513+
if (redgifsId == null && streamableShortCode == null) {
514+
downloadFinished(params, builder, mediaType, randomNotificationIdOffset, mimeType,
515+
null,
516+
ERROR_INVALID_ARGUMENT,
517+
multipleDownloads);
518+
return false;
519+
}
520+
455521
fileUrl = VideoLinkFetcher.fetchVideoLinkSync(mRedgifsRetrofit, mStreamableApiProvider, mCurrentAccountSharedPreferences,
456522
redgifsId == null ? ViewVideoActivity.VIDEO_TYPE_STREAMABLE : ViewVideoActivity.VIDEO_TYPE_REDGIFS,
457523
redgifsId, streamableShortCode);
458524

459525
if (fileUrl == null) {
460526
downloadFinished(params, builder, mediaType, randomNotificationIdOffset, mimeType,
461527
null,
462-
redgifsId == null ? ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK : ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK,
528+
redgifsId == null ? ERROR_CANNOT_FETCH_STREAMABLE_VIDEO_LINK : ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK,
463529
multipleDownloads);
464530
return false;
465531
}
@@ -783,11 +849,15 @@ private void downloadFinished(JobParameters parameters, NotificationCompat.Build
783849
-1, randomNotificationIdOffset, null, null);
784850
break;
785851
case ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK:
786-
updateNotification(builder, mediaType, R.string.downloading_media_failed_cannot_fetch_redgifs_url,
852+
updateNotification(builder, mediaType, R.string.download_media_failed_cannot_fetch_redgifs_url,
853+
-1, randomNotificationIdOffset, null, null);
854+
break;
855+
case ERROR_CANNOT_FETCH_STREAMABLE_VIDEO_LINK:
856+
updateNotification(builder, mediaType, R.string.download_media_failed_cannot_fetch_streamable_url,
787857
-1, randomNotificationIdOffset, null, null);
788858
break;
789-
case ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK:
790-
updateNotification(builder, mediaType, R.string.downloading_media_failed_cannot_fetch_streamable_url,
859+
case ERROR_INVALID_ARGUMENT:
860+
updateNotification(builder, mediaType, R.string.download_media_failed_invalid_argument,
791861
-1, randomNotificationIdOffset, null, null);
792862
break;
793863
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
<item
5+
android:id="@+id/action_download_all_imgur_album_media_view_imgur_media_activity"
6+
android:orderInCategory="10"
7+
android:title="@string/action_download_all_imgur_album_media"
8+
app:showAsAction="never" />
9+
</menu>

app/src/main/res/values/strings.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
<string name="action_add_to_home_screen">Add to Home screen</string>
101101
<string name="action_reset_fab_position">Reset FAB position</string>
102102
<string name="action_download_all_gallery_media">Download All Gallery Media</string>
103+
<string name="action_download_all_imgur_album_media">Download All Imgur Album Media</string>
103104

104105
<string name="parse_json_response_error">Error occurred when parsing the JSON response</string>
105106
<string name="retrieve_token_error">Error Retrieving the token</string>
@@ -1051,9 +1052,11 @@
10511052
<string name="downloading_image_or_gif_failed_cannot_get_destination_directory">Download failed: cannot access destination directory</string>
10521053
<string name="downloading_media_failed_cannot_download_media">Download failed</string>
10531054
<string name="downloading_media_failed_cannot_save_to_destination_directory">Download failed: cannot save the file to destination directory</string>
1054-
<string name="downloading_media_failed_cannot_fetch_redgifs_url">Download failed: cannot fetch Redgifs video url</string>
1055-
<string name="downloading_media_failed_cannot_fetch_streamable_url">Download failed: cannot fetch Streamable video url</string>
1055+
<string name="download_media_failed_cannot_fetch_redgifs_url">Download failed: cannot fetch Redgifs video url</string>
1056+
<string name="download_media_failed_cannot_fetch_streamable_url">Download failed: cannot fetch Streamable video url</string>
1057+
<string name="download_media_failed_invalid_argument">Invalid argument</string>
10561058
<string name="download_all_gallery_media_notification_title">All Gallery Media</string>
1059+
<string name="download_all_imgur_album_media_notification_title">All Imgur Album Media</string>
10571060
<string name="download_gallery_failed_some_images">Downloaded. Some media failed to download.</string>
10581061

10591062
<string name="wallpaper_set">Wallpaper set</string>

0 commit comments

Comments
 (0)