【Android】WorkManager(章二)

剩余的三部分
官方文档在这里插入图片描述

案例

实现下载器,并监听下载进度

界面

在这里插入图片描述

定义Worker

在官方案例的前提下,进行完善
在这里插入图片描述

下载download

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下载进度

在这里插入图片描述

授予权限

在这里插入图片描述
在这里插入图片描述

开始工作并监听

在这里插入图片描述

完整代码

MainActivity.java

package com.test.downloadworkerapplication;

import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC;
import static com.test.downloadworkerapplication.MainActivity.MY_LOG_TAG;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.work.Data;
import androidx.work.ForegroundInfo;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

public class DownloadWorker extends Worker {
    public static final String KEY_INPUT_URL = "KEY_INPUT_URL";
    public static final String KEY_OUTPUT_FILE_NAME = "KEY_OUTPUT_FILE_NAME";
    public static final String KEY_FILE_URI = "KEY_FILE_URI";
    public static final String PROGRESS = "PROGRESS";

    private final NotificationManager notificationManager;

    public DownloadWorker(
            @NonNull Context context,
            @NonNull WorkerParameters parameters) {
        super(context, parameters);
        notificationManager = (NotificationManager)
                context.getSystemService(NOTIFICATION_SERVICE);

        Data data = new Data.Builder().putInt(PROGRESS, 0).build();
        setProgressAsync(data);
    }

    @NonNull
    @Override
    public Result doWork() {
        Data inputData = getInputData();
        String inputUrl = inputData.getString(KEY_INPUT_URL);
        String outputFile = inputData.getString(KEY_OUTPUT_FILE_NAME);

        String progress = "Starting Download";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            setForegroundAsync(createForegroundInfo(progress));
        }
        Uri uri = download(inputUrl, outputFile);

        Data progressData2 = new Data.Builder().putInt(PROGRESS, 100).build();
        setProgressAsync(progressData2);

        Data data = new Data.Builder()
                .putString(KEY_FILE_URI, uri.toString())
                .build();
        return Result.success(data);
    }

    private Uri download(String inputUrl, String outputFile) {
        // Downloads a file and updates bytes read
        // Calls setForegroundAsync(createForegroundInfo(myProgress))
        // periodically when it needs to update the ongoing Notification.
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                String myProgress = "downloading...";
                setForegroundAsync(createForegroundInfo(myProgress));
            }

            long fileSize = FileSizeFetcher.getFileSize(inputUrl);
            URL url = new URL(inputUrl);
            InputStream inputStream = url.openStream();

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            int downloadLen = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                downloadLen += len;
                byteArrayOutputStream.write(buffer, 0, len);

                /// 下载进度
                double progress = 1.0 * downloadLen / fileSize;
                Data data = new Data.Builder().putDouble(PROGRESS, progress).build();
                setProgressAsync(data);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            inputStream.close();

            File file = new File(getApplicationContext().getCacheDir(), outputFile + ".pdf");
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(byteArray);
            fileOutputStream.close();

            String absolutePath = file.getAbsolutePath();
            Log.i(MY_LOG_TAG, absolutePath);
            return Uri.fromFile(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.Q)
    @NonNull
    private ForegroundInfo createForegroundInfo(@NonNull String progress) {
        // Build a notification using bytesRead and contentLength
        Context context = getApplicationContext();
        String id = context.getString(R.string.notification_channel_id);
        String title = context.getString(R.string.notification_title);
        String cancel = context.getString(R.string.cancel_download);
        // This PendingIntent can be used to cancel the worker
        PendingIntent intent = WorkManager.getInstance(context)
                .createCancelPendingIntent(getId());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createChannel(id);
        }

        Notification notification = new NotificationCompat.Builder(context, id)
                .setContentTitle(title)
                .setTicker(title)
                .setContentText(progress)
                .setSmallIcon(R.drawable.ic_work_notification)
                .setOngoing(true)
                // Add the cancel action to the notification which can
                // be used to cancel the worker
                .addAction(android.R.drawable.ic_delete, cancel, intent)
                .build();

        int notificationId = 1000;
        return new ForegroundInfo(notificationId, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC);
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private void createChannel(String id) {
        // Create a Notification channel
        NotificationChannel channel = new NotificationChannel(id, "download channel", NotificationManager.IMPORTANCE_NONE);
        notificationManager.createNotificationChannel(channel);
    }
}

DownloadWorker.java

package com.test.downloadworkerapplication;

