Skip to content

Commit

Permalink
Add an option to download all media in an imgur album in ViewImgurMed…
Browse files Browse the repository at this point in the history
…iaActivity.
  • Loading branch information
Docile-Alligator committed Sep 18, 2024
1 parent 4799a09 commit f042b89
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package ml.docilealligator.infinityforreddit.activities;

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
Expand Down Expand Up @@ -48,6 +51,7 @@
import ml.docilealligator.infinityforreddit.font.TitleFontStyle;
import ml.docilealligator.infinityforreddit.fragments.ViewImgurImageFragment;
import ml.docilealligator.infinityforreddit.fragments.ViewImgurVideoFragment;
import ml.docilealligator.infinityforreddit.services.DownloadMediaService;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.JSONUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
Expand Down Expand Up @@ -297,6 +301,10 @@ private void setToolbarTitle(int position) {

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.view_imgur_media_activity, menu);
for (int i = 0; i < menu.size(); i++) {
Utils.setTitleWithCustomFontToMenuItem(typeface, menu.getItem(i), null);
}
return true;
}

Expand All @@ -305,6 +313,13 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
} else if (item.getItemId() == R.id.action_download_all_imgur_album_media_view_imgur_media_activity) {
//TODO: contentEstimatedBytes
JobInfo jobInfo = DownloadMediaService.constructImgurAlbumDownloadAllMediaJobInfo(this, 5000000L * images.size(), images);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);

Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show();
return true;
}

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
return true;
} else if (item.getItemId() == R.id.action_download_all_gallery_media_view_reddit_gallery_activity) {
//TODO: contentEstimatedBytes
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllImagesJobInfo(this, 5000000, post);
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllMediaJobInfo(this, 5000000L * gallery.size(), post);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);

Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
if (mPost.getPostType() == Post.GALLERY_TYPE) {
binding.downloadAllTextViewPostOptionsBottomSheetFragment.setVisibility(View.VISIBLE);
binding.downloadAllTextViewPostOptionsBottomSheetFragment.setOnClickListener(view -> {
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllImagesJobInfo(mBaseActivity, 5000000, mPost);
JobInfo jobInfo = DownloadMediaService.constructGalleryDownloadAllMediaJobInfo(mBaseActivity, 5000000, mPost);
((JobScheduler) mBaseActivity.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);

dismiss();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import android.os.Environment;
import android.os.PersistableBundle;
import android.provider.MediaStore;
import android.util.Log;

import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat;
Expand All @@ -35,6 +34,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;

Expand Down Expand Up @@ -69,6 +69,7 @@ public class DownloadMediaService extends JobService {
public static final String EXTRA_IS_NSFW = "EIN";
public static final String EXTRA_REDGIFS_ID = "EGI";
public static final String EXTRA_STREAMABLE_SHORT_CODE = "ESSC";
public static final String EXTRA_IS_ALL_GALLERY_MEDIA = "EIAGM";
public static final int EXTRA_MEDIA_TYPE_IMAGE = 0;
public static final int EXTRA_MEDIA_TYPE_GIF = 1;
public static final int EXTRA_MEDIA_TYPE_VIDEO = 2;
Expand All @@ -82,7 +83,8 @@ public class DownloadMediaService extends JobService {
private static final int ERROR_FILE_CANNOT_DOWNLOAD = 1;
private static final int ERROR_FILE_CANNOT_SAVE = 2;
private static final int ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK = 3;
private static final int ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK = 4;
private static final int ERROR_CANNOT_FETCH_STREAMABLE_VIDEO_LINK = 4;
private static final int ERROR_INVALID_ARGUMENT = 5;

private static int JOB_ID = 20000;

Expand Down Expand Up @@ -125,13 +127,13 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
extras.putString(EXTRA_FILE_NAME, post.getSubredditName()
+ "-" + post.getId() + ".jpg");
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
} else if (post.getPostType() == Post.GIF_TYPE) {
extras.putString(EXTRA_URL, post.getVideoUrl());
extras.putInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_GIF);
extras.putString(EXTRA_FILE_NAME, post.getSubredditName() + "-" + post.getId() + ".gif");
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
} else if (post.getPostType() == Post.VIDEO_TYPE) {
if (post.isStreamable()) {
if (post.isLoadRedgifsOrStreamableVideoSuccess()) {
Expand Down Expand Up @@ -160,21 +162,21 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt

extras.putInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_VIDEO);
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
} else if (post.getPostType() == Post.GALLERY_TYPE) {
Post.Gallery media = post.getGallery().get(galleryIndex);
if (media.mediaType == Post.Gallery.TYPE_VIDEO) {
extras.putString(EXTRA_URL, media.url);
extras.putInt(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_VIDEO);
extras.putString(EXTRA_FILE_NAME, media.fileName);
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
} else {
extras.putString(EXTRA_URL, media.hasFallback() ? media.fallbackUrl : media.url); // Retrieve original instead of the one additionally compressed by reddit
extras.putInt(EXTRA_MEDIA_TYPE, media.mediaType == Post.Gallery.TYPE_GIF ? EXTRA_MEDIA_TYPE_GIF: EXTRA_MEDIA_TYPE_IMAGE);
extras.putString(EXTRA_FILE_NAME, media.fileName);
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());
}
}

Expand All @@ -193,11 +195,11 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
}
}

public static JobInfo constructGalleryDownloadAllImagesJobInfo(Context context, long contentEstimatedBytes, Post post) {
public static JobInfo constructGalleryDownloadAllMediaJobInfo(Context context, long contentEstimatedBytes, Post post) {
PersistableBundle extras = new PersistableBundle();
if (post.getPostType() == Post.GALLERY_TYPE) {
extras.putString(EXTRA_SUBREDDIT_NAME, post.getSubredditName());
extras.putInt(EXTRA_IS_NSFW, post.isNSFW() ? 1 : 0);
extras.putBoolean(EXTRA_IS_NSFW, post.isNSFW());

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

Expand Down Expand Up @@ -234,6 +236,7 @@ public static JobInfo constructGalleryDownloadAllImagesJobInfo(Context context,
extras.putString(EXTRA_ALL_GALLERY_IMAGE_URLS, concatUrlsBuilder.toString());
extras.putString(EXTRA_ALL_GALLERY_IMAGE_MEDIA_TYPES, concatMediaTypesBuilder.toString());
extras.putString(EXTRA_ALL_GALLERY_IMAGE_FILE_NAMES, concatFileNamesBuilder.toString());
extras.putBoolean(EXTRA_IS_ALL_GALLERY_MEDIA, true);
}

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

public static JobInfo constructImgurAlbumDownloadAllMediaJobInfo(Context context, long contentEstimatedBytes, List<ImgurMedia> imgurMedia) {
PersistableBundle extras = new PersistableBundle();

StringBuilder concatUrlsBuilder = new StringBuilder();
StringBuilder concatMediaTypesBuilder = new StringBuilder();
StringBuilder concatFileNamesBuilder = new StringBuilder();

for (int i = 0; i < imgurMedia.size(); i++) {
ImgurMedia media = imgurMedia.get(i);

if (media.getType() == ImgurMedia.TYPE_VIDEO) {
concatUrlsBuilder.append(media.getLink()).append(" ");
concatMediaTypesBuilder.append(EXTRA_MEDIA_TYPE_VIDEO).append(" ");
concatFileNamesBuilder.append(media.getFileName()).append(" ");
} else {
concatUrlsBuilder.append(media.getLink()).append(" "); // Retrieve original instead of the one additionally compressed by reddit
concatMediaTypesBuilder.append(EXTRA_MEDIA_TYPE_IMAGE).append(" ");
concatFileNamesBuilder.append(media.getFileName()).append(" ");
}
}

if (concatUrlsBuilder.length() > 0) {
concatUrlsBuilder.deleteCharAt(concatUrlsBuilder.length() - 1);
}

if (concatMediaTypesBuilder.length() > 0) {
concatMediaTypesBuilder.deleteCharAt(concatMediaTypesBuilder.length() - 1);
}

if (concatFileNamesBuilder.length() > 0) {
concatFileNamesBuilder.deleteCharAt(concatFileNamesBuilder.length() - 1);
}

extras.putString(EXTRA_ALL_GALLERY_IMAGE_URLS, concatUrlsBuilder.toString());
extras.putString(EXTRA_ALL_GALLERY_IMAGE_MEDIA_TYPES, concatMediaTypesBuilder.toString());
extras.putString(EXTRA_ALL_GALLERY_IMAGE_FILE_NAMES, concatFileNamesBuilder.toString());

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().clearCapabilities().build())
.setEstimatedNetworkBytes(0, contentEstimatedBytes + 500)
.setExtras(extras)
.build();
} else {
return new JobInfo.Builder(JOB_ID++, new ComponentName(context, DownloadMediaService.class))
.setOverrideDeadline(0)
.setExtras(extras)
.build();
}
}

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))
Expand All @@ -296,7 +351,6 @@ public static JobInfo constructJobInfo(Context context, long contentEstimatedByt
public void onCreate() {
((Infinity) getApplication()).getAppComponent().inject(this);
notificationManager = NotificationManagerCompat.from(this);
Log.i("asdfasdf", "s " + JOB_ID);
}

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

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

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

if (extras.containsKey(EXTRA_ALL_GALLERY_IMAGE_URLS)) {
// Download all images in a gallery post
Expand Down Expand Up @@ -452,14 +509,23 @@ private boolean downloadMedia(JobParameters params, String fileUrl, PersistableB
// Only Redgifs and Streamble video can go inside this if clause.
String redgifsId = intent.getString(EXTRA_REDGIFS_ID, null);
String streamableShortCode = intent.getString(EXTRA_STREAMABLE_SHORT_CODE, null);

if (redgifsId == null && streamableShortCode == null) {
downloadFinished(params, builder, mediaType, randomNotificationIdOffset, mimeType,
null,
ERROR_INVALID_ARGUMENT,
multipleDownloads);
return false;
}

fileUrl = VideoLinkFetcher.fetchVideoLinkSync(mRedgifsRetrofit, mStreamableApiProvider, mCurrentAccountSharedPreferences,
redgifsId == null ? ViewVideoActivity.VIDEO_TYPE_STREAMABLE : ViewVideoActivity.VIDEO_TYPE_REDGIFS,
redgifsId, streamableShortCode);

if (fileUrl == null) {
downloadFinished(params, builder, mediaType, randomNotificationIdOffset, mimeType,
null,
redgifsId == null ? ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK : ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK,
redgifsId == null ? ERROR_CANNOT_FETCH_STREAMABLE_VIDEO_LINK : ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK,
multipleDownloads);
return false;
}
Expand Down Expand Up @@ -783,11 +849,15 @@ private void downloadFinished(JobParameters parameters, NotificationCompat.Build
-1, randomNotificationIdOffset, null, null);
break;
case ERROR_FILE_CANNOT_FETCH_REDGIFS_VIDEO_LINK:
updateNotification(builder, mediaType, R.string.downloading_media_failed_cannot_fetch_redgifs_url,
updateNotification(builder, mediaType, R.string.download_media_failed_cannot_fetch_redgifs_url,
-1, randomNotificationIdOffset, null, null);
break;
case ERROR_CANNOT_FETCH_STREAMABLE_VIDEO_LINK:
updateNotification(builder, mediaType, R.string.download_media_failed_cannot_fetch_streamable_url,
-1, randomNotificationIdOffset, null, null);
break;
case ERROR_FILE_CANNOT_FETCH_STREAMABLE_VIDEO_LINK:
updateNotification(builder, mediaType, R.string.downloading_media_failed_cannot_fetch_streamable_url,
case ERROR_INVALID_ARGUMENT:
updateNotification(builder, mediaType, R.string.download_media_failed_invalid_argument,
-1, randomNotificationIdOffset, null, null);
break;
}
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/res/menu/view_imgur_media_activity.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_download_all_imgur_album_media_view_imgur_media_activity"
android:orderInCategory="10"
android:title="@string/action_download_all_imgur_album_media"
app:showAsAction="never" />
</menu>
7 changes: 5 additions & 2 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
<string name="action_add_to_home_screen">Add to Home screen</string>
<string name="action_reset_fab_position">Reset FAB position</string>
<string name="action_download_all_gallery_media">Download All Gallery Media</string>
<string name="action_download_all_imgur_album_media">Download All Imgur Album Media</string>

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

<string name="wallpaper_set">Wallpaper set</string>
Expand Down

0 comments on commit f042b89

Please sign in to comment.