Android 下载服务示例:使用 Service 实现文件下载功能
以下是使用 Android Service 实现文件下载功能的完整代码示例:
MainActivity.java
package com.example.sh3;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.Manifest;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private DownloadService.DownloadBinder downloadBinder;
private boolean isContinue = false;
private boolean isDownload = false;
private TextView downloadProgress;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (DownloadService.DownloadBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startDownload = findViewById(R.id.start_download);
Button pauseDownload = findViewById(R.id.pause_download);
Button cancelDownload = findViewById(R.id.cancel_download);
downloadProgress = findViewById(R.id.download_progress);
pauseDownload.setEnabled(true);
cancelDownload.setEnabled(false);
startDownload.setOnClickListener(this);
pauseDownload.setOnClickListener(this);
cancelDownload.setOnClickListener(this);
Intent intent = new Intent(this, DownloadService.class);
startService(intent);//启动服务
bindService(intent,connection,BIND_AUTO_CREATE);//绑定服务
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
}
}
@Override
public void onClick(View v) {
EditText edittext=(EditText) findViewById(R.id.edit);
String url,site;
url=edittext.getText().toString();
// Toast.makeText(this, site, Toast.LENGTH_SHORT).show();
if(url.equals(''))
url= 'https://www.imooc.com/mobile/mukewang.apk';
// editText.setText(url);
if (downloadBinder == null) {
return;
}
Button startDownload = findViewById(R.id.start_download);
Button pauseDownload = findViewById(R.id.pause_download);
Button cancelDownload = findViewById(R.id.cancel_download);
int id = v.getId();
if (id == R.id.start_download) {
downloadBinder.startDownload(url);
isDownload = true;
startDownload.setEnabled(false);
pauseDownload.setEnabled(true);
cancelDownload.setEnabled(true);
downloadProgress.setVisibility(View.VISIBLE); // 显示下载进度
} else if (id == R.id.pause_download) {
if (isDownload) {
if (!isContinue) {
downloadBinder.pauseDownload();
pauseDownload.setText('继续下载');
pauseDownload.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
isContinue = true;
} else {
downloadBinder.startDownload(url);
pauseDownload.setText('暂停下载');
pauseDownload.setBackgroundColor(getResources().getColor(R.color.colorGray));
isContinue = false;
}
} else {
Toast.makeText(this, '请先点击下载', Toast.LENGTH_SHORT).show();
}
} else if (id == R.id.cancel_download) {
downloadBinder.cancelDownload();
startDownload.setEnabled(true);
pauseDownload.setEnabled(true);
cancelDownload.setEnabled(false);
pauseDownload.setBackgroundColor(getResources().getColor(R.color.colorGray));
downloadProgress.setVisibility(View.GONE); // 隐藏下载进度
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 1:
if(grantResults.length>0&&grantResults[0]!=PackageManager.PERMISSION_GRANTED){
Toast.makeText(this,'拒绝权限无法使用程序',Toast.LENGTH_SHORT).show();
finish();
}
break;
default:
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
private void updateDownloadProgress(int progress) {
downloadProgress.setText('下载进度:' + progress + '%');
}
}
DownloadService.java
package com.example.sh3;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class DownloadService extends Service {
private DownloadTask downloadTask;
private String downloadUrl;
private int lastProgress;
private DownloadBinder binder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload(String url) {
if (downloadTask == null) {
downloadUrl = url;
downloadTask = new DownloadTask();
downloadTask.execute(downloadUrl);
}
}
public void pauseDownload() {
if (downloadTask != null) {
downloadTask.pauseDownload();
}
}
public void cancelDownload() {
if (downloadTask != null) {
downloadTask.cancelDownload();
}
}
public void updateDownloadProgress(int progress) {
if (downloadTask != null) {
downloadTask.updateDownloadProgress(progress);
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private class DownloadTask extends AsyncTask<String, Integer, Integer> {
private boolean isPaused = false;
private boolean isCanceled = false;
@Override
protected Integer doInBackground(String... params) {
InputStream is = null;
RandomAccessFile savedFile = null;
File file = null;
try {
long downloadedLength = 0; // 记录已下载的文件长度
String downloadUrl = params[0];
String fileName = downloadUrl.substring(downloadUrl.lastIndexOf('/'));
String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
file = new File(directory + fileName);
if (file.exists()) {
downloadedLength = file.length();
}
long contentLength = getContentLength(downloadUrl);
if (contentLength == 0) {
return 0; // 下载文件长度为0,下载失败
} else if (contentLength == downloadedLength) {
return 1; // 下载文件长度等于已下载的文件长度,下载成功
}
HttpURLConnection connection = (HttpURLConnection) new URL(downloadUrl).openConnection();
connection.setRequestMethod('GET');
connection.setRequestProperty('Range', 'bytes=' + downloadedLength + '-');
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
is = connection.getInputStream();
savedFile = new RandomAccessFile(file, 'rw');
savedFile.seek(downloadedLength);
byte[] b = new byte[1024];
int total = 0;
int len;
while ((len = is.read(b)) != -1) {
if (isPaused) {
return 2; // 下载暂停
} else if (isCanceled) {
file.delete();
return 3; // 下载取消
} else {
total += len;
savedFile.write(b, 0, len);
int progress = (int) ((total + downloadedLength) * 100 / contentLength);
publishProgress(progress);
}
}
connection.disconnect();
return 1; // 下载成功
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (savedFile != null) {
savedFile.close();
}
if (isCanceled && file != null) {
file.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return 0; // 下载失败
}
@Override
protected void onProgressUpdate(Integer... values) {
int progress = values[0];
if (progress > lastProgress) {
Log.d('DownloadService', 'Download progress: ' + progress + '%');
lastProgress = progress;
}
}
@Override
protected void onPostExecute(Integer status) {
switch (status) {
case 0:
Log.d('DownloadService', 'Download failed');
break;
case 1:
Log.d('DownloadService', 'Download success');
break;
case 2:
Log.d('DownloadService', 'Download paused');
break;
case 3:
Log.d('DownloadService', 'Download canceled');
break;
default:
break;
}
}
public void pauseDownload() {
isPaused = true;
}
public void cancelDownload() {
isCanceled = true;
}
public void updateDownloadProgress(int progress) {
publishProgress(progress);
}
private long getContentLength(String downloadUrl) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(downloadUrl).openConnection();
connection.setRequestMethod('GET');
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.connect();
if (connection.getResponseCode() == 200) {
return connection.getContentLength();
}
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}
}
activity_main.xml
<RelativeLayout xmlns:android='http://schemas.android.com/apk/res/android'
xmlns:tools='http://schemas.android.com/tools'
android:layout_width='match_parent'
android:layout_height='match_parent'
android:paddingLeft='16dp'
android:paddingTop='16dp'
android:paddingRight='16dp'
android:paddingBottom='16dp'
tools:context='.MainActivity'>
<EditText
android:id='@+id/edit'
android:layout_width='match_parent'
android:layout_height='wrap_content'
android:hint='请输入下载链接' />
<Button
android:id='@+id/start_download'
android:layout_width='wrap_content'
android:layout_height='wrap_content'
android:text='开始下载' />
<Button
android:id='@+id/pause_download'
android:layout_width='wrap_content'
android:layout_height='wrap_content'
android:layout_below='@+id/start_download'
android:text='暂停下载' />
<Button
android:id='@+id/cancel_download'
android:layout_width='wrap_content'
android:layout_height='wrap_content'
android:layout_below='@+id/pause_download'
android:text='取消下载' />
<TextView
android:id='@+id/download_progress'
android:layout_width='wrap_content'
android:layout_height='wrap_content'
android:layout_below='@+id/cancel_download'
android:text='下载进度:0%' />
</RelativeLayout>
代码说明
-
MainActivity
- 申请写外部存储权限
- 创建一个 ServiceConnection 对象用于绑定服务
- 创建三个按钮:开始下载、暂停下载和取消下载
- 设置按钮点击监听器,分别调用服务中的对应方法
-
DownloadService
- 创建一个 DownloadBinder 类,用于暴露服务的方法给 Activity
- 创建一个 DownloadTask 类,继承自 AsyncTask,用于执行下载操作
- 在 DownloadTask 中实现下载逻辑,包括:
- 获取下载链接和文件名
- 创建文件并写入数据
- 计算下载进度并更新 UI
- 处理下载暂停、取消等操作
-
activity_main.xml
- 包含一个 EditText 用于输入下载链接
- 包含三个 Button 用于控制下载
- 包含一个 TextView 用于显示下载进度
使用方法
- 在 EditText 中输入要下载的链接
- 点击 '开始下载' 按钮开始下载
- 点击 '暂停下载' 按钮暂停下载
- 点击 '继续下载' 按钮继续下载
- 点击 '取消下载' 按钮取消下载
注意
- 需要在 AndroidManifest.xml 中声明 DownloadService 和相应的权限
- 需要在代码中添加对下载进度和状态的处理逻辑
- 下载文件存储在手机的 /storage/emulated/0/Download 目录下
原文地址: https://www.cveoy.top/t/topic/Nh7 著作权归作者所有。请勿转载和采集!