1

I'm using Periodic WorkManager but update wallpaper after every x minutes automatically. But the issue that I'm facing is that when 'downloadWallpaper' method is called to download the image, it meanwhile proceeds to next method 'setWallpaper' without waiting for image loading completion. How can I add wait for image downloading completion before setting it as wallpaper?

In activity, I was using AyncTask, but WorkManager doesn't need that. One other option is to user blockingGet method of RxJava but how can it be used with my downloadWallpaper method? Following is the code:

import androidx.work.Worker;

public class WallpaperChangeWorker extends Worker {
    protected final Result[] workerResult = {Result.SUCCESS};
    private String filePath;


    protected void setWorkerResult(Result result) {
        workerResult[0] = result;
    }

    @NonNull
    @Override
    public Result doWork() {
        prf = new PrefManager(getApplicationContext());
        wallpaperList = new ArrayList<>();

                loadFavorites();

        return workerResult[0];
    }

    private void downloadWallpaper(Wallpaper wallpaper) {
        title = wallpaper.getTitle();
        extension = wallpaper.getExtension();

        int count;
        try {
            URL url = new URL(wallpaper.getWallpaper());
            URLConnection conection = url.openConnection();
            conection.connect();
            // this will be useful so that you can show a tipical 0-100% progress bar
            int lengthOfFile = conection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(url.openStream(), 8192);

            String dir_path = Environment.getExternalStorageDirectory().toString() + getApplicationContext().getResources().getString(R.string.DownloadFolder);

            if (!dir_exists(dir_path)) {
                File directory = new File(dir_path);
                if (directory.mkdirs()) {
                    Log.v("dir", "is created 1");
                } else {
                    Log.v("dir", "not created 1");

                }
                if (directory.mkdir()) {
                    Log.v("dir", "is created 2");
                } else {
                    Log.v("dir", "not created 2");

                }
            } else {
                Log.v("dir", "is exist");
            }

            // Output stream
            OutputStream output = new FileOutputStream(dir_path + title.toString().replace("/", "_") + "." + extension);

            byte data[] = new byte[1024];

            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                // After this onProgressUpdate will be called
                //   publishProgress(""+(int)((total*100)/lenghtOfFile));

                // writing data to file
                output.write(data, 0, count);
            }

            // flushing output
            output.flush();


            output.close();
            input.close();
            MediaScannerConnection.scanFile(getApplicationContext(), new String[]{dir_path + title.toString().replace("/", "_") + "." + extension},
                    null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        @Override
                        public void onScanCompleted(String path, Uri uri) {

                        }
                    });
            /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                final Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                final Uri contentUri = Uri.fromFile(new File(dir_path + title.toString().replace("/", "_") + "." + extension));
                scanIntent.setData(contentUri);
                sendBroadcast(scanIntent);
            } else {
                final Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()));
                sendBroadcast(intent);
            }*/
            filePath = dir_path + title.toString().replace("/", "_") + "." + extension;

            setWallpaper();

        } catch (Exception e) {

            setWorkerResult(Result.FAILURE);
        }
    }

    private void setWallpaper() {

        WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());

        wallpaperManager.setWallpaperOffsetSteps(1, 1);
        wallpaperManager.suggestDesiredDimensions(width, height);
   wallpaperManager.setBitmap(bitmap);

            setWorkerResult(Result.SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            setWorkerResult(Result.RETRY);
        }
    }

    private boolean dir_exists(String dir_path) {
        boolean ret = false;
        File dir = new File(dir_path);
        if (dir.exists() && dir.isDirectory())
            ret = true;
        return ret;
    }

    private Bitmap loadBitmap(Uri src) {

        Bitmap bm = null;

        try {
            bm = BitmapFactory.decodeStream(
                    getApplicationContext().getContentResolver().openInputStream(src));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return bm;
    }


    private void loadFavorites() {
        final FavoritesStorage storageFavorites = new FavoritesStorage(getApplicationContext());
        wallpaperList = storageFavorites.loadFavorites();

        if (wallpaperList.size() > 0) {
            downloadWallpaper(wallpaperList.get(0));
        } else {
            setWorkerResult(Result.FAILURE);
        }

    }
}
Piyush Bansal
  • 1,635
  • 4
  • 16
  • 39
Usman Rana
  • 2,067
  • 1
  • 21
  • 32

1 Answers1

0

You can write downloading and setting wallpaper as different Works, and do it sequentially:

OneTimeWorkRequest download = new OneTimeWorkRequest.Builder(MyWorker.class).build();
OneTimeWorkRequest set = new OneTimeWorkRequest.Builder(MyWorker2.class).build();

WorkManager.getInstance()
   .beginWith(download)
   .then(set)
   .enqueue();

or you can use this construction

private final Object lock = new Object();
public void setImage(){
    synchronized (lock){
        lock.wait();
    }
    //wallpaperManager.setBitmap and etc work
}

and when you get callback about finish of loading file, you call lock.notify() but i think that is not best variant, and you could continue to search better architecure or way to organize downloading. But what is good in wait() method - is that the method does not consume resources