1.下载回调 成功、失败、暂停、取消、进度条
public interface DownloadListener { void onProgress(int progress); void onSuccess(); void onFail(); void onPause(); void onCanceled();}
2.异步下载,断点下载
public class DownloadTask extends AsyncTask<String, Integer, Integer> { public static final int TYPE_SUCCESS = 1; public static final int TYPE_FAIL = 2; public static final int TYPE_PAUSE = 3; public static final int TYPE_CANCELED = 4; private DownloadListener listener; private boolean isCanceled = false; private boolean isPause = false; private int lastProgress; public DownloadTask(DownloadListener listener) { this.listener = listener; } @Override protected Integer doInBackground(String... strings) { return downLoad(strings[0]); } @Override protected void onProgressUpdate(Integer... values) { int progress = values[0]; if (progress > lastProgress) { listener.onProgress(progress); lastProgress = progress; } } @Override protected void onPostExecute(Integer status) { switch (status) { case TYPE_SUCCESS: listener.onSuccess(); ; break; case TYPE_FAIL: listener.onFail(); break; case TYPE_PAUSE: listener.onPause(); break; case TYPE_CANCELED: listener.onCanceled(); break; } } public void pauseDownload() { isPause = true; } public void cancelDownload() { isCanceled = true; } private int downLoad(String url) { long downloadLength = 0; RandomAccessFile saveFiel = null; File file = null; InputStream is = null; String fileName = url.substring(url.lastIndexOf("/")); String director = Environment.getExternalStoragePublicDirectory(Environment .DIRECTORY_DOWNLOADS).getPath(); file = new File(director + fileName); if (file.exists()) { downloadLength = file.length(); } long contentLength = getContentLength(url); if (contentLength == 0) { return TYPE_FAIL; } else if (contentLength == downloadLength) { return TYPE_SUCCESS; } OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().addHeader("RANGE", "bytes=" + downloadLength + "-").url(url).build(); Response response = null; try { response = client.newCall(request).execute(); if (response != null) { is = response.body().byteStream(); saveFiel = new RandomAccessFile(file, "rw"); saveFiel.seek(downloadLength); byte[] b = new byte[1024]; int total = 0; int len; while ((len = is.read(b)) != -1) { if (isCanceled) { return TYPE_CANCELED; } else if (isPause) { return TYPE_PAUSE; } else { total += len; saveFiel.write(b, 0, len); int progress = (int) ((total + downloadLength) * 100 / contentLength); publishProgress(progress); } } response.body().close(); return TYPE_SUCCESS; } } catch (Exception e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } if (saveFiel != null) { saveFiel.close(); } if (isCanceled && file != null) { file.delete(); } } catch (IOException e) { e.printStackTrace(); } } return TYPE_FAIL; } public long getContentLength(String url) { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); try { Response response = client.newCall(request).execute(); if (response != null && response.isSuccessful()) { long currentLength = response.body().contentLength(); response.close(); return currentLength; } } catch (IOException e) { e.printStackTrace(); } return 0; } }3.起服务,后台下载public class DownloadService extends Service { private DownloadTask downloadTask; private String downloadUrl; private DownloadListener listener = new DownloadListener() { @Override public void onProgress(int progress) { getNotificationManager().notify(1, getNotication("DownLoading...", progress)); } @Override public void onSuccess() { downloadTask = null; stopForeground(true); getNotificationManager().notify(1, getNotication("Download Success", -1)); Toast.makeText(DownloadService.this, "Download Success", Toast.LENGTH_SHORT).show(); } @Override public void onFail() { downloadTask = null; stopForeground(true); getNotificationManager().notify(1, getNotication("Download Failed", -1)); Toast.makeText(DownloadService.this, "Download Fail", Toast.LENGTH_SHORT).show(); } @Override public void onPause() { downloadTask = null; Toast.makeText(DownloadService.this, "Paused", Toast.LENGTH_SHORT).show(); } @Override public void onCanceled() { downloadTask = null; stopForeground(true); Toast.makeText(DownloadService.this, "Canceled", Toast.LENGTH_SHORT).show(); } }; public DownloadService() { } private DownloadBind mBind = new DownloadBind(); class DownloadBind extends Binder { public void startDownload(String url) { if (downloadTask == null) { downloadUrl = url; downloadTask = new DownloadTask(listener); downloadTask.execute(url); startForeground(1, getNotication("Downloading...", 0)); Toast.makeText(DownloadService.this, "Downloading...", 1).show(); } } public void pauseDownload() { if (downloadTask != null) { downloadTask.pauseDownload(); } } public void cancelDownload() { if (downloadTask != null) { downloadTask.cancelDownload(); } else { if (downloadUrl != null) { String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/")); String directory = Environment.getExternalStoragePublicDirectory(Environment .DIRECTORY_DOWNLOADS).getPath(); File file = new File(directory + fileName); if (file.exists()) { file.delete(); } getNotificationManager().cancel(1); stopForeground(true); Toast.makeText(DownloadService.this, "Canceled", Toast.LENGTH_SHORT).show(); } } } } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return mBind; } private NotificationManager getNotificationManager() { return (NotificationManager) getSystemService(NOTIFICATION_SERVICE); } private Notification getNotication(String title, int progress) { Intent intent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentIntent(pendingIntent); builder.setContentTitle(title); if (progress > 0) { builder.setContentText(progress + "%"); builder.setProgress(100, progress, false); } return builder.build(); } }4.封装接口,便于操作public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(savedInstanceState); setClick(); startActivityIntent(); } protected abstract void initView(Bundle savedInstanceState); protected abstract void setClick(); protected abstract void startActivityIntent(); }5.MainActivty 启动Servicepublic class MainActivity extends BaseActivity implements View.OnClickListener { private Button start, pause, cancel; private DownloadService.DownloadBind bind; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = (DownloadService.DownloadBind) service; } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override public void initView(Bundle bundle) { setContentView(R.layout.activity_main); start = (Button) findViewById(R.id.start); pause = (Button) findViewById(R.id.pause); cancel = (Button) findViewById(R.id.cancel); } @Override public void setClick() { start.setOnClickListener(this); pause.setOnClickListener(this); cancel.setOnClickListener(this); } @Override public void startActivityIntent() { 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(this, new String[]{Manifest.permission .WRITE_EXTERNAL_STORAGE}, 1); } } @Override public void onClick(View v) { if (bind == null) { return; } switch (v.getId()) { case R.id.start: String url = "https://raw.githubusercontent" + ".com/guolindev/eclipse/master/eclipse-inst-win64.exe"; bind.startDownload(url); break; case R.id.pause: bind.pauseDownload(); break; case R.id.cancel: bind.cancelDownload(); break; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case 1: if (grantResults.length > 0 && grantResults[0] != PackageManager .PERMISSION_GRANTED) { Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show(); finish(); } break; } } @Override protected void onDestroy() { super.onDestroy(); unbindService(connection); } }源码下载地址:https://github.com/hushendian/Okhttp-AsyncTask-service-.git