Periodic WorkManager не дожидается завершения загрузки изображения, чтобы установить обои

Я использую Periodic WorkManager, но автоматически обновляю обои каждые x минут. Но проблема, с которой я столкнулся, заключается в том, что когда для загрузки изображения вызывается метод «скачать обои», он тем временем переходит к следующему методу «Установка обоев», не дожидаясь завершения загрузки изображения. Как добавить ожидание завершения загрузки изображения перед установкой его в качестве обоев?

В работе я использовал AyncTask, но WorkManager это не нужно. Еще один вариант - использовать метод blockingGet пользователя RxJava, но как его можно использовать с моим методом скачать обои? Ниже приведен код:

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);
        }

    }
}

У меня такая же проблема, ты когда-нибудь в этом догадывался?

Josh 17.09.2018 18:52

Я использовал библиотеку AndroidFastNetworking для загрузки изображения и по его завершении устанавливаю обои. Итак, его асинхронный вызов в рабочем потоке.

Usman Rana 18.09.2018 08:11

Я тоже это сделал, рад, что мы пришли к такому же выводу.

Josh 18.09.2018 18:41
1
3
290
1

Ответы 1

Вы можете написать скачивание и установку обоев как разные Работы, и делать это последовательно:

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

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

или вы можете использовать эту конструкцию

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

и когда вы получаете обратный вызов о завершении загрузки файла, вы вызываете lock.notify() но я думаю, что это не лучший вариант, и вы могли бы продолжить поиск лучшей архитектуры или способа организации загрузки. Но что хорошо в методе wait(), так это то, что метод не потребляет ресурсы.

Другие вопросы по теме