Start migrating EditProfileService to JobService.

This commit is contained in:
Docile-Alligator
2024-07-19 11:22:49 -04:00
parent 7443cf8095
commit fbdcf4a55f
10 changed files with 151 additions and 105 deletions

View File

@ -1,9 +1,13 @@
package ml.docilealligator.infinityforreddit.activities;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
@ -15,7 +19,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider;
import com.bumptech.glide.Glide;
@ -208,7 +211,7 @@ public class EditProfileActivity extends BaseActivity {
if (resultCode != RESULT_OK || data == null || accountName.equals(Account.ANONYMOUS_ACCOUNT)) {
return;
}
Intent intent = new Intent(this, EditProfileService.class);
/*Intent intent = new Intent(this, EditProfileService.class);
intent.setData(data.getData());
intent.putExtra(EditProfileService.EXTRA_ACCOUNT_NAME, accountName);
intent.putExtra(EditProfileService.EXTRA_ACCESS_TOKEN, accessToken);
@ -224,6 +227,32 @@ public class EditProfileActivity extends BaseActivity {
break;
default:
break;
}*/
int contentEstimatedBytes = 0;
PersistableBundle extras = new PersistableBundle();
extras.putString(EditProfileService.EXTRA_MEDIA_URI, data.getData().toString());
extras.putString(EditProfileService.EXTRA_ACCOUNT_NAME, accountName);
extras.putString(EditProfileService.EXTRA_ACCESS_TOKEN, accessToken);
switch (requestCode) {
case PICK_IMAGE_BANNER_REQUEST_CODE: {
extras.putInt(EditProfileService.EXTRA_POST_TYPE, EditProfileService.EXTRA_POST_TYPE_CHANGE_BANNER);
//TODO: contentEstimatedBytes
JobInfo jobInfo = EditProfileService.constructJobInfo(this, 100, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
break;
}
case PICK_IMAGE_AVATAR_REQUEST_CODE: {
extras.putInt(EditProfileService.EXTRA_POST_TYPE, EditProfileService.EXTRA_POST_TYPE_CHANGE_AVATAR);
//TODO: contentEstimatedBytes
JobInfo jobInfo = EditProfileService.constructJobInfo(this, 100, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
break;
}
default:
break;
}
}
@ -251,14 +280,24 @@ public class EditProfileActivity extends BaseActivity {
}
if (aboutYou == null || displayName == null) return false; //
Intent intent = new Intent(this, EditProfileService.class);
/*Intent intent = new Intent(this, EditProfileService.class);
intent.putExtra(EditProfileService.EXTRA_ACCOUNT_NAME, accountName);
intent.putExtra(EditProfileService.EXTRA_ACCESS_TOKEN, accessToken);
intent.putExtra(EditProfileService.EXTRA_DISPLAY_NAME, displayName); //
intent.putExtra(EditProfileService.EXTRA_ABOUT_YOU, aboutYou); //
intent.putExtra(EditProfileService.EXTRA_POST_TYPE, EditProfileService.EXTRA_POST_TYPE_SAVE_EDIT_PROFILE);
ContextCompat.startForegroundService(this, intent);
ContextCompat.startForegroundService(this, intent);*/
PersistableBundle extras = new PersistableBundle();
extras.putString(EditProfileService.EXTRA_ACCOUNT_NAME, accountName);
extras.putString(EditProfileService.EXTRA_ACCESS_TOKEN, accessToken);
extras.putString(EditProfileService.EXTRA_DISPLAY_NAME, displayName);
extras.putString(EditProfileService.EXTRA_ABOUT_YOU, aboutYou);
extras.putInt(EditProfileService.EXTRA_POST_TYPE, EditProfileService.EXTRA_POST_TYPE_SAVE_EDIT_PROFILE);
JobInfo jobInfo = EditProfileService.constructJobInfo(this, 1000, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
return true;
}
return false;

View File

@ -623,7 +623,6 @@ public class PostGalleryActivity extends BaseActivity implements FlairBottomShee
String payloadJSON = new Gson().toJson(payload);
extras.putString(SubmitPostService.EXTRA_REDDIT_GALLERY_PAYLOAD, payloadJSON);
// TODO: jobId and uploadBytes
JobInfo jobInfo = SubmitPostService.constructJobInfo(this, payloadJSON.length() * 2L, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);

View File

@ -581,7 +581,7 @@ public class PostImageActivity extends BaseActivity implements FlairBottomSheetF
extras.putInt(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TYPE_IMAGE);
}
// TODO: jobId and uploadBytes
// TODO: contentEstimatedBytes
JobInfo jobInfo = SubmitPostService.constructJobInfo(this, contentEstimatedBytes, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);

View File

@ -569,7 +569,6 @@ public class PostLinkActivity extends BaseActivity implements FlairBottomSheetFr
extras.putInt(SubmitPostService.EXTRA_RECEIVE_POST_REPLY_NOTIFICATIONS, binding.receivePostReplyNotificationsSwitchMaterialPostLinkActivity.isChecked() ? 1 : 0);
extras.putInt(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TEXT_OR_LINK);
// TODO: jobId and uploadBytes
JobInfo jobInfo = SubmitPostService.constructJobInfo(this, contentEstimatedBytes, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);

View File

@ -689,7 +689,6 @@ public class PostPollActivity extends BaseActivity implements FlairBottomSheetFr
String payloadJSON = new Gson().toJson(payload);
extras.putString(SubmitPostService.EXTRA_POLL_PAYLOAD, payloadJSON);
// TODO: jobId and uploadBytes
JobInfo jobInfo = SubmitPostService.constructJobInfo(this, payloadJSON.length() * 2L, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
}

View File

@ -564,7 +564,6 @@ public class PostTextActivity extends BaseActivity implements FlairBottomSheetFr
extras.putInt(SubmitPostService.EXTRA_RECEIVE_POST_REPLY_NOTIFICATIONS, binding.receivePostReplyNotificationsSwitchMaterialPostTextActivity.isChecked() ? 1 : 0);
extras.putInt(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TEXT_OR_LINK);
// TODO: jobId and uploadBytes
JobInfo jobInfo = SubmitPostService.constructJobInfo(this, contentEstimatedBytes, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
}

View File

@ -592,7 +592,7 @@ public class PostVideoActivity extends BaseActivity implements FlairBottomSheetF
extras.putInt(SubmitPostService.EXTRA_RECEIVE_POST_REPLY_NOTIFICATIONS, binding.receivePostReplyNotificationsSwitchMaterialPostVideoActivity.isChecked() ? 1 : 0);
extras.putInt(SubmitPostService.EXTRA_POST_TYPE, SubmitPostService.EXTRA_POST_TYPE_VIDEO);
// TODO: jobId and uploadBytes
// TODO: contentEstimatedBytes
JobInfo jobInfo = SubmitPostService.constructJobInfo(this, contentEstimatedBytes, extras);
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);

