From 664141b3240808597929901d52123c75c0b35427 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Mon, 21 Dec 2020 23:27:10 +0800 Subject: Rewrite DownloadMediaService to run in a background thread. --- .../activities/CustomizePostFilterActivity.java | 4 + .../infinityforreddit/fragments/PostFragment.java | 38 +- .../infinityforreddit/post/PostDataSource.java | 14 +- .../post/PostDataSourceFactory.java | 25 +- .../infinityforreddit/post/PostViewModel.java | 63 ++- .../services/DownloadMediaService.java | 502 +++++++++++---------- 6 files changed, 323 insertions(+), 323 deletions(-) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java index c9e34f61..99c67f43 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java @@ -172,6 +172,10 @@ public class CustomizePostFilterActivity extends BaseActivity { postTypeVideoLinearLayout.setOnClickListener(view -> { postTypeVideoCheckBox.performClick(); }); + + postTypeGalleryLinearLayout.setOnClickListener(view -> { + postTypeGalleryCheckBox.performClick(); + }); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java index bad67e8e..c13de414 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/PostFragment.java @@ -693,7 +693,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { if (accountName != null && !accountName.equals("")) { if (readPosts == null) { if (getArguments().getBoolean(EXTRA_DISABLE_READ_POSTS, false)) { - initializeAndBindPostViewModel(accessToken, locale); + initializeAndBindPostViewModel(accessToken); } else { FetchReadPosts.fetchReadPosts(mRedditDataRoomDatabase, accountName, postType == PostDataSource.TYPE_SUBREDDIT && subredditName != null && (subredditName.equals("all") || subredditName.equals("popular")), @@ -701,15 +701,15 @@ public class PostFragment extends Fragment implements FragmentCommunicator { if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { this.readPosts = readPosts; this.subredditFilterList = subredditFilters; - initializeAndBindPostViewModel(accessToken, locale); + initializeAndBindPostViewModel(accessToken); } }); } } else { - initializeAndBindPostViewModel(accessToken, locale); + initializeAndBindPostViewModel(accessToken); } } else { - initializeAndBindPostViewModelForAnonymous(accessToken, locale); + initializeAndBindPostViewModelForAnonymous(accessToken); } vibrateWhenActionTriggered = mSharedPreferences.getBoolean(SharedPreferencesUtils.VIBRATE_WHEN_ACTION_TRIGGERED, true); @@ -821,55 +821,55 @@ public class PostFragment extends Fragment implements FragmentCommunicator { return rootView; } - private void initializeAndBindPostViewModel(String accessToken, Locale locale) { + private void initializeAndBindPostViewModel(String accessToken) { if (postType == PostDataSource.TYPE_SEARCH) { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, query, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } else if (postType == PostDataSource.TYPE_SUBREDDIT) { if (subredditName.equals("all") || subredditName.equals("popular")) { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, readPosts, subredditFilterList)).get(PostViewModel.class); } else { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } } else if (postType == PostDataSource.TYPE_MULTI_REDDIT) { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, multiRedditPath, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } else if (postType == PostDataSource.TYPE_USER) { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, username, postType, sortType, postFilter, where, readPosts)).get(PostViewModel.class); } else { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, postFeedScrolledPositionSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } bindPostViewModel(); } - private void initializeAndBindPostViewModelForAnonymous(String accessToken, Locale locale) { + private void initializeAndBindPostViewModelForAnonymous(String accessToken) { //For anonymous user if (postType == PostDataSource.TYPE_SEARCH) { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, query, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } else if (postType == PostDataSource.TYPE_SUBREDDIT) { if (subredditName.equals("all") || subredditName.equals("popular")) { if (subredditFilterList != null) { mPostViewModel = new ViewModelProvider(this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, readPosts, subredditFilterList)).get(PostViewModel.class); } else { @@ -877,7 +877,7 @@ public class PostFragment extends Fragment implements FragmentCommunicator { if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { subredditFilterList = subredditFilters; mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, readPosts, subredditFilterList)).get(PostViewModel.class); @@ -887,23 +887,23 @@ public class PostFragment extends Fragment implements FragmentCommunicator { } } else { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } } else if (postType == PostDataSource.TYPE_MULTI_REDDIT) { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, multiRedditPath, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } else if (postType == PostDataSource.TYPE_USER) { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(accessToken == null ? mRetrofit : mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, username, postType, sortType, postFilter, where, readPosts)).get(PostViewModel.class); } else { mPostViewModel = new ViewModelProvider(PostFragment.this, new PostViewModel.Factory(mOauthRetrofit, accessToken, - accountName, locale, mSharedPreferences, postFeedScrolledPositionSharedPreferences, + accountName, mSharedPreferences, postFeedScrolledPositionSharedPreferences, postType, sortType, postFilter, readPosts)).get(PostViewModel.class); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSource.java index 1f6f5671..fc7d1583 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSource.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSource.java @@ -9,7 +9,6 @@ import androidx.paging.PageKeyedDataSource; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import java.util.Locale; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.PostFilter; @@ -41,7 +40,6 @@ public class PostDataSource extends PageKeyedDataSource { private Retrofit retrofit; private String accessToken; private String accountName; - private Locale locale; private SharedPreferences sharedPreferences; private SharedPreferences postFeedScrolledPositionSharedPreferences; private String subredditOrUserName; @@ -62,14 +60,13 @@ public class PostDataSource extends PageKeyedDataSource { private LoadParams params; private LoadCallback callback; - PostDataSource(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSource(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, int postType, SortType sortType, PostFilter postFilter, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; paginationNetworkStateLiveData = new MutableLiveData<>(); @@ -82,14 +79,13 @@ public class PostDataSource extends PageKeyedDataSource { postLinkedHashSet = new LinkedHashSet<>(); } - PostDataSource(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSource(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String path, int postType, SortType sortType, PostFilter postFilter, List readPostList, List subredditFilterList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; if (postType == TYPE_SUBREDDIT) { @@ -124,14 +120,13 @@ public class PostDataSource extends PageKeyedDataSource { postLinkedHashSet = new LinkedHashSet<>(); } - PostDataSource(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSource(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditOrUserName, int postType, SortType sortType, PostFilter postFilter, String where, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditOrUserName = subredditOrUserName; @@ -146,14 +141,13 @@ public class PostDataSource extends PageKeyedDataSource { postLinkedHashSet = new LinkedHashSet<>(); } - PostDataSource(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSource(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditOrUserName, String query, int postType, SortType sortType, PostFilter postFilter, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditOrUserName = subredditOrUserName; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSourceFactory.java index c31619af..2d0e6d19 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSourceFactory.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostDataSourceFactory.java @@ -1,13 +1,13 @@ package ml.docilealligator.infinityforreddit.post; import android.content.SharedPreferences; +import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.MutableLiveData; import androidx.paging.DataSource; import java.util.List; -import java.util.Locale; import ml.docilealligator.infinityforreddit.PostFilter; import ml.docilealligator.infinityforreddit.SortType; @@ -19,7 +19,6 @@ class PostDataSourceFactory extends DataSource.Factory { private Retrofit retrofit; private String accessToken; private String accountName; - private Locale locale; private SharedPreferences sharedPreferences; private SharedPreferences postFeedScrolledPositionSharedPreferences; private String subredditName; @@ -34,14 +33,13 @@ class PostDataSourceFactory extends DataSource.Factory { private PostDataSource postDataSource; private MutableLiveData postDataSourceLiveData; - PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, int postType, SortType sortType, PostFilter postFilter, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; postDataSourceLiveData = new MutableLiveData<>(); @@ -51,14 +49,13 @@ class PostDataSourceFactory extends DataSource.Factory { this.readPostList = readPostList; } - PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditName, int postType, SortType sortType, PostFilter postFilter, List readPostList, List subredditFilterList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditName = subredditName; @@ -70,14 +67,13 @@ class PostDataSourceFactory extends DataSource.Factory { this.subredditFilterList = subredditFilterList; } - PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditName, int postType, SortType sortType, PostFilter postFilter, String where, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditName = subredditName; @@ -89,14 +85,13 @@ class PostDataSourceFactory extends DataSource.Factory { this.readPostList = readPostList; } - PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + PostDataSourceFactory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditName, String query, int postType, SortType sortType, PostFilter postFilter, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditName = subredditName; @@ -112,19 +107,20 @@ class PostDataSourceFactory extends DataSource.Factory { @Override public DataSource create() { if (postType == PostDataSource.TYPE_FRONT_PAGE) { - postDataSource = new PostDataSource(retrofit, accessToken, accountName, locale, + postDataSource = new PostDataSource(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, postType, sortType, postFilter, readPostList); } else if (postType == PostDataSource.TYPE_SEARCH) { - postDataSource = new PostDataSource(retrofit, accessToken, accountName, locale, + postDataSource = new PostDataSource(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, query, postType, sortType, postFilter, readPostList); } else if (postType == PostDataSource.TYPE_SUBREDDIT || postType == PostDataSource.TYPE_MULTI_REDDIT) { - postDataSource = new PostDataSource(retrofit, accessToken, accountName, locale, + Log.i("asdasfd", "s5 " + (postFilter == null)); + postDataSource = new PostDataSource(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, readPostList, subredditFilterList); } else { - postDataSource = new PostDataSource(retrofit, accessToken, accountName, locale, + postDataSource = new PostDataSource(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, userWhere, readPostList); } @@ -142,6 +138,7 @@ class PostDataSourceFactory extends DataSource.Factory { } void changeSortTypeAndPostFilter(SortType sortType, PostFilter postFilter) { + Log.i("asdasfd", "s6 " + (postFilter == null)); this.sortType = sortType; this.postFilter = postFilter; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostViewModel.java index 189f0264..716eabaf 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/PostViewModel.java @@ -14,7 +14,6 @@ import androidx.paging.LivePagedListBuilder; import androidx.paging.PagedList; import java.util.List; -import java.util.Locale; import ml.docilealligator.infinityforreddit.NetworkState; import ml.docilealligator.infinityforreddit.PostFilter; @@ -31,12 +30,12 @@ public class PostViewModel extends ViewModel { private LiveData> posts; private MutableLiveData sortTypeLiveData; private MutableLiveData postFilterLiveData; - private NSFWAndSortTypeLiveData nsfwAndSortTypeLiveData; + private SortTypeAndPostFilterLiveData sortTypeAndPostFilterLiveData; - public PostViewModel(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public PostViewModel(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences cache, int postType, SortType sortType, PostFilter postFilter, List readPostList) { - postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, locale, + postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, sharedPreferences, cache, postType, sortType, postFilter, readPostList); initialLoadingState = Transformations.switchMap(postDataSourceFactory.getPostDataSourceLiveData(), @@ -51,7 +50,7 @@ public class PostViewModel extends ViewModel { postFilterLiveData = new MutableLiveData<>(); postFilterLiveData.postValue(postFilter); - nsfwAndSortTypeLiveData = new NSFWAndSortTypeLiveData(sortTypeLiveData, postFilterLiveData); + sortTypeAndPostFilterLiveData = new SortTypeAndPostFilterLiveData(sortTypeLiveData, postFilterLiveData); PagedList.Config pagedListConfig = (new PagedList.Config.Builder()) @@ -59,18 +58,18 @@ public class PostViewModel extends ViewModel { .setPageSize(25) .build(); - posts = Transformations.switchMap(nsfwAndSortTypeLiveData, nsfwAndSort -> { + posts = Transformations.switchMap(sortTypeAndPostFilterLiveData, sortAndPostFilter -> { postDataSourceFactory.changeSortTypeAndPostFilter( sortTypeLiveData.getValue(), postFilterLiveData.getValue()); return (new LivePagedListBuilder(postDataSourceFactory, pagedListConfig)).build(); }); } - public PostViewModel(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public PostViewModel(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences cache, String subredditName, int postType, SortType sortType, PostFilter postFilter, List readPostList, List subredditFilterList) { - postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, locale, + postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, sharedPreferences, cache, subredditName, postType, sortType, postFilter, readPostList, subredditFilterList); @@ -86,7 +85,7 @@ public class PostViewModel extends ViewModel { postFilterLiveData = new MutableLiveData<>(); postFilterLiveData.postValue(postFilter); - nsfwAndSortTypeLiveData = new NSFWAndSortTypeLiveData(sortTypeLiveData, postFilterLiveData); + sortTypeAndPostFilterLiveData = new SortTypeAndPostFilterLiveData(sortTypeLiveData, postFilterLiveData); PagedList.Config pagedListConfig = (new PagedList.Config.Builder()) @@ -94,18 +93,18 @@ public class PostViewModel extends ViewModel { .setPageSize(25) .build(); - posts = Transformations.switchMap(nsfwAndSortTypeLiveData, nsfwAndSort -> { + posts = Transformations.switchMap(sortTypeAndPostFilterLiveData, sortAndPostFilter -> { postDataSourceFactory.changeSortTypeAndPostFilter( sortTypeLiveData.getValue(), postFilterLiveData.getValue()); return (new LivePagedListBuilder(postDataSourceFactory, pagedListConfig)).build(); }); } - public PostViewModel(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public PostViewModel(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences cache, String subredditName, int postType, SortType sortType, PostFilter postFilter, String where, List readPostList) { - postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, locale, + postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, sharedPreferences, cache, subredditName, postType, sortType, postFilter, where, readPostList); initialLoadingState = Transformations.switchMap(postDataSourceFactory.getPostDataSourceLiveData(), @@ -120,7 +119,7 @@ public class PostViewModel extends ViewModel { postFilterLiveData = new MutableLiveData<>(); postFilterLiveData.postValue(postFilter); - nsfwAndSortTypeLiveData = new NSFWAndSortTypeLiveData(sortTypeLiveData, postFilterLiveData); + sortTypeAndPostFilterLiveData = new SortTypeAndPostFilterLiveData(sortTypeLiveData, postFilterLiveData); PagedList.Config pagedListConfig = (new PagedList.Config.Builder()) @@ -128,17 +127,17 @@ public class PostViewModel extends ViewModel { .setPageSize(25) .build(); - posts = Transformations.switchMap(nsfwAndSortTypeLiveData, nsfwAndSort -> { + posts = Transformations.switchMap(sortTypeAndPostFilterLiveData, sortAndPostFilter -> { postDataSourceFactory.changeSortTypeAndPostFilter( sortTypeLiveData.getValue(), postFilterLiveData.getValue()); return (new LivePagedListBuilder(postDataSourceFactory, pagedListConfig)).build(); }); } - public PostViewModel(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public PostViewModel(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences cache, String subredditName, String query, int postType, SortType sortType, PostFilter postFilter, List readPostList) { - postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, locale, + postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, accountName, sharedPreferences, cache, subredditName, query, postType, sortType, postFilter, readPostList); @@ -154,7 +153,7 @@ public class PostViewModel extends ViewModel { postFilterLiveData = new MutableLiveData<>(); postFilterLiveData.postValue(postFilter); - nsfwAndSortTypeLiveData = new NSFWAndSortTypeLiveData(sortTypeLiveData, postFilterLiveData); + sortTypeAndPostFilterLiveData = new SortTypeAndPostFilterLiveData(sortTypeLiveData, postFilterLiveData); PagedList.Config pagedListConfig = (new PagedList.Config.Builder()) @@ -162,7 +161,7 @@ public class PostViewModel extends ViewModel { .setPageSize(25) .build(); - posts = Transformations.switchMap(nsfwAndSortTypeLiveData, nsfwAndSort -> { + posts = Transformations.switchMap(sortTypeAndPostFilterLiveData, sortAndPostFilter -> { postDataSourceFactory.changeSortTypeAndPostFilter(sortTypeLiveData.getValue(), postFilterLiveData.getValue()); return (new LivePagedListBuilder(postDataSourceFactory, pagedListConfig)).build(); @@ -205,7 +204,6 @@ public class PostViewModel extends ViewModel { private Retrofit retrofit; private String accessToken; private String accountName; - private Locale locale; private SharedPreferences sharedPreferences; private SharedPreferences postFeedScrolledPositionSharedPreferences; private String subredditName; @@ -217,13 +215,12 @@ public class PostViewModel extends ViewModel { private List readPostList; private List subredditFilterList; - public Factory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public Factory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, int postType, SortType sortType, PostFilter postFilter, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.postType = postType; @@ -232,14 +229,13 @@ public class PostViewModel extends ViewModel { this.readPostList = readPostList; } - public Factory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public Factory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditName, int postType, SortType sortType, PostFilter postFilter, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditName = subredditName; @@ -250,7 +246,7 @@ public class PostViewModel extends ViewModel { } //With subreddit filter - public Factory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public Factory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditName, int postType, SortType sortType, PostFilter postFilter, @@ -258,7 +254,6 @@ public class PostViewModel extends ViewModel { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditName = subredditName; @@ -270,13 +265,12 @@ public class PostViewModel extends ViewModel { } //User posts - public Factory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public Factory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditName, int postType, SortType sortType, PostFilter postFilter, String where, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditName = subredditName; @@ -287,13 +281,12 @@ public class PostViewModel extends ViewModel { this.readPostList = readPostList; } - public Factory(Retrofit retrofit, String accessToken, String accountName, Locale locale, + public Factory(Retrofit retrofit, String accessToken, String accountName, SharedPreferences sharedPreferences, SharedPreferences postFeedScrolledPositionSharedPreferences, String subredditName, String query, int postType, SortType sortType, PostFilter postFilter, List readPostList) { this.retrofit = retrofit; this.accessToken = accessToken; this.accountName = accountName; - this.locale = locale; this.sharedPreferences = sharedPreferences; this.postFeedScrolledPositionSharedPreferences = postFeedScrolledPositionSharedPreferences; this.subredditName = subredditName; @@ -308,26 +301,26 @@ public class PostViewModel extends ViewModel { @Override public T create(@NonNull Class modelClass) { if (postType == PostDataSource.TYPE_FRONT_PAGE) { - return (T) new PostViewModel(retrofit, accessToken, accountName, locale, sharedPreferences, + return (T) new PostViewModel(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, postType, sortType, postFilter, readPostList); } else if (postType == PostDataSource.TYPE_SEARCH) { - return (T) new PostViewModel(retrofit, accessToken, accountName, locale, sharedPreferences, + return (T) new PostViewModel(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, query, postType, sortType, postFilter, readPostList); } else if (postType == PostDataSource.TYPE_SUBREDDIT || postType == PostDataSource.TYPE_MULTI_REDDIT) { - return (T) new PostViewModel(retrofit, accessToken, accountName, locale, sharedPreferences, + return (T) new PostViewModel(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, readPostList, subredditFilterList); } else { - return (T) new PostViewModel(retrofit, accessToken, accountName, locale, sharedPreferences, + return (T) new PostViewModel(retrofit, accessToken, accountName, sharedPreferences, postFeedScrolledPositionSharedPreferences, subredditName, postType, sortType, postFilter, userWhere, readPostList); } } } - private static class NSFWAndSortTypeLiveData extends MediatorLiveData> { - public NSFWAndSortTypeLiveData(LiveData sortTypeLiveData, LiveData postFilterLiveData) { + private static class SortTypeAndPostFilterLiveData extends MediatorLiveData> { + public SortTypeAndPostFilterLiveData(LiveData sortTypeLiveData, LiveData postFilterLiveData) { addSource(sortTypeLiveData, sortType -> setValue(Pair.create(postFilterLiveData.getValue(), sortType))); addSource(postFilterLiveData, postFilter -> setValue(Pair.create(postFilter, sortTypeLiveData.getValue()))); } 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 b369a6ae..2d5f641b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java @@ -11,13 +11,17 @@ import android.content.Intent; import android.content.SharedPreferences; import android.media.MediaScannerConnection; import android.net.Uri; -import android.os.AsyncTask; 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.provider.MediaStore; -import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.documentfile.provider.DocumentFile; @@ -29,6 +33,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Random; import javax.inject.Inject; import javax.inject.Named; @@ -43,8 +48,6 @@ import ml.docilealligator.infinityforreddit.utils.NotificationUtils; import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils; import okhttp3.OkHttpClient; import okhttp3.ResponseBody; -import retrofit2.Call; -import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; @@ -71,11 +74,9 @@ public class DownloadMediaService extends Service { SharedPreferences mSharedPreferences; @Inject CustomThemeWrapper mCustomThemeWrapper; - private int mediaType; - private String mimeType; private NotificationManagerCompat notificationManager; private NotificationCompat.Builder builder; - private boolean downloadFinished; + private ServiceHandler serviceHandler; public DownloadMediaService() { } @@ -85,131 +86,61 @@ public class DownloadMediaService extends Service { return null; } - private String getNotificationChannelId() { - switch (mediaType) { - case EXTRA_MEDIA_TYPE_GIF: - return NotificationUtils.CHANNEL_ID_DOWNLOAD_GIF; - case EXTRA_MEDIA_TYPE_VIDEO: - return NotificationUtils.CHANNEL_ID_DOWNLOAD_VIDEO; - default: - return NotificationUtils.CHANNEL_ID_DOWNLOAD_IMAGE; - } - } - - private String getNotificationChannel() { - switch (mediaType) { - case EXTRA_MEDIA_TYPE_GIF: - return NotificationUtils.CHANNEL_DOWNLOAD_GIF; - case EXTRA_MEDIA_TYPE_VIDEO: - return NotificationUtils.CHANNEL_DOWNLOAD_VIDEO; - default: - return NotificationUtils.CHANNEL_DOWNLOAD_IMAGE; - } - } - - private int getNotificationId() { - switch (mediaType) { - case EXTRA_MEDIA_TYPE_GIF: - return NotificationUtils.DOWNLOAD_GIF_NOTIFICATION_ID; - case EXTRA_MEDIA_TYPE_VIDEO: - return NotificationUtils.DOWNLOAD_VIDEO_NOTIFICATION_ID; - default: - return NotificationUtils.DOWNLOAD_IMAGE_NOTIFICATION_ID; - } - } - - private String getDownloadLocation() { - switch (mediaType) { - case EXTRA_MEDIA_TYPE_GIF: - return mSharedPreferences.getString(SharedPreferencesUtils.GIF_DOWNLOAD_LOCATION, ""); - case EXTRA_MEDIA_TYPE_VIDEO: - return mSharedPreferences.getString(SharedPreferencesUtils.VIDEO_DOWNLOAD_LOCATION, ""); - default: - return mSharedPreferences.getString(SharedPreferencesUtils.IMAGE_DOWNLOAD_LOCATION, ""); - } - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - ((Infinity) getApplication()).getAppComponent().inject(this); - - 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/*"; - - notificationManager = NotificationManagerCompat.from(this); - builder = new NotificationCompat.Builder(this, getNotificationChannelId()); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationChannel serviceChannel; - serviceChannel = new NotificationChannel( - getNotificationChannelId(), - getNotificationChannel(), - NotificationManager.IMPORTANCE_LOW - ); + // Handler that receives messages from the thread + private final class ServiceHandler extends Handler { + private boolean downloadFinished; - notificationManager.createNotificationChannel(serviceChannel); - } - - switch (mediaType) { - case EXTRA_MEDIA_TYPE_GIF: - startForeground( - NotificationUtils.DOWNLOAD_GIF_NOTIFICATION_ID, - createNotification(fileName[0]) - ); - break; - case EXTRA_MEDIA_TYPE_VIDEO: - startForeground( - NotificationUtils.DOWNLOAD_VIDEO_NOTIFICATION_ID, - createNotification(fileName[0]) - ); - break; - default: - startForeground( - NotificationUtils.DOWNLOAD_IMAGE_NOTIFICATION_ID, - createNotification(fileName[0]) - ); + public ServiceHandler(Looper looper) { + super(looper); } - - final DownloadProgressResponseBody.ProgressListener progressListener = new DownloadProgressResponseBody.ProgressListener() { - long time = 0; - - @Override public void update(long bytesRead, long contentLength, boolean done) { - if (!done) { - if (contentLength != -1) { - long currentTime = System.currentTimeMillis(); - if (currentTime - time > 1000) { - time = currentTime; - updateNotification(0, (int) ((100 * bytesRead) / contentLength), null); + @Override + public void handleMessage(Message msg) { + int randomNotificationIdOffset = msg.arg1; + Bundle intent = msg.getData(); + downloadFinished = false; + String fileUrl = intent.getString(EXTRA_URL); + final 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); + String mimeType = mediaType == EXTRA_MEDIA_TYPE_VIDEO ? "video/*" : "image/*"; + + final DownloadProgressResponseBody.ProgressListener progressListener = new DownloadProgressResponseBody.ProgressListener() { + long time = 0; + + @Override public void update(long bytesRead, long contentLength, boolean done) { + if (!done) { + if (contentLength != -1) { + long currentTime = System.currentTimeMillis(); + if (currentTime - time > 1000) { + time = currentTime; + updateNotification(mediaType, 0, + (int) ((100 * bytesRead) / contentLength), randomNotificationIdOffset, 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(); + 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(); - boolean separateDownloadFolder = mSharedPreferences.getBoolean(SharedPreferencesUtils.SEPARATE_FOLDER_FOR_EACH_SUBREDDIT, false); + retrofit = retrofit.newBuilder().client(client).build(); - retrofit.create(DownloadFile.class).downloadFile(fileUrl).enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { + boolean separateDownloadFolder = mSharedPreferences.getBoolean(SharedPreferencesUtils.SEPARATE_FOLDER_FOR_EACH_SUBREDDIT, false); + + Response response = null; + String destinationFileUriString = null; + boolean isDefaultDestination = true; + try { + response = retrofit.create(DownloadFile.class).downloadFile(fileUrl).execute(); if (response.isSuccessful() && response.body() != null) { - String destinationFileDirectory = getDownloadLocation(); - String destinationFileUriString; - boolean isDefaultDestination; + String destinationFileDirectory = getDownloadLocation(mediaType); if (destinationFileDirectory.equals("")) { if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { File directory = getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); @@ -217,12 +148,14 @@ 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, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); + downloadFinished(mediaType, randomNotificationIdOffset, mimeType, + null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); return; } destinationFileUriString = directoryPath + fileName[0]; } else { - downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); + downloadFinished(mediaType, randomNotificationIdOffset, mimeType, + null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); return; } } else { @@ -237,21 +170,24 @@ public class DownloadMediaService extends Service { if (separateDownloadFolder && subredditName != null && !subredditName.equals("")) { dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory)); if (dir == null) { - downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); + downloadFinished(mediaType, randomNotificationIdOffset, mimeType, + 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, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); + downloadFinished(mediaType, randomNotificationIdOffset, mimeType, + null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); return; } } } else { dir = DocumentFile.fromTreeUri(DownloadMediaService.this, Uri.parse(destinationFileDirectory)); if (dir == null) { - downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); + downloadFinished(mediaType, randomNotificationIdOffset, mimeType, + null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); return; } } @@ -266,135 +202,38 @@ public class DownloadMediaService extends Service { } picFile = dir.createFile(mimeType, fileName[0]); if (picFile == null) { - downloadFinished(null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); + downloadFinished(mediaType, randomNotificationIdOffset, mimeType, + null, ERROR_CANNOT_GET_DESTINATION_DIRECTORY); return; } destinationFileUriString = picFile.getUri().toString(); } - - new SaveImageOrGifAndCopyToExternalStorageAsyncTask(response.body(), mediaType, - isDefaultDestination, fileName[0], destinationFileUriString, getContentResolver(), - (destinationFileUri, errorCode) -> downloadFinished(destinationFileUri, errorCode)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + downloadFinished(mediaType, randomNotificationIdOffset, mimeType, null, + ERROR_FILE_CANNOT_DOWNLOAD); } + } catch (IOException e) { + e.printStackTrace(); } - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) { - downloadFinished(null, ERROR_FILE_CANNOT_DOWNLOAD); - } - }); - - return START_NOT_STICKY; - } - - 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 contentStringResId, int progress, PendingIntent pendingIntent) { - if (notificationManager != null) { - 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, 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, -1, null); - break; - case ERROR_FILE_CANNOT_DOWNLOAD: - 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, -1, null); - break; - } - EventBus.getDefault().post(new DownloadMediaEvent(false)); - } else { - MediaScannerConnection.scanFile( - this, new String[]{destinationFileUri.toString()}, null, - (path, uri) -> { - Intent intent = new Intent(); - intent.setAction(android.content.Intent.ACTION_VIEW); - 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, -1, pendingIntent); - EventBus.getDefault().post(new DownloadMediaEvent(true)); - } - ); - } - stopForeground(false); - } - - private static class SaveImageOrGifAndCopyToExternalStorageAsyncTask extends AsyncTask { - - private ResponseBody response; - private int mediaType; - private boolean isDefaultDestination; - private String destinationFileName; - @NonNull - private String destinationFileUriString; - private ContentResolver contentResolver; - private SaveImageOrGifAndCopyToExternalStorageAsyncTaskListener saveImageOrGifAndCopyToExternalStorageAsyncTaskListener; - private int errorCode = NO_ERROR; - - interface SaveImageOrGifAndCopyToExternalStorageAsyncTaskListener { - void finished(Uri destinationFileUri, int errorCode); - } - - public SaveImageOrGifAndCopyToExternalStorageAsyncTask(ResponseBody response, int mediaType, - boolean isDefaultDestination, - String destinationFileName, - @NonNull String destinationFileUriString, - ContentResolver contentResolver, - SaveImageOrGifAndCopyToExternalStorageAsyncTaskListener saveImageOrGifAndCopyToExternalStorageAsyncTaskListener) { - this.response = response; - this.mediaType = mediaType; - this.isDefaultDestination = isDefaultDestination; - this.destinationFileName = destinationFileName; - this.destinationFileUriString = destinationFileUriString; - this.contentResolver = contentResolver; - this.saveImageOrGifAndCopyToExternalStorageAsyncTaskListener = saveImageOrGifAndCopyToExternalStorageAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { try { - writeResponseBodyToDisk(response); + if (response != null && response.body() != null) { + Uri destinationFileUri = writeResponseBodyToDisk(response.body(), isDefaultDestination, destinationFileUriString, + fileName[0], mediaType); + downloadFinished(mediaType, randomNotificationIdOffset, + mimeType, destinationFileUri, NO_ERROR); + } } catch (IOException e) { - errorCode = ERROR_FILE_CANNOT_SAVE; + e.printStackTrace(); + downloadFinished(mediaType, randomNotificationIdOffset, + mimeType, null, ERROR_FILE_CANNOT_SAVE); } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - saveImageOrGifAndCopyToExternalStorageAsyncTaskListener.finished(Uri.parse(destinationFileUriString), errorCode); } - private void writeResponseBodyToDisk(ResponseBody body) throws IOException { + private Uri writeResponseBodyToDisk(ResponseBody body, boolean isDefaultDestination, + String destinationFileUriString, String destinationFileName, + int mediaType) throws IOException { + ContentResolver contentResolver = getContentResolver(); if (isDefaultDestination) { if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { InputStream inputStream = body.byteStream(); @@ -463,6 +302,179 @@ public class DownloadMediaService extends Service { } } } + 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); + break; + case ERROR_FILE_CANNOT_DOWNLOAD: + updateNotification(mediaType, R.string.downloading_media_failed_cannot_download_media, + -1, randomNotificationIdOffset, null); + break; + case ERROR_FILE_CANNOT_SAVE: + updateNotification(mediaType, R.string.downloading_media_failed_cannot_save_to_destination_directory, + -1, randomNotificationIdOffset, null); + break; + } + EventBus.getDefault().post(new DownloadMediaEvent(false)); + } else { + MediaScannerConnection.scanFile( + DownloadMediaService.this, new String[]{destinationFileUri.toString()}, null, + (path, uri) -> { + Intent intent = new Intent(); + intent.setAction(android.content.Intent.ACTION_VIEW); + intent.setDataAndType(destinationFileUri, mimeType); + intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + PendingIntent pendingIntent = PendingIntent.getActivity(DownloadMediaService.this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + updateNotification(mediaType, R.string.downloading_media_finished, -1, + randomNotificationIdOffset, pendingIntent); + EventBus.getDefault().post(new DownloadMediaEvent(true)); + } + ); + } + stopForeground(false); + } + } + + @Override + public void onCreate() { + super.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)); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel serviceChannel; + serviceChannel = new NotificationChannel( + getNotificationChannelId(mediaType), + getNotificationChannel(mediaType), + NotificationManager.IMPORTANCE_LOW + ); + + 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; + } + + 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 mediaType, int contentStringResId, int progress, int randomNotificationIdOffset, + PendingIntent pendingIntent) { + if (notificationManager != null) { + 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(mediaType, randomNotificationIdOffset), builder.build()); + } + } + + private String getNotificationChannelId(int mediaType) { + switch (mediaType) { + case EXTRA_MEDIA_TYPE_GIF: + return NotificationUtils.CHANNEL_ID_DOWNLOAD_GIF; + case EXTRA_MEDIA_TYPE_VIDEO: + return NotificationUtils.CHANNEL_ID_DOWNLOAD_VIDEO; + default: + return NotificationUtils.CHANNEL_ID_DOWNLOAD_IMAGE; + } + } + + private String getNotificationChannel(int mediaType) { + switch (mediaType) { + case EXTRA_MEDIA_TYPE_GIF: + return NotificationUtils.CHANNEL_DOWNLOAD_GIF; + case EXTRA_MEDIA_TYPE_VIDEO: + return NotificationUtils.CHANNEL_DOWNLOAD_VIDEO; + default: + return NotificationUtils.CHANNEL_DOWNLOAD_IMAGE; + } + } + + private int getNotificationId(int mediaType, int randomNotificationIdOffset) { + switch (mediaType) { + case EXTRA_MEDIA_TYPE_GIF: + return NotificationUtils.DOWNLOAD_GIF_NOTIFICATION_ID + randomNotificationIdOffset; + case EXTRA_MEDIA_TYPE_VIDEO: + return NotificationUtils.DOWNLOAD_VIDEO_NOTIFICATION_ID + randomNotificationIdOffset; + default: + return NotificationUtils.DOWNLOAD_IMAGE_NOTIFICATION_ID + randomNotificationIdOffset; + } + } + + private String getDownloadLocation(int mediaType) { + switch (mediaType) { + case EXTRA_MEDIA_TYPE_GIF: + return mSharedPreferences.getString(SharedPreferencesUtils.GIF_DOWNLOAD_LOCATION, ""); + case EXTRA_MEDIA_TYPE_VIDEO: + return mSharedPreferences.getString(SharedPreferencesUtils.VIDEO_DOWNLOAD_LOCATION, ""); + default: + return mSharedPreferences.getString(SharedPreferencesUtils.IMAGE_DOWNLOAD_LOCATION, ""); } } } -- cgit v1.2.3