剩余的三部分
官方文档
案例
实现下载器,并监听下载进度
界面
定义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;
}
}
运行