import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC;
import static com.test.downloadworkerapplication.MainActivity.MY_LOG_TAG;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.work.Data;
import androidx.work.ForegroundInfo;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

public class DownloadWorker extends Worker {
    public static final String KEY_INPUT_URL = "KEY_INPUT_URL";
    public static final String KEY_OUTPUT_FILE_NAME = "KEY_OUTPUT_FILE_NAME";
    public static final String KEY_FILE_URI = "KEY_FILE_URI";
    public static final String PROGRESS = "PROGRESS";

    private final NotificationManager notificationManager;

    public DownloadWorker(
            @NonNull Context context,
            @NonNull WorkerParameters parameters) {
        super(context, parameters);
        notificationManager = (NotificationManager)
                context.getSystemService(NOTIFICATION_SERVICE);

        Data data = new Data.Builder().putInt(PROGRESS, 0).build();
        setProgressAsync(data);
    }

    @NonNull
    @Override
    public Result doWork() {
        Data inputData = getInputData();
        String inputUrl = inputData.getString(KEY_INPUT_URL);
        String outputFile = inputData.getString(KEY_OUTPUT_FILE_NAME);

        String progress = "Starting Download";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            setForegroundAsync(createForegroundInfo(progress));
        }
        Uri uri = download(inputUrl, outputFile);

        Data progressData2 = new Data.Builder().putInt(PROGRESS, 100).build();
        setProgressAsync(progressData2);

        Data data = new Data.Builder()
                .putString(KEY_FILE_URI, uri.toString())
                .build();
        return Result.success(data);
    }

    private Uri download(String inputUrl, String outputFile) {
        // Downloads a file and updates bytes read
        // Calls setForegroundAsync(createForegroundInfo(myProgress))
        // periodically when it needs to update the ongoing Notification.
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                String myProgress = "downloading...";
                setForegroundAsync(createForegroundInfo(myProgress));
            }

            long fileSize = FileSizeFetcher.getFileSize(inputUrl);
            URL url = new URL(inputUrl);
            InputStream inputStream = url.openStream();

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            int downloadLen = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                downloadLen += len;
                byteArrayOutputStream.write(buffer, 0, len);

                /// 下载进度
                double progress = 1.0 * downloadLen / fileSize;
                Data data = new Data.Builder().putDouble(PROGRESS, progress).build();
                setProgressAsync(data);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            inputStream.close();

            File file = new File(getApplicationContext().getCacheDir(), outputFile + ".pdf");
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(byteArray);
            fileOutputStream.close();

            String absolutePath = file.getAbsolutePath();
            Log.i(MY_LOG_TAG, absolutePath);
            return Uri.fromFile(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.Q)
    @NonNull
    private ForegroundInfo createForegroundInfo(@NonNull String progress) {
        // Build a notification using bytesRead and contentLength
        Context context = getApplicationContext();
        String id = context.getString(R.string.notification_channel_id);
        String title = context.getString(R.string.notification_title);
        String cancel = context.getString(R.string.cancel_download);
        // This PendingIntent can be used to cancel the worker
        PendingIntent intent = WorkManager.getInstance(context)
                .createCancelPendingIntent(getId());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createChannel(id);
        }

        Notification notification = new NotificationCompat.Builder(context, id)
                .setContentTitle(title)
                .setTicker(title)
                .setContentText(progress)
                .setSmallIcon(R.drawable.ic_work_notification)
                .setOngoing(true)
                // Add the cancel action to the notification which can
                // be used to cancel the worker
                .addAction(android.R.drawable.ic_delete, cancel, intent)
                .build();

        int notificationId = 1000;
        return new ForegroundInfo(notificationId, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC);
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private void createChannel(String id) {
        // Create a Notification channel
        NotificationChannel channel = new NotificationChannel(id, "download channel", NotificationManager.IMPORTANCE_NONE);
        notificationManager.createNotificationChannel(channel);
    }
}

FileSizeFetch.java

package com.test.downloadworkerapplication;

import java.net.HttpURLConnection;
import java.net.URL;

public class FileSizeFetcher {
    public static long getFileSize(String urlString) {
        long fileSize = 0;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(urlString);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("HEAD"); // 使用HEAD请求以节省带宽
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                String contentLength = connection.getHeaderField("Content-Length");
                fileSize = Long.parseLong(contentLength);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return fileSize;
    }
}

运行

请添加图片描述
在这里插入图片描述

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sheng_er_sheng

打赏是什么?好吃么

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值