aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/ml/docilealligator/infinityforreddit
diff options
context:
space:
mode:
authorAlex Ning <chineseperson5@gmail.com>2020-06-06 13:33:03 +0000
committerAlex Ning <chineseperson5@gmail.com>2020-06-06 13:33:03 +0000
commit22576dc003ddaeb0c06f94eaf5f66598e5b3554f (patch)
tree2f86b927d4ea614776a49ac67c1a910ff13b0897 /app/src/main/java/ml/docilealligator/infinityforreddit
parentff5691aecb0f53ab11ea5a74244d10da7582cf26 (diff)
downloadinfinity-for-reddit-22576dc003ddaeb0c06f94eaf5f66598e5b3554f.tar
infinity-for-reddit-22576dc003ddaeb0c06f94eaf5f66598e5b3554f.tar.gz
infinity-for-reddit-22576dc003ddaeb0c06f94eaf5f66598e5b3554f.tar.bz2
infinity-for-reddit-22576dc003ddaeb0c06f94eaf5f66598e5b3554f.tar.lz
infinity-for-reddit-22576dc003ddaeb0c06f94eaf5f66598e5b3554f.tar.xz
infinity-for-reddit-22576dc003ddaeb0c06f94eaf5f66598e5b3554f.tar.zst
infinity-for-reddit-22576dc003ddaeb0c06f94eaf5f66598e5b3554f.zip
Downloading Reddit videos with sound is now available. For Android Q and above, the downloaded videos are stored in Movies/Infinity.
Diffstat (limited to 'app/src/main/java/ml/docilealligator/infinityforreddit')
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/API/DownloadRedditVideo.java13
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java79
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java4
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java3
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java10
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Event/DownloadRedditVideoEvent.java9
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java3
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java480
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java9
10 files changed, 574 insertions, 38 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/API/DownloadRedditVideo.java b/app/src/main/java/ml/docilealligator/infinityforreddit/API/DownloadRedditVideo.java
new file mode 100644
index 00000000..7e51123d
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/API/DownloadRedditVideo.java
@@ -0,0 +1,13 @@
+package ml.docilealligator.infinityforreddit.API;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.GET;
+import retrofit2.http.Streaming;
+import retrofit2.http.Url;
+
+public interface DownloadRedditVideo {
+ @Streaming
+ @GET()
+ Call<ResponseBody> downloadFile(@Url String fileUrl);
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java
index 709a8cd5..408d180d 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java
@@ -67,7 +67,7 @@ class AccessTokenAuthenticator implements Authenticator {
Call<String> accessTokenCall = api.getAccessToken(APIUtils.getHttpBasicAuthHeader(), params);
try {
- retrofit2.Response response = accessTokenCall.execute();
+ retrofit2.Response<String> response = accessTokenCall.execute();
if (response.isSuccessful() && response.body() != null) {
JSONObject jsonObject = new JSONObject((String) response.body());
String newAccessToken = jsonObject.getString(APIUtils.ACCESS_TOKEN_KEY);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java
index 29b78878..0bd5f7fc 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewVideoActivity.java
@@ -59,6 +59,7 @@ import butterknife.ButterKnife;
import ml.docilealligator.infinityforreddit.FetchGfycatVideoLinks;
import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
+import ml.docilealligator.infinityforreddit.Service.DownloadRedditVideoService;
import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils;
import retrofit2.Retrofit;
@@ -94,11 +95,14 @@ public class ViewVideoActivity extends AppCompatActivity {
private String videoDownloadUrl;
private String videoFileName;
+ private String subredditName;
+ private String id;
private boolean wasPlaying;
private boolean isDownloading = false;
private boolean isMute = false;
private String postTitle;
private long resumePosition = -1;
+ private int videoType;
@Inject
@Named("gfycat")
@@ -181,7 +185,7 @@ public class ViewVideoActivity extends AppCompatActivity {
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
videoPlayerView.setPlayer(player);
- int videoType = getIntent().getIntExtra(EXTRA_VIDEO_TYPE, VIDEO_TYPE_NORMAL);
+ videoType = getIntent().getIntExtra(EXTRA_VIDEO_TYPE, VIDEO_TYPE_NORMAL);
if (videoType == VIDEO_TYPE_GFYCAT || videoType == VIDEO_TYPE_REDGIFS) {
if (savedInstanceState != null) {
String videoUrl = savedInstanceState.getString(VIDEO_URI_STATE);
@@ -243,7 +247,9 @@ public class ViewVideoActivity extends AppCompatActivity {
player.prepare(new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mVideoUri));
} else {
videoDownloadUrl = intent.getStringExtra(EXTRA_VIDEO_DOWNLOAD_URL);
- videoFileName = intent.getStringExtra(EXTRA_SUBREDDIT) + "-" + intent.getStringExtra(EXTRA_ID) + ".mp4";
+ subredditName = intent.getStringExtra(EXTRA_SUBREDDIT);
+ id = intent.getStringExtra(EXTRA_ID);
+ videoFileName = subredditName + "-" + id + ".mp4";
// Produces DataSource instances through which media data is loaded.
dataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "Infinity"));
// Prepare the player with the source.
@@ -387,46 +393,59 @@ public class ViewVideoActivity extends AppCompatActivity {
private void download() {
isDownloading = false;
- DownloadManager.Request request = new DownloadManager.Request(Uri.parse(videoDownloadUrl));
- request.setTitle(videoFileName);
+ if (videoType != VIDEO_TYPE_NORMAL) {
+ DownloadManager.Request request = new DownloadManager.Request(Uri.parse(videoDownloadUrl));
+ request.setTitle(videoFileName);
- request.allowScanningByMediaScanner();
- request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ request.allowScanningByMediaScanner();
+ request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
- //Android Q support
- if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, videoFileName);
- } else {
- String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
- File directory = new File(path + "/Infinity/");
- boolean saveToInfinityFolder = true;
- if (!directory.exists()) {
- if (!directory.mkdir()) {
- saveToInfinityFolder = false;
- }
+ //Android Q support
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, videoFileName);
} else {
- if (directory.isFile()) {
- if (!(directory.delete() && directory.mkdir())) {
+ String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
+ File directory = new File(path + "/Infinity/");
+ boolean saveToInfinityFolder = true;
+ if (!directory.exists()) {
+ if (!directory.mkdir()) {
saveToInfinityFolder = false;
}
+ } else {
+ if (directory.isFile()) {
+ if (!(directory.delete() && directory.mkdir())) {
+ saveToInfinityFolder = false;
+ }
+ }
+ }
+
+ if (saveToInfinityFolder) {
+ request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES + "/Infinity/", videoFileName);
+ } else {
+ request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, videoFileName);
}
}
- if (saveToInfinityFolder) {
- request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES + "/Infinity/", videoFileName);
- } else {
- request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, videoFileName);
+ DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
+
+ if (manager == null) {
+ Toast.makeText(this, R.string.download_failed, Toast.LENGTH_SHORT).show();
+ return;
}
- }
- DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
+ manager.enqueue(request);
+ } else {
+ Intent 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);
- if (manager == null) {
- Toast.makeText(this, R.string.download_failed, Toast.LENGTH_SHORT).show();
- return;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ startForegroundService(intent);
+ } else {
+ startService(intent);
+ }
}
-
- manager.enqueue(request);
Toast.makeText(this, R.string.download_started, Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java
index eea62a78..07009344 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/PostRecyclerViewAdapter.java
@@ -879,7 +879,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView
intent.setData(videoUri);
intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_DOWNLOAD_URL, post.getVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.EXTRA_SUBREDDIT, subredditName);
- intent.putExtra(ViewVideoActivity.EXTRA_ID, fullName);
+ intent.putExtra(ViewVideoActivity.EXTRA_ID, id);
mActivity.startActivity(intent);
});
@@ -2130,7 +2130,7 @@ public class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView
intent.setData(Uri.parse(post.getVideoUrl()));
intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_DOWNLOAD_URL, post.getVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.EXTRA_SUBREDDIT, post.getSubredditName());
- intent.putExtra(ViewVideoActivity.EXTRA_ID, post.getFullName());
+ intent.putExtra(ViewVideoActivity.EXTRA_ID, post.getId());
intent.putExtra(ViewVideoActivity.EXTRA_POST_TITLE, post.getTitle());
mActivity.startActivity(intent);
} else if (post.getPostType() == Post.GIF_TYPE) {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
index 86274fd6..4ee9fe85 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java
@@ -51,6 +51,7 @@ import ml.docilealligator.infinityforreddit.Fragment.SubredditListingFragment;
import ml.docilealligator.infinityforreddit.Fragment.SubscribedSubredditsListingFragment;
import ml.docilealligator.infinityforreddit.Fragment.UserListingFragment;
import ml.docilealligator.infinityforreddit.Fragment.ViewImgurVideoFragment;
+import ml.docilealligator.infinityforreddit.Service.DownloadRedditVideoService;
import ml.docilealligator.infinityforreddit.Service.SubmitPostService;
import ml.docilealligator.infinityforreddit.Settings.AdvancedPreferenceFragment;
import ml.docilealligator.infinityforreddit.Settings.CustomizeMainPageTabsFragment;
@@ -173,4 +174,6 @@ public interface AppComponent {
void inject(ViewImgurMediaActivity viewImgurMediaActivity);
void inject(ViewImgurVideoFragment viewImgurVideoFragment);
+
+ void inject(DownloadRedditVideoService downloadRedditVideoService);
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java
index 8fe1e28d..f4f32b20 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java
@@ -91,6 +91,16 @@ class AppModule {
}
@Provides
+ @Named("download_reddit_video")
+ @Singleton
+ Retrofit provideDownloadRedditVideoRetrofit() {
+ return new Retrofit.Builder()
+ .baseUrl("http://localhost/")
+ .addConverterFactory(ScalarsConverterFactory.create())
+ .build();
+ }
+
+ @Provides
@Named("gfycat")
@Singleton
Retrofit provideGfycatRetrofit() {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Event/DownloadRedditVideoEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/DownloadRedditVideoEvent.java
new file mode 100644
index 00000000..2edb279e
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Event/DownloadRedditVideoEvent.java
@@ -0,0 +1,9 @@
+package ml.docilealligator.infinityforreddit.Event;
+
+public class DownloadRedditVideoEvent {
+ public boolean isSuccessful;
+
+ public DownloadRedditVideoEvent(boolean isSuccessful) {
+ this.isSuccessful = isSuccessful;
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java
index 36160d0c..155e4b02 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java
@@ -11,7 +11,10 @@ public class NotificationUtils {
public static final String CHANNEL_SUBMIT_POST = "Submit Post";
static final String CHANNEL_ID_NEW_MESSAGES = "new_messages";
static final String CHANNEL_NEW_MESSAGES = "New Messages";
+ public static final String CHANNEL_ID_DOWNLOAD_REDDIT_VIDEO = "download_reddit_video";
+ public static final String CHANNEL_DOWNLOAD_REDDIT_VIDEO = "Download Reddit Video";
public static final int SUBMIT_POST_SERVICE_NOTIFICATION_ID = 10000;
+ public static final int DOWNLOAD_REDDIT_VIDEO_NOTIFICATION_ID = 20000;
private static final int SUMMARY_BASE_ID_UNREAD_MESSAGE = 0;
private static final int NOTIFICATION_BASE_ID_UNREAD_MESSAGE = 1;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
new file mode 100644
index 00000000..e5885c90
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/DownloadRedditVideoService.java
@@ -0,0 +1,480 @@
+package ml.docilealligator.infinityforreddit.Service;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.net.Uri;
+import android.os.AsyncTask;
+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.annotation.RequiresApi;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import ml.docilealligator.infinityforreddit.CustomTheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.Event.DownloadRedditVideoEvent;
+import ml.docilealligator.infinityforreddit.Infinity;
+import ml.docilealligator.infinityforreddit.NotificationUtils;
+import ml.docilealligator.infinityforreddit.R;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+
+import static android.os.Environment.getExternalStoragePublicDirectory;
+
+public class DownloadRedditVideoService extends Service {
+ public static final String EXTRA_VIDEO_URL = "EVU";
+ public static final String EXTRA_SUBREDDIT = "ES";
+ public static final String EXTRA_POST_ID = "EPI";
+
+ @Inject
+ @Named("download_reddit_video")
+ Retrofit retrofit;
+ @Inject
+ CustomThemeWrapper mCustomThemeWrapper;
+
+ public DownloadRedditVideoService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ ((Infinity) getApplication()).getAppComponent().inject(this);
+
+ String videoUrl = intent.getStringExtra(EXTRA_VIDEO_URL);
+ String audioUrl = videoUrl.substring(0, videoUrl.lastIndexOf('/')) + "/audio";
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel serviceChannel = new NotificationChannel(
+ NotificationUtils.CHANNEL_ID_DOWNLOAD_REDDIT_VIDEO,
+ NotificationUtils.CHANNEL_DOWNLOAD_REDDIT_VIDEO,
+ NotificationManager.IMPORTANCE_LOW
+ );
+
+ NotificationManagerCompat manager = NotificationManagerCompat.from(this);
+ manager.createNotificationChannel(serviceChannel);
+ }
+
+ startForeground(NotificationUtils.DOWNLOAD_REDDIT_VIDEO_NOTIFICATION_ID, createNotification(R.string.downloading_reddit_video));
+
+ ml.docilealligator.infinityforreddit.API.DownloadRedditVideo downloadRedditVideo = retrofit.create(ml.docilealligator.infinityforreddit.API.DownloadRedditVideo.class);
+ downloadRedditVideo.downloadFile(videoUrl).enqueue(new Callback<ResponseBody>() {
+ @Override
+ public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> videoResponse) {
+ if (videoResponse.isSuccessful() && videoResponse.body() != null) {
+ String fileNameWithoutExtension = intent.getStringExtra(EXTRA_SUBREDDIT)
+ + "-" + intent.getStringExtra(EXTRA_POST_ID);
+
+ downloadRedditVideo.downloadFile(audioUrl).enqueue(new Callback<ResponseBody>() {
+ @Override
+ public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> audioResponse) {
+ File directory = getExternalCacheDir();
+ if (directory != null) {
+ String directoryPath = directory.getAbsolutePath() + "/";
+ if (audioResponse.isSuccessful() && audioResponse.body() != null) {
+ String videoFilePath = writeResponseBodyToDisk(videoResponse.body(), directoryPath + fileNameWithoutExtension+ "-cache.mp4");
+ if (videoFilePath != null) {
+ String audioFilePath = writeResponseBodyToDisk(audioResponse.body(), directoryPath + fileNameWithoutExtension + "-cache.mp3");
+ if (audioFilePath != null) {
+ String outputFilePath = directoryPath + fileNameWithoutExtension + ".mp4";
+ if(muxVideoAndAudio(videoFilePath, audioFilePath, outputFilePath)) {
+ new CopyFileAsyncTask(new File(outputFilePath), fileNameWithoutExtension + ".mp4",
+ getContentResolver(), new CopyFileAsyncTask.CopyFileAsyncTaskListener() {
+ @Override
+ public void successful() {
+ new File(videoFilePath).delete();
+ new File(audioFilePath).delete();
+ new File(outputFilePath).delete();
+
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(true));
+
+ stopService();
+ }
+
+ @Override
+ public void failed() {
+ new File(videoFilePath).delete();
+ new File(audioFilePath).delete();
+ new File(outputFilePath).delete();
+
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ }).execute();
+ } else {
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ } else {
+ new File(videoFilePath).delete();
+
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ } else {
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ } else {
+ //No audio
+ String videoFilePath = writeResponseBodyToDisk(videoResponse.body(), directoryPath + fileNameWithoutExtension+ ".mp4");
+ if (videoFilePath != null) {
+ new CopyFileAsyncTask(new File(videoFilePath), fileNameWithoutExtension + ".mp4",
+ getContentResolver(), new CopyFileAsyncTask.CopyFileAsyncTaskListener() {
+ @Override
+ public void successful() {
+ new File(videoFilePath).delete();
+
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(true));
+
+ stopService();
+ }
+
+ @Override
+ public void failed() {
+ new File(videoFilePath).delete();
+
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ }).execute();
+ } else {
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ }
+ } else {
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ });
+ } else {
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
+ EventBus.getDefault().post(new DownloadRedditVideoEvent(false));
+
+ stopService();
+ }
+ });
+
+ return START_NOT_STICKY;
+ }
+
+ private Notification createNotification(int stringResId) {
+ return new NotificationCompat.Builder(this, NotificationUtils.CHANNEL_ID_DOWNLOAD_REDDIT_VIDEO)
+ .setContentTitle(getString(stringResId))
+ .setContentText(getString(R.string.please_wait))
+ .setSmallIcon(R.drawable.ic_notification)
+ .setColor(mCustomThemeWrapper.getColorPrimaryLightTheme())
+ .build();
+ }
+
+ private String writeResponseBodyToDisk(ResponseBody body, String filePath) {
+ try {
+ File file = new File(filePath);
+
+ InputStream inputStream = null;
+ OutputStream outputStream = null;
+
+ try {
+ byte[] fileReader = new byte[4096];
+
+ long fileSize = body.contentLength();
+ long fileSizeDownloaded = 0;
+
+ inputStream = body.byteStream();
+ outputStream = new FileOutputStream(file);
+
+ while (true) {
+ int read = inputStream.read(fileReader);
+
+ if (read == -1) {
+ break;
+ }
+
+ outputStream.write(fileReader, 0, read);
+
+ fileSizeDownloaded += read;
+
+ Log.i("asdfsadf", "file download: " + fileSizeDownloaded + " of " + fileSize);
+ }
+
+ outputStream.flush();
+
+ return file.getPath();
+ } catch (IOException e) {
+ return null;
+ } finally {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ }
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ private boolean muxVideoAndAudio(String videoFilePath, String audioFilePath, String outputFilePath) {
+ try {
+ File file = new File(outputFilePath);
+ file.createNewFile();
+ MediaExtractor videoExtractor = new MediaExtractor();
+ videoExtractor.setDataSource(videoFilePath);
+ MediaExtractor audioExtractor = new MediaExtractor();
+ audioExtractor.setDataSource(audioFilePath);
+ MediaMuxer muxer = new MediaMuxer(outputFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+
+ videoExtractor.selectTrack(0);
+ MediaFormat videoFormat = videoExtractor.getTrackFormat(0);
+ int videoTrack = muxer.addTrack(videoFormat);
+
+ audioExtractor.selectTrack(0);
+ MediaFormat audioFormat = audioExtractor.getTrackFormat(0);
+ int audioTrack = muxer.addTrack(audioFormat);
+ boolean sawEOS = false;
+ int offset = 100;
+ int sampleSize = 256 * 1024;
+ ByteBuffer videoBuf = ByteBuffer.allocate(sampleSize);
+ ByteBuffer audioBuf = ByteBuffer.allocate(sampleSize);
+ MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
+ MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();
+
+ videoExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ audioExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+
+ muxer.start();
+
+ while (!sawEOS)
+ {
+ videoBufferInfo.offset = offset;
+ videoBufferInfo.size = videoExtractor.readSampleData(videoBuf, offset);
+
+
+ if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0)
+ {
+ // Log.d(TAG, "saw input EOS.");
+ sawEOS = true;
+ videoBufferInfo.size = 0;
+ } else {
+ videoBufferInfo.presentationTimeUs = videoExtractor.getSampleTime();
+ videoBufferInfo.flags = videoExtractor.getSampleFlags();
+ muxer.writeSampleData(videoTrack, videoBuf, videoBufferInfo);
+ videoExtractor.advance();
+ }
+ }
+
+ boolean sawEOS2 = false;
+ while (!sawEOS2)
+ {
+ audioBufferInfo.offset = offset;
+ audioBufferInfo.size = audioExtractor.readSampleData(audioBuf, offset);
+
+ if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0) {
+ sawEOS2 = true;
+ audioBufferInfo.size = 0;
+ } else {
+ audioBufferInfo.presentationTimeUs = audioExtractor.getSampleTime();
+ audioBufferInfo.flags = audioExtractor.getSampleFlags();
+ muxer.writeSampleData(audioTrack, audioBuf, audioBufferInfo);
+ audioExtractor.advance();
+
+ }
+ }
+
+ muxer.stop();
+ muxer.release();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+ private void stopService() {
+ stopForeground(true);
+ stopSelf();
+ }
+
+ private static class CopyFileAsyncTask extends AsyncTask<Void, Void, Void> {
+ private File src;
+ private String destinationFileName;
+ private ContentResolver contentResolver;
+ private CopyFileAsyncTaskListener copyFileAsyncTaskListener;
+ private boolean successful;
+
+ interface CopyFileAsyncTaskListener {
+ void successful();
+ void failed();
+ }
+
+ CopyFileAsyncTask(File src, String destinationFileName, ContentResolver contentResolver, CopyFileAsyncTaskListener copyFileAsyncTaskListener) {
+ this.src = src;
+ this.destinationFileName = destinationFileName;
+ this.contentResolver = contentResolver;
+ this.copyFileAsyncTaskListener = copyFileAsyncTaskListener;
+ }
+
+ @Override
+ protected Void doInBackground(Void... voids) {
+ if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ successful = copy(src, destinationFileName);
+ } else {
+ try {
+ copyFileQ(src, destinationFileName);
+ successful = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ successful = false;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ super.onPostExecute(aVoid);
+ if (successful) {
+ copyFileAsyncTaskListener.successful();
+ } else {
+ copyFileAsyncTaskListener.failed();
+ }
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.Q)
+ private void copyFileQ(File src, String outputFileName) throws IOException {
+ String relativeLocation = Environment.DIRECTORY_MOVIES + "/Infinity/";
+
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, outputFileName);
+ contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);
+ contentValues.put(MediaStore.Video.Media.IS_PENDING, 1);
+
+ OutputStream stream = null;
+ Uri uri = null;
+
+ try {
+ final Uri contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+ uri = contentResolver.insert(contentUri, contentValues);
+
+ if (uri == null) {
+ throw new IOException("Failed to create new MediaStore record.");
+ }
+
+ stream = contentResolver.openOutputStream(uri);
+
+ if (stream == null) {
+ throw new IOException("Failed to get output stream.");
+ }
+
+ InputStream in = new FileInputStream(src);
+
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ stream.write(buf, 0, len);
+ }
+
+ contentValues.clear();
+ contentValues.put(MediaStore.Images.Media.IS_PENDING, 0);
+ contentResolver.update(uri, contentValues, null, null);
+ } catch (IOException e) {
+ if (uri != null) {
+ // Don't leave an orphan entry in the MediaStore
+ contentResolver.delete(uri, null, null);
+ }
+
+ throw e;
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ private boolean copy(File src, String outputFileName) {
+ File directory = getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
+ if (directory != null) {
+ String directoryPath = directory.getAbsolutePath() + "/Infinity/";;
+ File dst = new File(directoryPath, outputFileName);
+
+ try (InputStream in = new FileInputStream(src)) {
+ try (OutputStream out = new FileOutputStream(dst)) {
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+
+ src.delete();
+ return true;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ src.delete();
+ return false;
+ }
+ } else {
+ src.delete();
+ return false;
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java
index cedf9730..5177e415 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Service/SubmitPostService.java
@@ -4,7 +4,6 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
-import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
@@ -110,22 +109,22 @@ public class SubmitPostService extends Service {
if (postType == EXTRA_POST_TEXT_OR_LINK) {
content = intent.getStringExtra(EXTRA_CONTENT);
kind = intent.getStringExtra(EXTRA_KIND);
- startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(this, R.string.posting));
+ startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(R.string.posting));
submitTextOrLinkPost();
} else if (postType == EXTRA_POST_TYPE_IMAGE) {
mediaUri = intent.getData();
- startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(this, R.string.posting_image));
+ startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(R.string.posting_image));
submitImagePost();
} else {
mediaUri = intent.getData();
- startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(this, R.string.posting_video));
+ startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(R.string.posting_video));
submitVideoPost();
}
return START_NOT_STICKY;
}
- private Notification createNotification(Context context, int stringResId) {
+ private Notification createNotification(int stringResId) {
return new NotificationCompat.Builder(this, NotificationUtils.CHANNEL_SUBMIT_POST)
.setContentTitle(getString(stringResId))
.setContentText(getString(R.string.please_wait))