Скачивание файла в Service/IntentService и отображение процесса скачивания

213
12 марта 2019, 02:00

У меня есть плеер, в котором можно скачивать песни. Для скачивания на данный момент я использую IntentService, который выглядит вот так:

public class DownloadService extends IntentService implements ApiResponse.ApiFailureListener {
    public static final String ACTION_DOWNLOAD_STARTED = "com.example.uncolor.action.DOWNLOAD_STARTED";
    public static final String ACTION_DOWNLOAD_COMPLETED = "com.example.uncolor.action.DOWNLOAD_COMPLETED";
    public static final String ACTION_DOWNLOAD_FAILURE = "com.example.uncolor.action.DOWNLOAD_FAILURE";
    public static final String ARG_MUSIC = "music";
    public DownloadService() {
        super("Download Service");
    }
    private BaseMusic music;
    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        App.Log("onStart service");
        super.onStart(intent, startId);
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        App.Log("onHandleIntent service");
        Bundle extras = intent.getExtras();
        if (extras != null) {
            music = extras.getParcelable("music");
            if(music != null) {
                  App.Log("download url: " + music.getDownload());
            }
        }
        if(music == null){
            App.Log("music null");
            sendIntent(ACTION_DOWNLOAD_FAILURE);
            return;
        }
        String artist = "";
        String title = "";
        if(music.getArtist() != null){
            artist = music.getArtist();
        }
        if(music.getTitle() != null){
            title = music.getTitle();
        }
        File outputFile = new File(Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
                        artist + " - " + title + ".mp3");
        String uriFromFile = Uri.fromFile(outputFile).toString();
        App.Log("Uri from file: " + uriFromFile);
        initDownload();
    }
    private void initDownload() {
        App.Log("init download");
        onDownloadStarted(ACTION_DOWNLOAD_STARTED);
        Api.getSource().downloadFile(music.getDownload()).enqueue(ApiResponse
                .getCallback(getDownloadCallback(), this));
    }
    private ApiResponse.ApiResponseListener<ResponseBody> getDownloadCallback() {
        return new ApiResponse.ApiResponseListener<ResponseBody>() {
            @Override
            public void onResponse(ResponseBody result) {
                try {
                    downloadFile(result);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
    }
    private void downloadFile(ResponseBody body) throws IOException {
        App.Log("download file");
        int count;
        byte data[] = new byte[1024 * 4];
        long fileSize = body.contentLength();
        InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
        String artist = "";
        String title = "";
        if(music.getArtist() != null){
            artist = music.getArtist();
        }
        if(music.getTitle() != null){
            title = music.getTitle();
        }
        File outputFile =
                new File(Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
                        artist + " - " + title + ".mp3");
        OutputStream output = new FileOutputStream(outputFile);
        long total = 0;
        long startTime = System.currentTimeMillis();
        int timeCount = 1;
        while ((count = bis.read(data)) != -1) {
            total += count;
            int totalFileSize = (int) (fileSize / (Math.pow(1024, 2)));
            double current = Math.round(total / (Math.pow(1024, 2)));
            int progress = (int) ((total * 100) / fileSize);
            long currentTime = System.currentTimeMillis() - startTime;
            Download download = new Download();
            download.setTotalFileSize(totalFileSize);
            if (currentTime > 1000 * timeCount) {
                download.setCurrentFileSize((int) current);
                download.setProgress(progress);
                timeCount++;
            }
            output.write(data, 0, count);
        }
        App.Log("output path: " + outputFile.getAbsolutePath());
        music.setLocalPath(outputFile.getAbsolutePath());
        onDownloadComplete(ACTION_DOWNLOAD_COMPLETED);
        output.flush();
        output.close();
        bis.close();
        App.Log("download complete");
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        App.Log("onDestroy Download service");
    }

    private void sendIntent(String action) {
        App.Log("send intent");
        Intent intent = new Intent();
        intent.setAction(action);
        intent.putExtra(ARG_MUSIC, music);
        sendBroadcast(intent);
    }
    private void onDownloadComplete(String action) {
        App.Log("onDownloadComplete");
        sendIntent(action);
    }
    private void onDownloadStarted(String action) {
        App.Log("onDownloadStarted");
        sendIntent(action);
    }
    @Override
    public void onTaskRemoved(Intent rootIntent) {
    }
    @Override
    public void onFailure(int code, String message) {
        App.Log("Download failure");
        sendIntent(ACTION_DOWNLOAD_FAILURE);
    }
}

Проблема данного класса в том, что я не могу узнать прогресс скачивания во время загрузки(1%, 2%...и так далее) и отобразить его в Activity. Хотелось бы узнать, каким способом лучше скачивать файлы. Может лучше будет использовать обычный Service? Нужно как то формировать очередь скачиваний... Заранее благодарю за помощь!

Answer 1

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

Получить DownloadManager можно:

((DownloadManager) context.getSystemService(DOWNLOAD_SERVICE))

Пример использования (request - твой запрос):

Request request = DownloadManager.Request(Uri.parse("твой URL"))
            //Устанавливаем уведомление, которое будет отображать процесс загрузки        
            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
            .setTitle("твое название файла")
            //папка назначения куда скачается файл
            .setDestinationInExternalFilesDir(
                context,
                Environment.DIRECTORY_DOWNLOADS, fileName + fileExtension
            )
        //Складываем твой запрос в очередь для скачивания
        downloadManager.enqueue(request)
READ ALSO
MySQL Could not create connection to database server

MySQL Could not create connection to database server

До перезагрузки компьютера всё работало отличноПосле перезагрузки netbeans пишет ошибку при компиляции проекта

353
Передача запроса сервлету и jsp

Передача запроса сервлету и jsp

Что-то вообще заплутался,ребятаПомогите,пожалуйста

212
Как отсортировать TreeSet по выбранному критерию при помощи интерфейса Comparable&lt;T&gt;?

Как отсортировать TreeSet по выбранному критерию при помощи интерфейса Comparable<T>?

Должно отсортировать по цене, но пишет вроде бы то, что обычно пишет, если Comparable не использовать, если я правильно понялПовторял за примером...

192
Ввод символов с клавиатуры

Ввод символов с клавиатуры

Тренируюсь и сделал вот такой небольшой пример:

219