Подтверждение загрузки в DownloadManager

331
21 февраля 2017, 17:16

Здравствуйте!

Я использую DownloadManager для загрузки файлов в своем приложении, требуется сделать загрузку и прежде чем продолжить работу с файлом нужно убедиться, что он полностью успел загрузиться.

final String DOWNLOAD_FILE = "https://s04g.storage.yandex.net/rdisk/585a6604b6bf33cb41214756c8bcb6e042e43997f4dfe17ad59165adb2050bd1/58a9d0b9/jAtpeUabHpPNIw4Mb7j7hAJKqlCebrorxpbrJybHDsliI2I2klqhwIqCdcp1qNlrvPGP6vLE4syFY40S1bo83Q==?uid=21323916&filename=Music.zip&disposition=attachment&hash=&limit=0&content_type=application%2Fx-zip-compressed&fsize=70303471&hid=4700b296603d09c16a00bed3ec6214e4&media_type=compressed&tknv=v2&etag=5ae8af2d8bce2bd03da3ad9975f7c2c8&rtoken=rWu9ENQ02TvG&force_default=yes&ycrid=na-501eb41ae05c5d3357d490381dc2e603-downloader12g&ts=548e52d1ae040&s=b5e129a2d70b5f19cc9ed9a872b340f5bf2bbaae9b7e264f6c0ac855447e6112&bp=/32/8/data-0.20:40030971360:70303471&pb=U2FsdGVkX1-srN3n6Ub2oPEPgx-KI4tr5AxU4rOtz4d3Y_72xPNBaOzzEU88c7tccKKojdcS1N_Mrd1NUe1woyNHjich9dA-OWWfgK5d33U=";
final String Download_ID = "PREF_DOWNLOAD_ID";
SharedPreferences preferenceManager;
DownloadManager downloadManager;
long id;
int stat = 0;
preferenceManager = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
                downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                // проверяем был ли уже загружен файл
                String path = Environment.getExternalStorageDirectory() + "/";
                File file = new File(path + "LiveWallpapers/123.zip");
                if (!file.exists()) {
                    Log.i(TAG, "Файл отсутствует");
                    // загружаем файл
                    Uri downloadUri = Uri.parse(DOWNLOAD_FILE);
                    DownloadManager.Request request = new DownloadManager.Request(downloadUri);
                    // назначаем имя для файла
                    request.setDestinationInExternalPublicDir("LiveWallpapers", "123.zip");
                    // сохраняем request id
                    SharedPreferences.Editor PrefEdit = preferenceManager.edit();
                    id = downloadManager.enqueue(request);
                    PrefEdit.putLong(Download_ID, id);
                    PrefEdit.apply();
                } else {
                    Log.i(TAG, "Файл уже загружен");
                    // файл уже загружен
                    is = getResources().openRawResource(R.raw.nature1);
                }

                // ждем загрузку файла
                if (is == null) {
                    repeat:
                    for (int z = 0; z < 30; z++) {
                        // проверяем процесс загрузки файла
                        BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
                            @Override
                            public void onReceive(Context context, Intent intent) {
                                Log.i(TAG, "Проверка метки");
                                String action = intent.getAction();
                                if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
                                    DownloadManager.Query query = new DownloadManager.Query();
                                    query.setFilterById(id);
                                    Cursor cursor = downloadManager.query(query);
                                    if (cursor != null && cursor.moveToFirst()) {
                                        int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
                                        if (DownloadManager.STATUS_SUCCESSFUL == cursor.getInt(columnIndex)) {
                                            Log.i(TAG, "Метка об окончании загрузки");
                                            stat = 1;
                                            cursor.close();
                                        }
                                    }
                                }
                            }
                        };
                        if (stat == 1) {
                            Log.i(TAG, "Открываем анимацию");
                            is = getResources().openRawResource(R.raw.nature1);
                            break;
                        } else {
                            // отправляем проверку на загруженность файла
                            registerReceiver(downloadReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
                            try {
                                Log.i(TAG, "Файл в процессе загрузки...");
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                            }
                            continue repeat;
                        }
                    }
                }

В принципе файл скачивается корретно, если же файл с таким именем уже существует, то этот процесс пропускается. Проблема заключается в том, что если файла не существует и он загружается я не получаю уведомления об его окончании загрузки, т.е. не срабатывает переход сюда

BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
    ...
}

По логу вижу что сначала появляется 'Файл отсутствует', потом 'Файл в процессе загрузки...', но даже по завершению загрузки логи продолжают сыпать 'Файл в процессе загрузки...'

Руководствовался вот этой статьей при написании кода: http://blog.vogella.com/2011/06/14/android-downloadmanager-example/

В файле манифеста добавлено:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Некоторые могут сказать, что нужно делать отдельный класс и прослушивать события в нем вот так:

public class DownloadBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "log";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
            // ?
        }
    }
}

Манифест

<receiver android:name=".DownloadBroadcastReceiver"
   android:enabled="true"
   android:exported="true">
      <intent-filter>
         <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
      </intent-filter>
</receiver>

Но вот не знаю я как потом это событие передать в свой класс из DownloadBroadcastReceiver, где происходит работа с кодом, а перетащить весь код туда у меня тоже не получится...

Сделал вот так:

downloadWallpaper("https://media.giphy.com/media/rAJfdmusNFDDG/source.gif", "source.gif");
Uri path =(Uri.parse(Environment.getExternalStorageDirectory() + "/LiveWallpapers/" + "source.gif"));
Log.i(TAG, "Путь Uri " + path);
is = getContentResolver().openInputStream(path);

Но что-то все-равно не нравится ему...

02-21 04:43:50.940 2179-2179/com.developer.skyline.livewallpapers I/log: Файл отсутствует по указанному пути /storage/sdcard/LiveWallpapers/source.gif
02-21 04:43:50.970 2179-2179/com.developer.skyline.livewallpapers I/log: Файл в процессе загрузки...
02-21 04:43:51.970 2179-2179/com.developer.skyline.livewallpapers I/log: Файл уже загружен
02-21 04:43:51.970 2179-2179/com.developer.skyline.livewallpapers I/log: Путь Uri /storage/sdcard/LiveWallpapers/source.gif
02-21 04:43:51.970 2179-2179/com.developer.skyline.livewallpapers I/log: Error creating NyanEngine
                                                                         java.io.FileNotFoundException: No content provider: /storage/sdcard/LiveWallpapers/source.gif
                                                                             at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1049)
                                                                             at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:904)
                                                                             at android.content.ContentResolver.openInputStream(ContentResolver.java:629)
                                                                             at com.developer.skyline.livewallpapers.LiveWallpaperService$GifEngine.<init>(LiveWallpaperService.java:84)
                                                                             at com.developer.skyline.livewallpapers.LiveWallpaperService.onCreateEngine(LiveWallpaperService.java:40)
                                                                             at android.service.wallpaper.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:1028)
                                                                             at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:40)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                             at android.os.Looper.loop(Looper.java:136)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:5017)
                                                                             at java.lang.reflect.Method.invokeNative(Native Method)
                                                                             at java.lang.reflect.Method.invoke(Method.java:515)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
                                                                             at dalvik.system.NativeStart.main(Native Method)
Answer 1

В общем удалось решить данную проблему без всякого прослушивания о завершении загрузки таким вот образом:

// скачиваем файл
        public void downloadWallpaper(String url, String name) {
            SharedPreferences preferenceManager = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            String Download_ID = "PREF_DOWNLOAD_ID";
            repeat: for (int z = 0; z < 10; z++) {
                if (is != null) {
                    Log.i(TAG, "Файл загружен успшно");
                    is = getResources().openRawResource(R.raw.nature1);
                    break;
                } else {
                    // проверяем был ли уже загружен файл
                    String path = Environment.getExternalStorageDirectory() + "/";
                    File file = new File(path + "LiveWallpapers/" + name);
                    if (!file.exists()) {
                        Log.i(TAG, "Файл отсутствует");
                        // загружаем файл
                        Uri downloadUri = Uri.parse(url);
                        DownloadManager.Request request = new DownloadManager.Request(downloadUri);
                        // назначаем имя для файла
                        request.setDestinationInExternalPublicDir("LiveWallpapers", name);
                        // сохраняем request id
                        SharedPreferences.Editor PrefEdit = preferenceManager.edit();
                        long id = downloadManager.enqueue(request);
                        PrefEdit.putLong(Download_ID, id);
                        PrefEdit.apply();
                    } else {
                        Log.i(TAG, "Файл уже загружен");
                        // файл уже загружен
                        is = getResources().openRawResource(R.raw.nature1);
                        break;
                    }
                    if (is == null) {
                        try {
                            Log.i(TAG, "Файл в процессе загрузки...");
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {}
                        continue repeat;
                    }
                }
            }
        }

Осталось разобраться как загруженную картинку запихнуть в InputStream? В данный момент картинка берется из каталога raw таким вот образом:

is = getResources().openRawResource(R.raw.nature1);

Мне же нужно будет брать картинку из каталога

File file = new File(path + "LiveWallpapers/" + name);

и добавить ее в поток, кто подскажет как это прописать?

Answer 2

Очередной раз отвечу на свой собственный вопрос, проблема была решена таким вот образом:

downloadWallpaper("https://media.giphy.com/media/rAJfdmusNFDDG/source.gif", "source.gif");
Uri path =(Uri.parse("file://" + Environment.getExternalStorageDirectory() + "/LiveWallpapers/" + "source.gif"));
is = getContentResolver().openInputStream(path);

Как видите для чтения файла необходимо добавить вот этот кусок в начало пути file://

Всем спасибо, все свободны :)

READ ALSO
reflection - Вызов метода с передачей массива

reflection - Вызов метода с передачей массива

Имеется класс вот в таком видеТоесть написать Foo или Bar с указанием импорта не получится, только так

351
Кнопка вверх android

Кнопка вверх android

Есть активность(активность 1), она запускает другую(активность 2), причем передает некие данные влияющие на то что отображает дочерняя активность(активность...

417
Как вывести массив в обратном порядке без использования length

Как вывести массив в обратном порядке без использования length

Создаётся массив целых чиселНужно вывести массив в обратном порядке

635
Нужна библиотека для оплаты в Android

Нужна библиотека для оплаты в Android

Во многих приложениях есть возможность оплачивать деньги через Qiwi, WebMoney, Visa ит

341