View File

@ -1,18 +1,18 @@
package ml.docilealligator.infinityforreddit.services;
import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.Bundle;
import android.os.Build;
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.os.PersistableBundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -27,6 +27,7 @@ import org.greenrobot.eventbus.EventBus;
import java.io.FileNotFoundException;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Named;
@ -42,46 +43,57 @@ import ml.docilealligator.infinityforreddit.utils.EditProfileUtils;
import ml.docilealligator.infinityforreddit.utils.NotificationUtils;
import retrofit2.Retrofit;
public class EditProfileService extends Service {
public class EditProfileService extends JobService {
public static final String EXTRA_ACCESS_TOKEN = "EAT";
public static final String EXTRA_ACCOUNT_NAME = "EAN";
public static final String EXTRA_DISPLAY_NAME = "EDN";
public static final String EXTRA_ABOUT_YOU = "EAY";
public static final String EXTRA_POST_TYPE = "EPT";
public static final String EXTRA_MEDIA_URI = "EU";
public static final int EXTRA_POST_TYPE_UNKNOWN = 0x500;
public static final int EXTRA_POST_TYPE_CHANGE_BANNER = 0x501;
public static final int EXTRA_POST_TYPE_CHANGE_AVATAR = 0x502;
public static final int EXTRA_POST_TYPE_SAVE_EDIT_PROFILE = 0x503;
private static final String EXTRA_MEDIA_URI = "EU";
private static final int MAX_BANNER_WIDTH = 1280;
private static final int MIN_BANNER_WIDTH = 640;
private static final int AVATAR_SIZE = 256;
private static int JOB_ID = 10000;
@Inject
@Named("oauth")
Retrofit mOauthRetrofit;
@Inject
CustomThemeWrapper mCustomThemeWrapper;
@Inject
Executor mExecutor;
private Handler handler;
private ServiceHandler serviceHandler;
public static JobInfo constructJobInfo(Context context, long contentEstimatedBytes, PersistableBundle extras) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
return new JobInfo.Builder(JOB_ID++, new ComponentName(context, EditProfileService.class))
.setUserInitiated(true)
.setRequiredNetwork(new NetworkRequest.Builder().build())
.setEstimatedNetworkBytes(0, contentEstimatedBytes + 500)
.setExtras(extras)
.build();
} else {
return new JobInfo.Builder(JOB_ID++, new ComponentName(context, EditProfileService.class))
.build();
}
}
@Override
public void onCreate() {
super.onCreate();
((Infinity) getApplication()).getAppComponent().inject(this);
handler = new Handler();
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
serviceHandler = new ServiceHandler(thread.getLooper());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
((Infinity) getApplication()).getAppComponent().inject(this);
public boolean onStartJob(JobParameters params) {
NotificationChannelCompat serviceChannel =
new NotificationChannelCompat.Builder(
NotificationUtils.CHANNEL_SUBMIT_POST,
@ -93,41 +105,83 @@ public class EditProfileService extends Service {
manager.createNotificationChannel(serviceChannel);
int randomNotificationIdOffset = new Random().nextInt(10000);
Bundle bundle = intent.getExtras();
final int postType = intent.getIntExtra(EXTRA_POST_TYPE, EXTRA_POST_TYPE_UNKNOWN);
PersistableBundle bundle = params.getExtras();
String accessToken = bundle.getString(EXTRA_ACCESS_TOKEN);
String accountName = bundle.getString(EXTRA_ACCOUNT_NAME);
final int postType = bundle.getInt(EXTRA_POST_TYPE, EXTRA_POST_TYPE_UNKNOWN);
switch (postType) {
case EXTRA_POST_TYPE_CHANGE_BANNER:
bundle.putString(EXTRA_MEDIA_URI, intent.getData().toString());
startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_change_banner));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
setNotification(params,
NotificationUtils.EDIT_PROFILE_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_change_banner),
JobService.JOB_END_NOTIFICATION_POLICY_REMOVE);
} else {
manager.notify(NotificationUtils.EDIT_PROFILE_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_change_banner));
}
break;
case EXTRA_POST_TYPE_CHANGE_AVATAR:
bundle.putString(EXTRA_MEDIA_URI, intent.getData().toString());
startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_change_avatar));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
setNotification(params,
NotificationUtils.EDIT_PROFILE_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_change_avatar),
JobService.JOB_END_NOTIFICATION_POLICY_REMOVE);
} else {
manager.notify(NotificationUtils.EDIT_PROFILE_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_change_avatar));
}
break;
case EXTRA_POST_TYPE_SAVE_EDIT_PROFILE:
startForeground(NotificationUtils.SUBMIT_POST_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_save_profile));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
setNotification(params,
NotificationUtils.EDIT_PROFILE_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_save_profile),
JobService.JOB_END_NOTIFICATION_POLICY_REMOVE);
} else {
manager.notify(NotificationUtils.EDIT_PROFILE_SERVICE_NOTIFICATION_ID + randomNotificationIdOffset,
createNotification(R.string.submit_save_profile));
}
break;
default:
case EXTRA_POST_TYPE_UNKNOWN:
break;
return false;
}
Message msg = serviceHandler.obtainMessage();
msg.setData(bundle);
serviceHandler.sendMessage(msg);
return START_NOT_STICKY;
mExecutor.execute(() -> {
switch (postType) {
case EXTRA_POST_TYPE_CHANGE_BANNER:
submitChangeBanner(params, accessToken,
Uri.parse(bundle.getString(EXTRA_MEDIA_URI)),
accountName);
break;
case EXTRA_POST_TYPE_CHANGE_AVATAR:
submitChangeAvatar(params, accessToken,
Uri.parse(bundle.getString(EXTRA_MEDIA_URI)),
accountName);
break;
case EXTRA_POST_TYPE_SAVE_EDIT_PROFILE:
submitSaveEditProfile(
params,
accessToken,
accountName,
bundle.getString(EXTRA_DISPLAY_NAME),
bundle.getString(EXTRA_ABOUT_YOU)
);
break;
}
});
return true;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
public boolean onStopJob(JobParameters params) {
return false;
}
private void submitChangeBanner(String accessToken, Uri mediaUri, String accountName) {
private void submitChangeBanner(JobParameters parameters, String accessToken, Uri mediaUri, String accountName) {
try {
final int width = getWidthBanner(mediaUri);
final int height = Math.round(width * 3 / 10f); // ratio 10:3
@ -138,22 +192,22 @@ public class EditProfileService extends Service {
@Override
public void success() {
handler.post(() -> EventBus.getDefault().post(new SubmitChangeBannerEvent(true, "")));
stopService();
jobFinished(parameters, false);
}
@Override
public void failed(String message) {
handler.post(() -> EventBus.getDefault().post(new SubmitChangeBannerEvent(false, message)));
stopService();
jobFinished(parameters, false);
}
});
} catch (InterruptedException | ExecutionException | FileNotFoundException e) {
e.printStackTrace();
stopService();
jobFinished(parameters, false);
}
}
private void submitChangeAvatar(String accessToken, Uri mediaUri, String accountName) {
private void submitChangeAvatar(JobParameters parameters, String accessToken, Uri mediaUri, String accountName) {
try {
final CropTransformation avatarCrop = new CropTransformation(AVATAR_SIZE, AVATAR_SIZE, CropTransformation.CropType.CENTER);
final Bitmap resource = Glide.with(this).asBitmap().skipMemoryCache(true)
@ -162,22 +216,22 @@ public class EditProfileService extends Service {
@Override
public void success() {
handler.post(() -> EventBus.getDefault().post(new SubmitChangeAvatarEvent(true, "")));
stopService();
jobFinished(parameters, false);
}
@Override
public void failed(String message) {
handler.post(() -> EventBus.getDefault().post(new SubmitChangeAvatarEvent(false, message)));
stopService();
jobFinished(parameters, false);
}
});
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
stopService();
jobFinished(parameters, false);
}
}
private void submitSaveEditProfile(@Nullable String accessToken,
private void submitSaveEditProfile(JobParameters parameters, @Nullable String accessToken,
@NonNull String accountName,
String displayName,
String publicDesc
@ -191,13 +245,13 @@ public class EditProfileService extends Service {
@Override
public void success() {
handler.post(() -> EventBus.getDefault().post(new SubmitSaveProfileEvent(true, "")));
stopService();
jobFinished(parameters, false);
}
@Override
public void failed(String message) {
handler.post(() -> EventBus.getDefault().post(new SubmitSaveProfileEvent(false, message)));
stopService();
jobFinished(parameters, false);
}
});
@ -212,54 +266,10 @@ public class EditProfileService extends Service {
.build();
}
private void stopService() {
stopForeground(true);
stopSelf();
}
private int getWidthBanner(Uri mediaUri) throws FileNotFoundException {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver().openInputStream(mediaUri), null, options);
return Math.max(Math.min(options.outWidth, MAX_BANNER_WIDTH), MIN_BANNER_WIDTH);
}
private 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 accountName = bundle.getString(EXTRA_ACCOUNT_NAME);
final int postType = bundle.getInt(EXTRA_POST_TYPE, EXTRA_POST_TYPE_UNKNOWN);
switch (postType) {
case EXTRA_POST_TYPE_CHANGE_BANNER:
submitChangeBanner(accessToken,
Uri.parse(bundle.getString(EXTRA_MEDIA_URI)),
accountName);
break;
case EXTRA_POST_TYPE_CHANGE_AVATAR:
submitChangeAvatar(accessToken,
Uri.parse(bundle.getString(EXTRA_MEDIA_URI)),
accountName);
break;
case EXTRA_POST_TYPE_SAVE_EDIT_PROFILE:
submitSaveEditProfile(
accessToken,
accountName,
bundle.getString(EXTRA_DISPLAY_NAME),
bundle.getString(EXTRA_ABOUT_YOU)
);
break;
default:
case EXTRA_POST_TYPE_UNKNOWN:
break;
}
}
}
}

View File

@ -28,6 +28,7 @@ public class NotificationUtils {
public static final int DOWNLOAD_IMAGE_NOTIFICATION_ID = 40000;
public static final int DOWNLOAD_GIF_NOTIFICATION_ID = 50000;
public static final int MATERIAL_YOU_NOTIFICATION_ID = 60000;
public static final int EDIT_PROFILE_SERVICE_NOTIFICATION_ID = 70000;
private static final int SUMMARY_BASE_ID_UNREAD_MESSAGE = 0;
private static final int NOTIFICATION_BASE_ID_UNREAD_MESSAGE = 1;

View File

@ -1275,9 +1275,9 @@
<string name="app_lock_timeout_24_hours">24 hours</string>
<!--EditProfileService Notification-->
<string name="submit_change_avatar">Submit Change Avatar</string>
<string name="submit_change_banner">Submit Change Banner</string>
<string name="submit_save_profile">Submit Save Profile</string>
<string name="submit_change_avatar">Changing Avatar</string>
<string name="submit_change_banner">Changing Banner</string>
<string name="submit_save_profile">Saving Profile</string>
<!--EditProfileActivity-->
<string name="action_edit_profile">Edit Profile</string>