diff options
author | Alex Ning <chineseperson5@gmail.com> | 2021-01-26 02:36:38 +0000 |
---|---|---|
committer | Alex Ning <chineseperson5@gmail.com> | 2021-01-26 02:36:38 +0000 |
commit | b6c00df82fbde6d8746eaa78a7e72fb73bfef946 (patch) | |
tree | abb2b6b9c9cb75aebc2a5ca71f86a59d5fa7a734 /app/src/main/java | |
parent | 7ca511d3f18e6bb626db413d5d249da4502ef862 (diff) | |
download | infinity-for-reddit-b6c00df82fbde6d8746eaa78a7e72fb73bfef946.tar infinity-for-reddit-b6c00df82fbde6d8746eaa78a7e72fb73bfef946.tar.gz infinity-for-reddit-b6c00df82fbde6d8746eaa78a7e72fb73bfef946.tar.bz2 infinity-for-reddit-b6c00df82fbde6d8746eaa78a7e72fb73bfef946.tar.lz infinity-for-reddit-b6c00df82fbde6d8746eaa78a7e72fb73bfef946.tar.xz infinity-for-reddit-b6c00df82fbde6d8746eaa78a7e72fb73bfef946.tar.zst infinity-for-reddit-b6c00df82fbde6d8746eaa78a7e72fb73bfef946.zip |
Rewrite SubmitPostService to run the service in a background thread.
Diffstat (limited to 'app/src/main/java')
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java | 442 | ||||
-rw-r--r-- | app/src/main/java/ml/docilealligator/infinityforreddit/services/SubmitPostService.java | 327 |
2 files changed, 281 insertions, 488 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java index 14216298..c31da124 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/SubmitPost.java @@ -1,9 +1,7 @@ package ml.docilealligator.infinityforreddit.post; import android.graphics.Bitmap; -import android.os.AsyncTask; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.json.JSONArray; @@ -21,15 +19,14 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import ml.docilealligator.infinityforreddit.apis.RedditAPI; import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.apis.RedditAPI; import ml.docilealligator.infinityforreddit.utils.APIUtils; import ml.docilealligator.infinityforreddit.utils.JSONUtils; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.RequestBody; import retrofit2.Call; -import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; @@ -38,33 +35,31 @@ public class SubmitPost { Locale locale, String subredditName, String title, String content, Flair flair, boolean isSpoiler, boolean isNSFW, String kind, SubmitPostListener submitPostListener) { - submitPost(oauthRetrofit, accessToken, locale, subredditName, title, content, + submitPost(oauthRetrofit, accessToken, subredditName, title, content, flair, isSpoiler, isNSFW, kind, null, submitPostListener); } public static void submitImagePost(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, - String accessToken, Locale locale, - String subredditName, String title, Bitmap image, Flair flair, - boolean isSpoiler, boolean isNSFW, SubmitPostListener submitPostListener) { - uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, image, - new UploadImageListener() { - @Override - public void uploaded(String imageUrl) { - submitPost(oauthRetrofit, accessToken, locale, - subredditName, title, imageUrl, flair, isSpoiler, isNSFW, - APIUtils.KIND_IMAGE, null, submitPostListener); - } - - @Override - public void uploadFailed(@Nullable String errorMessage) { - submitPostListener.submitFailed(errorMessage); - } - }); + String accessToken, String subredditName, String title, Bitmap image, + Flair flair, boolean isSpoiler, boolean isNSFW, SubmitPostListener submitPostListener) { + try { + String imageUrlOrError = uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, image); + if (imageUrlOrError != null && !imageUrlOrError.startsWith("Error: ")) { + submitPost(oauthRetrofit, accessToken, + subredditName, title, imageUrlOrError, flair, isSpoiler, isNSFW, + APIUtils.KIND_IMAGE, null, submitPostListener); + } else { + submitPostListener.submitFailed(imageUrlOrError); + } + } catch (IOException | JSONException | XmlPullParserException e) { + e.printStackTrace(); + submitPostListener.submitFailed(e.getMessage()); + } } public static void submitVideoPost(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, Retrofit uploadVideoRetrofit, String accessToken, - Locale locale, String subredditName, String title, File buffer, String mimeType, + String subredditName, String title, File buffer, String mimeType, Bitmap posterBitmap, Flair flair, boolean isSpoiler, boolean isNSFW, SubmitPostListener submitPostListener) { RedditAPI api = oauthRetrofit.create(RedditAPI.class); @@ -76,97 +71,64 @@ public class SubmitPost { uploadImageParams.put(APIUtils.MIMETYPE_KEY, mimeType); Call<String> uploadImageCall = api.uploadImage(APIUtils.getOAuthHeader(accessToken), uploadImageParams); - uploadImageCall.enqueue(new Callback<String>() { - @Override - public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { - if (response.isSuccessful()) { - new ParseJSONResponseFromAWSAsyncTask(response.body(), new ParseJSONResponseFromAWSAsyncTask.ParseJSONResponseFromAWSListener() { - @Override - public void parseSuccessful(Map<String, RequestBody> nameValuePairsMap) { - RequestBody fileBody = RequestBody.create(buffer, MediaType.parse("application/octet-stream")); - MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_video." + fileType, fileBody); - - RedditAPI uploadVideoToAWSApi; - if (fileType.equals("gif")) { - uploadVideoToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); - } else { - uploadVideoToAWSApi = uploadVideoRetrofit.create(RedditAPI.class); - } - Call<String> uploadMediaToAWS = uploadVideoToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); - - uploadMediaToAWS.enqueue(new Callback<String>() { - @Override - public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { - if (response.isSuccessful()) { - new ParseXMLReponseFromAWSAsyncTask(response.body(), new ParseXMLReponseFromAWSAsyncTask.ParseXMLResponseFromAWSListener() { - @Override - public void parseSuccessful(String url) { - uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, - posterBitmap, new UploadImageListener() { - @Override - public void uploaded(String imageUrl) { - if (fileType.equals("gif")) { - submitPost(oauthRetrofit, accessToken, locale, - subredditName, title, url, flair, isSpoiler, isNSFW, - APIUtils.KIND_VIDEOGIF, imageUrl, submitPostListener); - } else { - submitPost(oauthRetrofit, accessToken, locale, - subredditName, title, url, flair, isSpoiler, isNSFW, - APIUtils.KIND_VIDEO, imageUrl, submitPostListener); - } - } - - @Override - public void uploadFailed(@Nullable String errorMessage) { - submitPostListener.submitFailed(errorMessage); - } - }); - } - - @Override - public void parseFailed() { - submitPostListener.submitFailed(null); - } - }).execute(); - } else { - submitPostListener.submitFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); - } - }); - } + try { + Response<String> uploadImageResponse = uploadImageCall.execute(); + if (uploadImageResponse.isSuccessful()) { + Map<String, RequestBody> nameValuePairsMap = parseJSONResponseFromAWS(uploadImageResponse.body()); + + RequestBody fileBody = RequestBody.create(buffer, MediaType.parse("application/octet-stream")); + MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_video." + fileType, fileBody); - @Override - public void parseFailed() { - submitPostListener.submitFailed(null); + RedditAPI uploadVideoToAWSApi; + if (fileType.equals("gif")) { + uploadVideoToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); + } else { + uploadVideoToAWSApi = uploadVideoRetrofit.create(RedditAPI.class); + } + Call<String> uploadMediaToAWS = uploadVideoToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); + Response<String> uploadMediaToAWSResponse = uploadMediaToAWS.execute(); + if (uploadMediaToAWSResponse.isSuccessful()) { + String url = parseXMLResponseFromAWS(uploadMediaToAWSResponse.body()); + if (url == null) { + submitPostListener.submitFailed(null); + return; + } + String imageUrlOrError = uploadImage(oauthRetrofit, uploadMediaRetrofit, accessToken, posterBitmap); + if (imageUrlOrError != null && !imageUrlOrError.startsWith("Error: ")) { + if (fileType.equals("gif")) { + submitPost(oauthRetrofit, accessToken, + subredditName, title, url, flair, isSpoiler, isNSFW, + APIUtils.KIND_VIDEOGIF, imageUrlOrError, submitPostListener); + } else { + submitPost(oauthRetrofit, accessToken, + subredditName, title, url, flair, isSpoiler, isNSFW, + APIUtils.KIND_VIDEO, imageUrlOrError, submitPostListener); } - }).execute(); + } else { + submitPostListener.submitFailed(imageUrlOrError); + } } else { - submitPostListener.submitFailed(response.message()); + submitPostListener.submitFailed(uploadMediaToAWSResponse.code() + " " + uploadMediaToAWSResponse.message()); } + } else { + submitPostListener.submitFailed(uploadImageResponse.code() + " " + uploadImageResponse.message()); } - - @Override - public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); - } - }); + } catch (IOException | XmlPullParserException | JSONException e) { + e.printStackTrace(); + submitPostListener.submitFailed(e.getMessage()); + } } public static void submitCrosspost(Retrofit oauthRetrofit, String accessToken, - Locale locale, String subredditName, String title, String crosspostFullname, + String subredditName, String title, String crosspostFullname, Flair flair, boolean isSpoiler, boolean isNSFW, String kind, SubmitPostListener submitPostListener) { - submitPost(oauthRetrofit, accessToken, locale, subredditName, title, crosspostFullname, + submitPost(oauthRetrofit, accessToken, subredditName, title, crosspostFullname, flair, isSpoiler, isNSFW, kind, null, submitPostListener); } private static void submitPost(Retrofit oauthRetrofit, String accessToken, - Locale locale, String subredditName, String title, String content, + String subredditName, String title, String content, Flair flair, boolean isSpoiler, boolean isNSFW, String kind, @Nullable String posterUrl, SubmitPostListener submitPostListener) { RedditAPI api = oauthRetrofit.create(RedditAPI.class); @@ -206,32 +168,23 @@ public class SubmitPost { params.put(APIUtils.NSFW_KEY, Boolean.toString(isNSFW)); Call<String> submitPostCall = api.submit(APIUtils.getOAuthHeader(accessToken), params); - submitPostCall.enqueue(new Callback<String>() { - @Override - public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { - if (response.isSuccessful()) { - try { - getSubmittedPost(response.body(), kind, oauthRetrofit, accessToken, - locale, submitPostListener); - } catch (JSONException e) { - e.printStackTrace(); - submitPostListener.submitFailed(null); - } - } else { - submitPostListener.submitFailed(response.message()); - } - } - @Override - public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); + try { + Response<String> response = submitPostCall.execute(); + if (response.isSuccessful()) { + getSubmittedPost(response.body(), kind, oauthRetrofit, accessToken, submitPostListener); + } else { + submitPostListener.submitFailed(response.message()); } - }); + } catch (IOException | JSONException e) { + e.printStackTrace(); + submitPostListener.submitFailed(e.getMessage()); + } } - private static void uploadImage(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, - String accessToken, Bitmap image, - UploadImageListener uploadImageListener) { + @Nullable + private static String uploadImage(Retrofit oauthRetrofit, Retrofit uploadMediaRetrofit, + String accessToken, Bitmap image) throws IOException, JSONException, XmlPullParserException { RedditAPI api = oauthRetrofit.create(RedditAPI.class); Map<String, String> uploadImageParams = new HashMap<>(); @@ -239,70 +192,32 @@ public class SubmitPost { uploadImageParams.put(APIUtils.MIMETYPE_KEY, "image/jpeg"); Call<String> uploadImageCall = api.uploadImage(APIUtils.getOAuthHeader(accessToken), uploadImageParams); - uploadImageCall.enqueue(new Callback<String>() { - @Override - public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { - if (response.isSuccessful()) { - new ParseJSONResponseFromAWSAsyncTask(response.body(), new ParseJSONResponseFromAWSAsyncTask.ParseJSONResponseFromAWSListener() { - @Override - public void parseSuccessful(Map<String, RequestBody> nameValuePairsMap) { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - image.compress(Bitmap.CompressFormat.JPEG, 100, stream); - byte[] byteArray = stream.toByteArray(); - - RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), byteArray); - MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_image.jpg", fileBody); - - RedditAPI uploadMediaToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); - Call<String> uploadMediaToAWS = uploadMediaToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); - - uploadMediaToAWS.enqueue(new Callback<String>() { - @Override - public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { - if (response.isSuccessful()) { - new ParseXMLReponseFromAWSAsyncTask(response.body(), new ParseXMLReponseFromAWSAsyncTask.ParseXMLResponseFromAWSListener() { - @Override - public void parseSuccessful(String url) { - uploadImageListener.uploaded(url); - } - - @Override - public void parseFailed() { - uploadImageListener.uploadFailed(null); - } - }).execute(); - } else { - uploadImageListener.uploadFailed("Error: " + response.code()); - } - } - - @Override - public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { - uploadImageListener.uploadFailed(t.getMessage()); - } - }); - } - - @Override - public void parseFailed() { - uploadImageListener.uploadFailed(null); - } - }).execute(); - } else { - uploadImageListener.uploadFailed(response.message()); - } - } - - @Override - public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { - uploadImageListener.uploadFailed(t.getMessage()); + Response<String> uploadImageResponse = uploadImageCall.execute(); + if (uploadImageResponse.isSuccessful()) { + Map<String, RequestBody> nameValuePairsMap = parseJSONResponseFromAWS(uploadImageResponse.body()); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + image.compress(Bitmap.CompressFormat.JPEG, 100, stream); + byte[] byteArray = stream.toByteArray(); + + RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), byteArray); + MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", "post_image.jpg", fileBody); + + RedditAPI uploadMediaToAWSApi = uploadMediaRetrofit.create(RedditAPI.class); + Call<String> uploadMediaToAWS = uploadMediaToAWSApi.uploadMediaToAWS(nameValuePairsMap, fileToUpload); + Response<String> uploadMediaToAWSResponse = uploadMediaToAWS.execute(); + if (uploadMediaToAWSResponse.isSuccessful()) { + return parseXMLResponseFromAWS(uploadMediaToAWSResponse.body()); + } else { + return "Error: " + uploadMediaToAWSResponse.code(); } - }); + } else { + return "Error: " + uploadImageResponse.message(); + } } private static void getSubmittedPost(String response, String kind, Retrofit oauthRetrofit, - String accessToken, Locale locale, - SubmitPostListener submitPostListener) throws JSONException { + String accessToken, SubmitPostListener submitPostListener) throws JSONException, IOException { JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) @@ -328,31 +243,22 @@ public class SubmitPost { RedditAPI api = oauthRetrofit.create(RedditAPI.class); Call<String> getPostCall = api.getPostOauth(postId, APIUtils.getOAuthHeader(accessToken)); - getPostCall.enqueue(new Callback<String>() { - @Override - public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { - if (response.isSuccessful()) { - ParsePost.parsePost(response.body(), new ParsePost.ParsePostListener() { - @Override - public void onParsePostSuccess(Post post) { - submitPostListener.submitSuccessful(post); - } - - @Override - public void onParsePostFail() { - submitPostListener.submitFailed(null); - } - }); - } else { - submitPostListener.submitFailed(response.message()); + Response<String> getPostCallResponse = getPostCall.execute(); + if (getPostCallResponse.isSuccessful()) { + ParsePost.parsePost(getPostCallResponse.body(), new ParsePost.ParsePostListener() { + @Override + public void onParsePostSuccess(Post post) { + submitPostListener.submitSuccessful(post); } - } - @Override - public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { - submitPostListener.submitFailed(t.getMessage()); - } - }); + @Override + public void onParsePostFail() { + submitPostListener.submitFailed(null); + } + }); + } else { + submitPostListener.submitFailed(getPostCallResponse.message()); + } } else { submitPostListener.submitSuccessful(null); } @@ -364,115 +270,39 @@ public class SubmitPost { void submitFailed(@Nullable String errorMessage); } - private interface UploadImageListener { - void uploaded(String imageUrl); - - void uploadFailed(@Nullable String errorMessage); - } - - private static class ParseJSONResponseFromAWSAsyncTask extends AsyncTask<Void, Void, Void> { - private String response; - private ParseJSONResponseFromAWSListener parseJSONResponseFromAWSListener; - private Map<String, RequestBody> nameValuePairsMap; - private boolean successful; - ParseJSONResponseFromAWSAsyncTask(String response, ParseJSONResponseFromAWSListener parseJSONResponseFromAWSListener) { - this.response = response; - this.parseJSONResponseFromAWSListener = parseJSONResponseFromAWSListener; - nameValuePairsMap = new HashMap<>(); - successful = false; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - JSONObject responseObject = new JSONObject(response); - JSONArray nameValuePairs = responseObject.getJSONObject(JSONUtils.ARGS_KEY).getJSONArray(JSONUtils.FIELDS_KEY); - - nameValuePairsMap = new HashMap<>(); - for (int i = 0; i < nameValuePairs.length(); i++) { - nameValuePairsMap.put(nameValuePairs.getJSONObject(i).getString(JSONUtils.NAME_KEY), - APIUtils.getRequestBody(nameValuePairs.getJSONObject(i).getString(JSONUtils.VALUE_KEY))); - } - - successful = true; - } catch (JSONException e) { - e.printStackTrace(); - successful = false; - } + private static Map<String, RequestBody> parseJSONResponseFromAWS(String response) throws JSONException { + JSONObject responseObject = new JSONObject(response); + JSONArray nameValuePairs = responseObject.getJSONObject(JSONUtils.ARGS_KEY).getJSONArray(JSONUtils.FIELDS_KEY); - return null; + Map<String, RequestBody> nameValuePairsMap = new HashMap<>(); + for (int i = 0; i < nameValuePairs.length(); i++) { + nameValuePairsMap.put(nameValuePairs.getJSONObject(i).getString(JSONUtils.NAME_KEY), + APIUtils.getRequestBody(nameValuePairs.getJSONObject(i).getString(JSONUtils.VALUE_KEY))); } - @Override - protected void onPostExecute(Void aVoid) { - if (successful) { - parseJSONResponseFromAWSListener.parseSuccessful(nameValuePairsMap); - } else { - parseJSONResponseFromAWSListener.parseFailed(); - } - } - - interface ParseJSONResponseFromAWSListener { - void parseSuccessful(Map<String, RequestBody> nameValuePairsMap); - - void parseFailed(); - } + return nameValuePairsMap; } - private static class ParseXMLReponseFromAWSAsyncTask extends AsyncTask<Void, Void, Void> { - private String response; - private ParseXMLResponseFromAWSListener parseXMLResponseFromAWSListener; - private String imageUrl; - private boolean successful; - ParseXMLReponseFromAWSAsyncTask(String response, ParseXMLResponseFromAWSListener parseXMLResponseFromAWSListener) { - this.response = response; - this.parseXMLResponseFromAWSListener = parseXMLResponseFromAWSListener; - successful = false; - } - - @Override - protected Void doInBackground(Void... voids) { - try { - XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser(); - xmlPullParser.setInput(new StringReader(response)); - - boolean isLocationTag = false; - int eventType = xmlPullParser.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - if (xmlPullParser.getName().equals("Location")) { - isLocationTag = true; - } - } else if (eventType == XmlPullParser.TEXT) { - if (isLocationTag) { - imageUrl = xmlPullParser.getText(); - successful = true; - return null; - } - } - eventType = xmlPullParser.next(); + @Nullable + private static String parseXMLResponseFromAWS(String response) throws XmlPullParserException, IOException { + XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser(); + xmlPullParser.setInput(new StringReader(response)); + + boolean isLocationTag = false; + int eventType = xmlPullParser.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + if (xmlPullParser.getName().equals("Location")) { + isLocationTag = true; + } + } else if (eventType == XmlPullParser.TEXT) { + if (isLocationTag) { + return xmlPullParser.getText(); } - } catch (XmlPullParserException | IOException e) { - e.printStackTrace(); - successful = false; - } - - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - if (successful) { - parseXMLResponseFromAWSListener.parseSuccessful(imageUrl); - } else { - parseXMLResponseFromAWSListener.parseFailed(); } + eventType = xmlPullParser.next(); } - interface ParseXMLResponseFromAWSListener { - void parseSuccessful(String url); - - void parseFailed(); - } + return null; } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/services/SubmitPostService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/services/SubmitPostService.java index b979a07e..2f313125 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/services/SubmitPostService.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/services/SubmitPostService.java @@ -6,11 +6,15 @@ import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.AsyncTask; import android.os.Build; +import android.os.Bundle; +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.widget.Toast; import androidx.annotation.NonNull; @@ -19,8 +23,6 @@ import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import com.bumptech.glide.Glide; -import com.bumptech.glide.request.target.CustomTarget; -import com.bumptech.glide.request.transition.Transition; import org.greenrobot.eventbus.EventBus; @@ -29,22 +31,24 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Random; +import java.util.concurrent.ExecutionException; import javax.inject.Inject; import javax.inject.Named; +import ml.docilealligator.infinityforreddit.Flair; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.events.SubmitCrosspostEvent; import ml.docilealligator.infinityforreddit.events.SubmitImagePostEvent; import ml.docilealligator.infinityforreddit.events.SubmitTextOrLinkPostEvent; import ml.docilealligator.infinityforreddit.events.SubmitVideoOrGifPostEvent; -import ml.docilealligator.infinityforreddit.Flair; -import ml.docilealligator.infinityforreddit.Infinity; -import ml.docilealligator.infinityforreddit.utils.NotificationUtils; import ml.docilealligator.infinityforreddit.post.Post; import ml.docilealligator.infinityforreddit.post.SubmitPost; -import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.utils.APIUtils; +import ml.docilealligator.infinityforreddit.utils.NotificationUtils; import retrofit2.Retrofit; public class SubmitPostService extends Service { @@ -61,6 +65,7 @@ public class SubmitPostService extends Service { public static final int EXTRA_POST_TYPE_IMAGE = 1; public static final int EXTRA_POST_TYPE_VIDEO = 2; public static final int EXTRA_POST_TYPE_CROSSPOST = 3; + private static final String EXTRA_MEDIA_URI = "EU"; @Inject @Named("oauth") Retrofit mOauthRetrofit; @@ -72,15 +77,7 @@ public class SubmitPostService extends Service { Retrofit mUploadVideoRetrofit; @Inject CustomThemeWrapper mCustomThemeWrapper; - private String mAccessToken; - private String subredditName; - private String title; - private Flair flair; - private boolean isSpoiler; - private boolean isNSFW; - private String content; - private String kind; - private Uri mediaUri; + private ServiceHandler serviceHandler; public SubmitPostService() { } @@ -90,17 +87,59 @@ public class SubmitPostService extends Service { return null; } + // Handler that receives messages from the thread + private final class ServiceHandler extends Handler { + public ServiceHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(@NonNull Message msg) { + super.handleMessage(msg); + Bundle bundle = msg.getData(); + String accessToken = bundle.getString(EXTRA_ACCESS_TOKEN); + String subredditName = bundle.getString(EXTRA_SUBREDDIT_NAME); + String title = bundle.getString(EXTRA_TITLE); + Flair flair = bundle.getParcelable(EXTRA_FLAIR); + boolean isSpoiler = bundle.getBoolean(EXTRA_IS_SPOILER, false); + boolean isNSFW = bundle.getBoolean(EXTRA_IS_NSFW, false); + int postType = bundle.getInt(EXTRA_POST_TYPE, EXTRA_POST_TEXT_OR_LINK); + + if (postType == EXTRA_POST_TEXT_OR_LINK) { + String content = bundle.getString(EXTRA_CONTENT); + String kind = bundle.getString(EXTRA_KIND); + submitTextOrLinkPost(accessToken, subredditName, title, content, flair, isSpoiler, isNSFW, kind); + } else if (postType == EXTRA_POST_TYPE_CROSSPOST) { + String content = bundle.getString(EXTRA_CONTENT); + submitCrosspost(accessToken, subredditName, title, content, flair, isSpoiler, isNSFW); + } else if (postType == EXTRA_POST_TYPE_IMAGE) { + Uri mediaUri = Uri.parse(bundle.getString(EXTRA_MEDIA_URI)); + submitImagePost(accessToken, mediaUri, subredditName, title, flair, isSpoiler, isNSFW); + } else { + Uri mediaUri = Uri.parse(bundle.getString(EXTRA_MEDIA_URI)); + submitVideoPost(accessToken, mediaUri, subredditName, title, flair, isSpoiler, isNSFW); + } + } + } + @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public void onCreate() { ((Infinity) getApplication()).getAppComponent().inject(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()); + } - mAccessToken = intent.getStringExtra(EXTRA_ACCESS_TOKEN); - subredditName = intent.getStringExtra(EXTRA_SUBREDDIT_NAME); - title = intent.getStringExtra(EXTRA_TITLE); - flair = intent.getParcelableExtra(EXTRA_FLAIR); - isSpoiler = intent.getBooleanExtra(EXTRA_IS_SPOILER, false); - isNSFW = intent.getBooleanExtra(EXTRA_IS_NSFW, false); - int postType = intent.getIntExtra(EXTRA_POST_TYPE, EXTRA_POST_TEXT_OR_LINK); + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + ((Infinity) getApplication()).getAppComponent().inject(this); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel serviceChannel = new NotificationChannel( @@ -113,25 +152,26 @@ public class SubmitPostService extends Service { manager.createNotificationChannel(serviceChannel); } + int randomNotificationIdOffset = new Random().nextInt(10000); + int postType = intent.getIntExtra(EXTRA_POST_TYPE, EXTRA_POST_TEXT_OR_LINK); + Bundle bundle = intent.getExtras(); + 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(R.string.posting)); - submitTextOrLinkPost(); + startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset, createNotification(R.string.posting)); } else if (postType == EXTRA_POST_TYPE_CROSSPOST) { - content = intent.getStringExtra(EXTRA_CONTENT); - startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(R.string.posting)); - submitCrosspost(); + startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset, createNotification(R.string.posting)); } else if (postType == EXTRA_POST_TYPE_IMAGE) { - mediaUri = intent.getData(); - startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(R.string.posting_image)); - submitImagePost(); + bundle.putString(EXTRA_MEDIA_URI, intent.getData().toString()); + startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset, createNotification(R.string.posting_image)); } else { - mediaUri = intent.getData(); - startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID, createNotification(R.string.posting_video)); - submitVideoPost(); + bundle.putString(EXTRA_MEDIA_URI, intent.getData().toString()); + startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset, createNotification(R.string.posting_video)); } + Message msg = serviceHandler.obtainMessage(); + msg.setData(bundle); + serviceHandler.sendMessage(msg); + return START_NOT_STICKY; } @@ -144,8 +184,8 @@ public class SubmitPostService extends Service { .build(); } - private void submitTextOrLinkPost() { - SubmitPost.submitTextOrLinkPost(mOauthRetrofit, mAccessToken, getResources().getConfiguration().locale, + private void submitTextOrLinkPost(String accessToken, String subredditName, String title, String content, Flair flair, boolean isSpoiler, boolean isNSFW, String kind) { + SubmitPost.submitTextOrLinkPost(mOauthRetrofit, accessToken, getResources().getConfiguration().locale, subredditName, title, content, flair, isSpoiler, isNSFW, kind, new SubmitPost.SubmitPostListener() { @Override public void submitSuccessful(Post post) { @@ -163,9 +203,9 @@ public class SubmitPostService extends Service { }); } - private void submitCrosspost() { - SubmitPost.submitCrosspost(mOauthRetrofit, mAccessToken, getResources().getConfiguration().locale, - subredditName, title, content, flair, isSpoiler, isNSFW, APIUtils.KIND_CROSSPOST, new SubmitPost.SubmitPostListener() { + private void submitCrosspost(String accessToken, String subredditName, String title, String content, Flair flair, boolean isSpoiler, boolean isNSFW) { + SubmitPost.submitCrosspost(mOauthRetrofit, accessToken, subredditName, title, content, flair, isSpoiler, + isNSFW, APIUtils.KIND_CROSSPOST, new SubmitPost.SubmitPostListener() { @Override public void submitSuccessful(Post post) { EventBus.getDefault().post(new SubmitCrosspostEvent(true, post, null)); @@ -182,49 +222,35 @@ public class SubmitPostService extends Service { }); } - private void submitImagePost() { - Glide.with(this) - .asBitmap() - .load(mediaUri) - .into(new CustomTarget<Bitmap>() { - - @Override - public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { - SubmitPost.submitImagePost(mOauthRetrofit, mUploadMediaRetrofit, mAccessToken, - getResources().getConfiguration().locale, subredditName, title, resource, - flair, isSpoiler, isNSFW, new SubmitPost.SubmitPostListener() { - @Override - public void submitSuccessful(Post post) { - EventBus.getDefault().post(new SubmitImagePostEvent(true, null)); - Toast.makeText(SubmitPostService.this, R.string.image_is_processing, Toast.LENGTH_SHORT).show(); - - stopService(); - } - - @Override - public void submitFailed(@Nullable String errorMessage) { - EventBus.getDefault().post(new SubmitImagePostEvent(false, errorMessage)); - - stopService(); - } - }); - } - - @Override - public void onLoadFailed(@Nullable Drawable errorDrawable) { - EventBus.getDefault().post(new SubmitImagePostEvent(false, getString(R.string.error_processing_image))); + private void submitImagePost(String accessToken, Uri mediaUri, String subredditName, String title, Flair flair, boolean isSpoiler, boolean isNSFW) { + try { + Bitmap resource = Glide.with(this).asBitmap().load(mediaUri).submit().get(); + SubmitPost.submitImagePost(mOauthRetrofit, mUploadMediaRetrofit, accessToken, subredditName, title, resource, + flair, isSpoiler, isNSFW, new SubmitPost.SubmitPostListener() { + @Override + public void submitSuccessful(Post post) { + EventBus.getDefault().post(new SubmitImagePostEvent(true, null)); + Toast.makeText(SubmitPostService.this, R.string.image_is_processing, Toast.LENGTH_SHORT).show(); - stopService(); - } + stopService(); + } - @Override - public void onLoadCleared(@Nullable Drawable placeholder) { + @Override + public void submitFailed(@Nullable String errorMessage) { + EventBus.getDefault().post(new SubmitImagePostEvent(false, errorMessage)); - } - }); + stopService(); + } + }); + } catch (ExecutionException | InterruptedException e) { + e.printStackTrace(); + EventBus.getDefault().post(new SubmitImagePostEvent(false, getString(R.string.error_processing_image))); + stopService(); + } } - private void submitVideoPost() { + private void submitVideoPost(String accessToken, Uri mediaUri, String subredditName, String title, + Flair flair, boolean isSpoiler, boolean isNSFW) { try { InputStream in = getContentResolver().openInputStream(mediaUri); String type = getContentResolver().getType(mediaUri); @@ -235,67 +261,39 @@ public class SubmitPostService extends Service { cacheFilePath = getExternalCacheDir() + "/" + mediaUri.getLastPathSegment() + ".mp4"; } - new CopyFileToCacheAsyncTask(in, cacheFilePath, - new CopyFileToCacheAsyncTask.CopyFileToCacheAsyncTaskListener() { - @Override - public void success() { - Glide.with(SubmitPostService.this) - .asBitmap() - .load(mediaUri) - .into(new CustomTarget<Bitmap>() { - @Override - public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { - if (type != null) { - SubmitPost.submitVideoPost(mOauthRetrofit, mUploadMediaRetrofit, mUploadVideoRetrofit, - mAccessToken, getResources().getConfiguration().locale, subredditName, title, - new File(cacheFilePath), type, resource, flair, isSpoiler, isNSFW, - new SubmitPost.SubmitPostListener() { - @Override - public void submitSuccessful(Post post) { - EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(true, false, null)); - if (type.contains("gif")) { - Toast.makeText(SubmitPostService.this, R.string.gif_is_processing, Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(SubmitPostService.this, R.string.video_is_processing, Toast.LENGTH_SHORT).show(); - } - - stopService(); - } - - @Override - public void submitFailed(@Nullable String errorMessage) { - EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(false, false, errorMessage)); - - stopService(); - } - }); - } else { - EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(false, true, null)); - } - } - - @Override - public void onLoadFailed(@Nullable Drawable errorDrawable) { - EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(false, true, null)); - - stopService(); - } - - @Override - public void onLoadCleared(@Nullable Drawable placeholder) { - - } - }); - } - - @Override - public void failed() { - EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(false, true, null)); + copyFileToCache(in, cacheFilePath); + + Bitmap resource = Glide.with(this).asBitmap().load(mediaUri).submit().get(); + + if (type != null) { + SubmitPost.submitVideoPost(mOauthRetrofit, mUploadMediaRetrofit, mUploadVideoRetrofit, + accessToken, subredditName, title, new File(cacheFilePath), type, resource, flair, + isSpoiler, isNSFW, new SubmitPost.SubmitPostListener() { + @Override + public void submitSuccessful(Post post) { + EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(true, false, null)); + if (type.contains("gif")) { + Toast.makeText(SubmitPostService.this, R.string.gif_is_processing, Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(SubmitPostService.this, R.string.video_is_processing, Toast.LENGTH_SHORT).show(); + } + + stopService(); + } + + @Override + public void submitFailed(@Nullable String errorMessage) { + EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(false, false, errorMessage)); + + stopService(); + } + }); + } else { + EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(false, true, null)); - stopService(); - } - }).execute(); - } catch (IOException e) { + stopService(); + } + } catch (IOException | InterruptedException | ExecutionException e) { e.printStackTrace(); EventBus.getDefault().post(new SubmitVideoOrGifPostEvent(false, true, null)); @@ -303,47 +301,12 @@ public class SubmitPostService extends Service { } } - private static class CopyFileToCacheAsyncTask extends AsyncTask<Void, Void, Void> { - - private InputStream fileInputStream; - private String destinationFilePath; - private CopyFileToCacheAsyncTaskListener copyFileToCacheAsyncTaskListener; - private boolean parseFailed = false; - - interface CopyFileToCacheAsyncTaskListener { - void success(); - void failed(); - } - - public CopyFileToCacheAsyncTask(InputStream fileInputStream, String destinationFilePath, CopyFileToCacheAsyncTaskListener copyFileToCacheAsyncTaskListener) { - this.fileInputStream = fileInputStream; - this.destinationFilePath = destinationFilePath; - this.copyFileToCacheAsyncTaskListener = copyFileToCacheAsyncTaskListener; - } - - @Override - protected Void doInBackground(Void... voids) { - try (OutputStream out = new FileOutputStream(destinationFilePath)) { - byte[] buf = new byte[2048]; - int len; - while ((len = fileInputStream.read(buf)) > 0) { - out.write(buf, 0, len); - } - } catch (IOException e) { - e.printStackTrace(); - parseFailed = true; - } - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if (parseFailed) { - copyFileToCacheAsyncTaskListener.failed(); - } else { - copyFileToCacheAsyncTaskListener.success(); - } + private static void copyFileToCache(InputStream fileInputStream, String destinationFilePath) throws IOException { + OutputStream out = new FileOutputStream(destinationFilePath); + byte[] buf = new byte[2048]; + int len; + while ((len = fileInputStream.read(buf)) > 0) { + out.write(buf, 0, len); } } |