mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Set Wallpaper in background (#5665)
* Worker added for setting up wallpaper * Fix crash * Fix test * Fix test
This commit is contained in:
parent
a7a2125e1d
commit
4c687b4335
5 changed files with 190 additions and 61 deletions
|
|
@ -0,0 +1,130 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.Worker;
|
||||
import androidx.work.WorkerParameters;
|
||||
import com.facebook.common.executors.CallerThreadExecutor;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.core.ImagePipeline;
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
||||
import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import fr.free.nrw.commons.R;
|
||||
import java.io.IOException;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class SetWallpaperWorker extends Worker {
|
||||
|
||||
private static final String NOTIFICATION_CHANNEL_ID = "set_wallpaper_channel";
|
||||
private static final int NOTIFICATION_ID = 1;
|
||||
|
||||
public SetWallpaperWorker(@NonNull Context context, @NonNull WorkerParameters params) {
|
||||
super(context, params);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result doWork() {
|
||||
Context context = getApplicationContext();
|
||||
createNotificationChannel(context);
|
||||
showProgressNotification(context);
|
||||
|
||||
String imageUrl = getInputData().getString("imageUrl");
|
||||
if (imageUrl == null) {
|
||||
return Result.failure();
|
||||
}
|
||||
|
||||
ImageRequest imageRequest = ImageRequestBuilder
|
||||
.newBuilderWithSource(Uri.parse(imageUrl))
|
||||
.build();
|
||||
|
||||
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
||||
final DataSource<CloseableReference<CloseableImage>>
|
||||
dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);
|
||||
|
||||
dataSource.subscribe(new BaseBitmapDataSubscriber() {
|
||||
@Override
|
||||
public void onNewResultImpl(@Nullable Bitmap bitmap) {
|
||||
if (dataSource.isFinished() && bitmap != null) {
|
||||
Timber.d("Bitmap loaded from url %s", imageUrl.toString());
|
||||
setWallpaper(context, Bitmap.createBitmap(bitmap));
|
||||
dataSource.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailureImpl(DataSource dataSource) {
|
||||
Timber.d("Error getting bitmap from image url %s", imageUrl.toString());
|
||||
showNotification(context, "Setting Wallpaper Failed", "Failed to download image.");
|
||||
if (dataSource != null) {
|
||||
dataSource.close();
|
||||
}
|
||||
}
|
||||
}, CallerThreadExecutor.getInstance());
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private void setWallpaper(Context context, Bitmap bitmap) {
|
||||
WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
|
||||
|
||||
try {
|
||||
wallpaperManager.setBitmap(bitmap);
|
||||
showNotification(context, "Wallpaper Set", "Wallpaper has been updated successfully.");
|
||||
|
||||
} catch (Exception e) {
|
||||
Timber.e(e, "Error setting wallpaper");
|
||||
showNotification(context, "Setting Wallpaper Failed", " "+e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void showProgressNotification(Context context) {
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.commons_logo)
|
||||
.setContentTitle("Setting Wallpaper")
|
||||
.setContentText("Please wait...")
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setOngoing(true)
|
||||
.setProgress(0, 0, true);
|
||||
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
|
||||
private void showNotification(Context context, String title, String content) {
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.commons_logo)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setOngoing(false);
|
||||
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
|
||||
private void createNotificationChannel(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
CharSequence name = "Wallpaper Setting";
|
||||
String description = "Notifications for wallpaper setting progress";
|
||||
int importance = NotificationManager.IMPORTANCE_HIGH;
|
||||
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance);
|
||||
channel.setDescription(description);
|
||||
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -164,9 +164,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
|||
if (savedInstanceState != null) {
|
||||
editable = savedInstanceState.getBoolean("editable", false);
|
||||
isFeaturedImage = savedInstanceState.getBoolean("isFeaturedImage", false);
|
||||
if(null != binding.mediaDetailsPager) {
|
||||
binding.mediaDetailsPager.setCurrentItem(savedInstanceState.getInt("current-page", 0), false);
|
||||
}
|
||||
|
||||
}
|
||||
setHasOptionsMenu(true);
|
||||
initProvider();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package fr.free.nrw.commons.utils;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
|
|
@ -8,10 +10,14 @@ import android.graphics.BitmapFactory;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
import com.facebook.common.executors.CallerThreadExecutor;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
|
|
@ -22,6 +28,7 @@ import com.facebook.imagepipeline.image.CloseableImage;
|
|||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.SetWallpaperWorker;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
|
@ -195,38 +202,24 @@ public class ImageUtils {
|
|||
* @param imageUrl Url of the image
|
||||
*/
|
||||
public static void setWallpaperFromImageUrl(Context context, Uri imageUrl) {
|
||||
showSettingWallpaperProgressBar(context);
|
||||
Timber.d("Trying to set wallpaper from url %s", imageUrl.toString());
|
||||
ImageRequest imageRequest = ImageRequestBuilder
|
||||
.newBuilderWithSource(imageUrl)
|
||||
.setAutoRotateEnabled(true)
|
||||
.build();
|
||||
|
||||
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
||||
final DataSource<CloseableReference<CloseableImage>>
|
||||
dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);
|
||||
enqueueSetWallpaperWork(context, imageUrl);
|
||||
|
||||
dataSource.subscribe(new BaseBitmapDataSubscriber() {
|
||||
|
||||
@Override
|
||||
public void onNewResultImpl(@Nullable Bitmap bitmap) {
|
||||
if (dataSource.isFinished() && bitmap != null) {
|
||||
Timber.d("Bitmap loaded from url %s", imageUrl.toString());
|
||||
setWallpaper(context, Bitmap.createBitmap(bitmap));
|
||||
dataSource.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailureImpl(DataSource dataSource) {
|
||||
Timber.d("Error getting bitmap from image url %s", imageUrl.toString());
|
||||
if (dataSource != null) {
|
||||
dataSource.close();
|
||||
}
|
||||
}
|
||||
}, CallerThreadExecutor.getInstance());
|
||||
}
|
||||
|
||||
private static void createNotificationChannel(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
CharSequence name = "Wallpaper Setting";
|
||||
String description = "Notifications for wallpaper setting progress";
|
||||
int importance = NotificationManager.IMPORTANCE_DEFAULT;
|
||||
NotificationChannel channel = new NotificationChannel("set_wallpaper_channel", name, importance);
|
||||
channel.setDescription(description);
|
||||
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the set avatar api to set the image url as user's avatar
|
||||
* @param context
|
||||
|
|
@ -272,23 +265,21 @@ public class ImageUtils {
|
|||
|
||||
}
|
||||
|
||||
private static void setWallpaper(Context context, Bitmap bitmap) {
|
||||
WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
|
||||
try {
|
||||
wallpaperManager.setBitmap(bitmap);
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wallpaper_set_successfully));
|
||||
if (progressDialogWallpaper != null && progressDialogWallpaper.isShowing()) {
|
||||
progressDialogWallpaper.dismiss();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "Error setting wallpaper");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wallpaper_set_unsuccessfully));
|
||||
if (progressDialogWallpaper != null) {
|
||||
progressDialogWallpaper.cancel();
|
||||
}
|
||||
}
|
||||
public static void enqueueSetWallpaperWork(Context context, Uri imageUrl) {
|
||||
createNotificationChannel(context); // Ensure the notification channel is created
|
||||
|
||||
Data inputData = new Data.Builder()
|
||||
.putString("imageUrl", imageUrl.toString())
|
||||
.build();
|
||||
|
||||
OneTimeWorkRequest setWallpaperWork = new OneTimeWorkRequest.Builder(SetWallpaperWorker.class)
|
||||
.setInputData(inputData)
|
||||
.build();
|
||||
|
||||
WorkManager.getInstance(context).enqueue(setWallpaperWork);
|
||||
}
|
||||
|
||||
|
||||
private static void showSettingWallpaperProgressBar(Context context) {
|
||||
progressDialogWallpaper = ProgressDialog.show(context, context.getString(R.string.setting_wallpaper_dialog_title),
|
||||
context.getString(R.string.setting_wallpaper_dialog_message), true);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import android.view.MenuItem
|
|||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.work.testing.WorkManagerTestInitHelper
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.soloader.SoLoader
|
||||
import com.nhaarman.mockitokotlin2.any
|
||||
|
|
@ -79,8 +80,11 @@ class MediaDetailPagerFragmentUnitTests {
|
|||
|
||||
MockitoAnnotations.openMocks(this)
|
||||
|
||||
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
WorkManagerTestInitHelper.initializeTestWorkManager(context)
|
||||
|
||||
OkHttpConnectionFactory.CLIENT = createTestClient()
|
||||
|
||||
SoLoader.setInTestMode()
|
||||
|
|
|
|||
|
|
@ -3,14 +3,22 @@ package fr.free.nrw.commons.utils
|
|||
import android.app.ProgressDialog
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.work.Data
|
||||
import androidx.work.ListenableWorker
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.testing.TestListenableWorkerBuilder
|
||||
import androidx.work.testing.WorkManagerTestInitHelper
|
||||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import fr.free.nrw.commons.contributions.SetWallpaperWorker
|
||||
import fr.free.nrw.commons.location.LatLng
|
||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.mock
|
||||
|
|
@ -24,6 +32,7 @@ import java.lang.reflect.Field
|
|||
import java.lang.reflect.Method
|
||||
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||
@LooperMode(LooperMode.Mode.PAUSED)
|
||||
|
|
@ -31,9 +40,6 @@ class ImageUtilsTest {
|
|||
|
||||
private lateinit var context: Context
|
||||
|
||||
@Mock
|
||||
private lateinit var bitmap: Bitmap
|
||||
|
||||
@Mock
|
||||
private lateinit var progressDialogWallpaper: ProgressDialog
|
||||
|
||||
|
|
@ -43,10 +49,18 @@ class ImageUtilsTest {
|
|||
@Mock
|
||||
private lateinit var compositeDisposable: CompositeDisposable
|
||||
|
||||
@Mock
|
||||
private lateinit var imageUri: Uri
|
||||
|
||||
private lateinit var workManager: WorkManager
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
WorkManagerTestInitHelper.initializeTestWorkManager(context)
|
||||
workManager = WorkManager.getInstance(context)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -87,20 +101,13 @@ class ImageUtilsTest {
|
|||
fun testSetWallpaper() {
|
||||
val mockImageUtils = mock(ImageUtils::class.java)
|
||||
val method: Method = ImageUtils::class.java.getDeclaredMethod(
|
||||
"setWallpaper",
|
||||
"enqueueSetWallpaperWork",
|
||||
Context::class.java,
|
||||
Bitmap::class.java
|
||||
Uri::class.java
|
||||
)
|
||||
method.isAccessible = true
|
||||
|
||||
`when`(progressDialogWallpaper.isShowing).thenReturn(true)
|
||||
|
||||
val progressDialogWallpaperField: Field =
|
||||
ImageUtils::class.java.getDeclaredField("progressDialogWallpaper")
|
||||
progressDialogWallpaperField.isAccessible = true
|
||||
progressDialogWallpaperField.set(mockImageUtils, progressDialogWallpaper)
|
||||
|
||||
method.invoke(mockImageUtils, context, bitmap)
|
||||
method.invoke(mockImageUtils, context, imageUri)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -190,5 +197,4 @@ class ImageUtilsTest {
|
|||
method.isAccessible = true
|
||||
method.invoke(mockImageUtils, null)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue