aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAlex Ning <chineseperson5@gmail.com>2020-10-15 15:39:05 +0000
committerAlex Ning <chineseperson5@gmail.com>2020-10-15 15:39:05 +0000
commitd23af6981aed4667326f05aba75836f0bb124bed (patch)
tree3a42f5b54027535a927901fcee828fa7b4f678b5 /app
parent6284de74fe6529fde5c22292e6ba251000941e61 (diff)
downloadinfinity-for-reddit-d23af6981aed4667326f05aba75836f0bb124bed.tar
infinity-for-reddit-d23af6981aed4667326f05aba75836f0bb124bed.tar.gz
infinity-for-reddit-d23af6981aed4667326f05aba75836f0bb124bed.tar.bz2
infinity-for-reddit-d23af6981aed4667326f05aba75836f0bb124bed.tar.lz
infinity-for-reddit-d23af6981aed4667326f05aba75836f0bb124bed.tar.xz
infinity-for-reddit-d23af6981aed4667326f05aba75836f0bb124bed.tar.zst
infinity-for-reddit-d23af6981aed4667326f05aba75836f0bb124bed.zip
Show progress when downloding images and gifs.
Diffstat (limited to '')
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/DownloadProgressResponseBody.java56
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java141
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java45
-rw-r--r--app/src/main/res/values/strings.xml5
4 files changed, 187 insertions, 60 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/DownloadProgressResponseBody.java b/app/src/main/java/ml/docilealligator/infinityforreddit/DownloadProgressResponseBody.java
new file mode 100644
index 00000000..4bad1623
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/DownloadProgressResponseBody.java
@@ -0,0 +1,56 @@
+package ml.docilealligator.infinityforreddit;
+
+import java.io.IOException;
+
+import okhttp3.MediaType;
+import okhttp3.ResponseBody;
+import okio.Buffer;
+import okio.BufferedSource;
+import okio.ForwardingSource;
+import okio.Okio;
+import okio.Source;
+
+public class DownloadProgressResponseBody extends ResponseBody {
+
+ private final ResponseBody responseBody;
+ private final ProgressListener progressListener;
+ private BufferedSource bufferedSource;
+
+ public DownloadProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
+ this.responseBody = responseBody;
+ this.progressListener = progressListener;
+ }
+
+ @Override public MediaType contentType() {
+ return responseBody.contentType();
+ }
+
+ @Override public long contentLength() {
+ return responseBody.contentLength();
+ }
+
+ @Override public BufferedSource source() {
+ if (bufferedSource == null) {
+ bufferedSource = Okio.buffer(source(responseBody.source()));
+ }
+ return bufferedSource;
+ }
+
+ private Source source(Source source) {
+ return new ForwardingSource(source) {
+ long totalBytesRead = 0L;
+
+ @Override public long read(Buffer sink, long byteCount) throws IOException {
+ long bytesRead = super.read(sink, byteCount);
+ // read() returns the number of bytes read, or -1 if this source is exhausted.
+ totalBytesRead += bytesRead != -1 ? bytesRead : 0;
+ progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
+ return bytesRead;
+ }
+ };
+ }
+
+ public interface ProgressListener {
+ void update(long bytesRead, long contentLength, boolean done);
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java
index e3f5e10e..61d9ce3d 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadMediaService.java
@@ -7,7 +7,6 @@ import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentResolver;
import android.content.ContentValues;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaScannerConnection;
@@ -17,6 +16,7 @@ import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.provider.MediaStore;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
@@ -36,11 +36,13 @@ import javax.inject.Named;
import ml.docilealligator.infinityforreddit.API.DownloadFile;
import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.DownloadProgressResponseBody;
import ml.docilealligator.infinityforreddit.Event.DownloadMediaEvent;
import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils;
+import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
@@ -72,6 +74,9 @@ public class DownloadMediaService extends Service {
CustomThemeWrapper mCustomThemeWrapper;
private int mediaType;
private String mimeType;
+ private NotificationManagerCompat notificationManager;
+ private NotificationCompat.Builder builder;
+ private boolean downloadFinished;
public DownloadMediaService() {
}
@@ -129,12 +134,55 @@ public class DownloadMediaService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
((Infinity) getApplication()).getAppComponent().inject(this);
+ notificationManager = NotificationManagerCompat.from(this);
+ builder = new NotificationCompat.Builder(this, getNotificationChannelId());
+
+ downloadFinished = false;
String fileUrl = intent.getStringExtra(EXTRA_URL);
final String[] fileName = {intent.getStringExtra(EXTRA_FILE_NAME)};
String subredditName = intent.getStringExtra(EXTRA_SUBREDDIT_NAME);
mediaType = intent.getIntExtra(EXTRA_MEDIA_TYPE, EXTRA_MEDIA_TYPE_IMAGE);
mimeType = mediaType == EXTRA_MEDIA_TYPE_VIDEO ? "video/*" : "image/*";
+ final DownloadProgressResponseBody.ProgressListener progressListener = new DownloadProgressResponseBody.ProgressListener() {
+ boolean firstUpdate = true;
+ long time = 0;
+
+ @Override public void update(long bytesRead, long contentLength, boolean done) {
+ if (done) {
+ //updateNotification(0, null, -1, null);
+ } else {
+ if (firstUpdate) {
+ firstUpdate = false;
+ if (contentLength == -1) {
+ Log.i("adfasdf", "content-length: unknown");
+ } else {
+ Log.i("adfasdf", "content-length: " + contentLength);
+ }
+ }
+
+ if (contentLength != -1) {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - time) / 1000 > 2) {
+ time = currentTime;
+ updateNotification(0, (int) ((100 * bytesRead) / contentLength), null);
+ }
+ }
+ }
+ }
+ };
+
+ OkHttpClient client = new OkHttpClient.Builder()
+ .addNetworkInterceptor(chain -> {
+ okhttp3.Response originalResponse = chain.proceed(chain.request());
+ return originalResponse.newBuilder()
+ .body(new DownloadProgressResponseBody(originalResponse.body(), progressListener))
+ .build();
+ })
+ .build();
+
+ retrofit = retrofit.newBuilder().client(client).build();
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel;
serviceChannel = new NotificationChannel(
@@ -151,19 +199,19 @@ public class DownloadMediaService extends Service {
case EXTRA_MEDIA_TYPE_GIF:
startForeground(
NotificationUtils.DOWNLOAD_GIF_NOTIFICATION_ID,
- createNotification(R.string.downloading_gif, fileName[0], null)
+ createNotification(fileName[0])
);
break;
case EXTRA_MEDIA_TYPE_VIDEO:
startForeground(
NotificationUtils.DOWNLOAD_VIDEO_NOTIFICATION_ID,
- createNotification(R.string.downloading_video, fileName[0], null)
+ createNotification(fileName[0])
);
break;
default:
startForeground(
NotificationUtils.DOWNLOAD_IMAGE_NOTIFICATION_ID,
- createNotification(R.string.downloading_image, fileName[0], null)
+ createNotification(fileName[0])
);
}
@@ -183,12 +231,12 @@ 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(null, fileName[0], ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
+ downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
destinationFileUriString = directoryPath + fileName[0];
} else {
- downloadFinished(null, fileName[0], ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
+ downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
} else {
@@ -203,21 +251,21 @@ public class DownloadMediaService extends Service {
if (separateDownloadFolder && subredditName != null && !subredditName.equals("")) {
dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory));
if (dir == null) {
- downloadFinished(null, fileName[0], ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
+ downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
dir = dir.findFile(subredditName);
if (dir == null) {
dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory)).createDirectory(subredditName);
if (dir == null) {
- downloadFinished(null, fileName[0], ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
+ downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
}
} else {
dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory));
if (dir == null) {
- downloadFinished(null, fileName[0], ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
+ downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
}
@@ -232,7 +280,7 @@ public class DownloadMediaService extends Service {
}
picFile = dir.createFile(mimeType, fileName[0]);
if (picFile == null) {
- downloadFinished(null, fileName[0], ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
+ downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY);
return;
}
destinationFileUriString = picFile.getUri().toString();
@@ -240,58 +288,59 @@ public class DownloadMediaService extends Service {
new SaveImageOrGifAndCopyToExternalStorageAsyncTask(response.body(), mediaType,
isDefaultDestination, fileName[0], destinationFileUriString, getContentResolver(),
- new SaveImageOrGifAndCopyToExternalStorageAsyncTask.SaveImageOrGifAndCopyToExternalStorageAsyncTaskListener() {
- @Override
- public void finished(Uri destinationFileUri, int errorCode) {
- downloadFinished(destinationFileUri, fileName[0], errorCode);
- }
-
- @Override
- public void updateProgressNotification(int stringResId) {
- updateNotification(stringResId, fileName[0], null);
- }
- }).execute();
+ (destinationFileUri, errorCode) -> downloadFinished(destinationFileUri, errorCode)).execute();
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
- downloadFinished(null, fileName[0], ERROR_FILE_CANNOT_DOWNLOAD);
+ downloadFinished(null, ERROR_FILE_CANNOT_DOWNLOAD);
}
});
return super.onStartCommand(intent, flags, startId);
}
- private Notification createNotification(int stringResId, String fileName, PendingIntent pendingIntent) {
- NotificationCompat.Builder builder;
- builder = new NotificationCompat.Builder(this, getNotificationChannelId());
- builder.setContentTitle(fileName).setContentText(getString(stringResId));
- if (pendingIntent != null) {
- builder.setContentIntent(pendingIntent);
- }
+ private Notification createNotification(String fileName) {
+ builder.setContentTitle(fileName).setContentText(getString(R.string.downloading))
+ .setProgress(100, 0, false);
return builder.setSmallIcon(R.drawable.ic_notification)
.setColor(mCustomThemeWrapper.getColorPrimaryLightTheme())
.build();
}
- private void updateNotification(int stringResId, String fileName, PendingIntent pendingIntent) {
- NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ private void updateNotification(int contentStringResId, int progress, PendingIntent pendingIntent) {
if (notificationManager != null) {
- notificationManager.notify(getNotificationId(), createNotification(stringResId, fileName, pendingIntent));
+ if (progress < 0) {
+ builder.setProgress(0, 0, false);
+ } else {
+ builder.setProgress(100, progress, false);
+ }
+ if (contentStringResId != 0) {
+ builder.setContentText(getString(contentStringResId));
+ }
+ if (pendingIntent != null) {
+ builder.setContentIntent(pendingIntent);
+ }
+ notificationManager.notify(getNotificationId(), builder.build());
}
}
- private void downloadFinished(Uri destinationFileUri, String fileName, int errorCode) {
+ private void downloadFinished(Uri destinationFileUri, int errorCode) {
+ if (downloadFinished) {
+ return;
+ }
+
+ downloadFinished = true;
if (errorCode != NO_ERROR) {
switch (errorCode) {
case ERROR_CANNOT_GET_DESTINATION_DIRECTORY:
- updateNotification(R.string.downloading_image_or_gif_failed_cannot_get_destination_directory, fileName, null);
+ updateNotification(R.string.downloading_image_or_gif_failed_cannot_get_destination_directory, -1, null);
break;
case ERROR_FILE_CANNOT_DOWNLOAD:
- updateNotification(R.string.downloading_media_failed_cannot_download_media, fileName, null);
+ updateNotification(R.string.downloading_media_failed_cannot_download_media, -1, null);
break;
case ERROR_FILE_CANNOT_SAVE:
- updateNotification(R.string.downloading_media_failed_cannot_save_to_destination_directory, fileName, null);
+ updateNotification(R.string.downloading_media_failed_cannot_save_to_destination_directory, -1, null);
break;
}
EventBus.getDefault().post(new DownloadMediaEvent(false));
@@ -304,7 +353,7 @@ public class DownloadMediaService extends Service {
intent.setDataAndType(destinationFileUri, mimeType);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
- updateNotification(R.string.downloading_media_finished, fileName, pendingIntent);
+ updateNotification(R.string.downloading_media_finished, -1, pendingIntent);
EventBus.getDefault().post(new DownloadMediaEvent(true));
}
);
@@ -326,7 +375,6 @@ public class DownloadMediaService extends Service {
interface SaveImageOrGifAndCopyToExternalStorageAsyncTaskListener {
void finished(Uri destinationFileUri, int errorCode);
- void updateProgressNotification(int stringResId);
}
public SaveImageOrGifAndCopyToExternalStorageAsyncTask(ResponseBody response, int mediaType,
@@ -345,24 +393,7 @@ public class DownloadMediaService extends Service {
}
@Override
- protected void onProgressUpdate(Integer... values) {
- super.onProgressUpdate(values);
- saveImageOrGifAndCopyToExternalStorageAsyncTaskListener.updateProgressNotification(values[0]);
- }
-
- @Override
protected Void doInBackground(Void... voids) {
- switch (mediaType) {
- case EXTRA_MEDIA_TYPE_IMAGE:
- publishProgress(R.string.downloading_image_save_image);
- break;
- case EXTRA_MEDIA_TYPE_GIF:
- publishProgress(R.string.downloading_gif_save_gif);
- break;
- case EXTRA_MEDIA_TYPE_VIDEO:
- publishProgress(R.string.downloading_video_save_video);
- }
-
try {
writeResponseBodyToDisk(response);
} catch (IOException e) {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
index c8d31b8d..6ae6350b 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
@@ -21,6 +21,7 @@ import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.provider.MediaStore;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
@@ -42,11 +43,13 @@ import javax.inject.Named;
import ml.docilealligator.infinityforreddit.API.DownloadFile;
import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.DownloadProgressResponseBody;
import ml.docilealligator.infinityforreddit.Event.DownloadRedditVideoEvent;
import ml.docilealligator.infinityforreddit.Infinity;
-import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
import ml.docilealligator.infinityforreddit.R;
+import ml.docilealligator.infinityforreddit.Utils.NotificationUtils;
import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils;
+import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
@@ -92,6 +95,46 @@ public class DownloadRedditVideoService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
((Infinity) getApplication()).getAppComponent().inject(this);
+
+ final DownloadProgressResponseBody.ProgressListener progressListener = new DownloadProgressResponseBody.ProgressListener() {
+ boolean firstUpdate = true;
+
+ @Override public void update(long bytesRead, long contentLength, boolean done) {
+ if (done) {
+ Log.i("adfasdf", "completed");
+ } else {
+ if (firstUpdate) {
+ firstUpdate = false;
+ if (contentLength == -1) {
+ Log.i("adfasdf", "content-length: unknown");
+ } else {
+ Log.i("adfasdf", "content-length: " + contentLength);
+ }
+ }
+
+ Log.i("adfasdf", "bytes read " + bytesRead);
+
+ if (contentLength != -1) {
+ Log.i("adfasdf", "progress: " + ((100 * bytesRead) / contentLength));
+ }
+ }
+ }
+ };
+
+ OkHttpClient client = new OkHttpClient.Builder()
+ .addNetworkInterceptor(chain -> {
+ okhttp3.Response originalResponse = chain.proceed(chain.request());
+ return originalResponse.newBuilder()
+ .body(new DownloadProgressResponseBody(originalResponse.body(), progressListener))
+ .build();
+ })
+ .build();
+
+ retrofit = retrofit.newBuilder().client(client).build();
+
+
+
+
String videoUrl = intent.getStringExtra(EXTRA_VIDEO_URL);
String audioUrl = videoUrl.substring(0, videoUrl.lastIndexOf('/')) + "/DASH_audio.mp4";
String subredditName = intent.getStringExtra(EXTRA_SUBREDDIT);
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a776fe86..294f9fce 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -857,10 +857,7 @@
<string name="downloading_video">Downloading Video</string>
<string name="downloading_video_save_video">Saving Video</string>
- <string name="downloading_image">Downloading Image</string>
- <string name="downloading_gif">Downloading Gif</string>
- <string name="downloading_image_save_image">Saving Image</string>
- <string name="downloading_gif_save_gif">Saving Gif</string>
+ <string name="downloading">Downloading</string>
<string name="downloading_media_finished">Downloaded</string>
<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>