1.新建一个Service:
public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onCreate(){ super.onCreate(); } @Override public int onStartCommand(Intent intent,int flags,int startId) { return super.onStartCommand(intent,flags,startId); } @Override public void onDestroy() { super.onDestroy(); } }2.启动服务:
Intent startIntent = new Intent(this,MyService.class); startService(startIntent);3.停止服务:
Intent stopIntent = new Intent(this,MyService.class); stopService(stopIntent);
4.与活动绑定:
4.1 Service中添加如下:
private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder { public void startDownload() { Log.d("MyService","start Download"); } public int getProgress() { Log.d("MyService","getProgress"); return 0; } }
4.2 修改MainActivity:
private MyService.DownloadBinder downloadBinder; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { downloadBinder = (MyService.DownloadBinder) service; downloadBinder.startDownload(); downloadBinder.getProgress(); } @Override public void onServiceDisconnected(ComponentName name) { } };
Intent bindIntent = new Intent(this,MyService.class); bindService(bindIntent,mServiceConnection,BIND_AUTO_CREATE);5.解除绑定:
unbindService(mServiceConnection);
6.前台服务,修改MyService中onCreate方法:
public void onCreate(){ super.onCreate(); Intent intent = new Intent(this,MainActivity.class); PendingIntent pi = PendingIntent.getActivity(this,0,intent,0); Notification notification = new NotificationCompat.Builder(this) .setContentTitle("title") .setContentText("haha") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(pi) .build(); startForeground(1,notification); }
7.IntentService解决了异步和不能自动停止问题,不要忘记manifest文件中声明:
public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { Log.d("MyIntentService","Thread id is " + Thread.currentThread().getId()); } @Override public void onDestroy(){ super.onDestroy(); } }
8.下载示例:
8.1 定义一个回调接口:
public interface DownloadListener { void onProgress(int progress); void onSuccess(); void onFailed(); void onPaused(); void onCanceled(); }
8.2 实现下载功能:
public class DownloadTask extends AsyncTask<String,Integer,Integer> { public static final int TYPE_SUCCESS = 0; public static final int TYPE_FAILED = 1; public static final int TYPE_PAUSED = 2; public static final int TYPE_CANCELED = 3; private DownloadListener listener; private boolean isCanceled = false; private boolean isPaused = false; private int lastProgress; public DownloadTask(DownloadListener listener) { this.listener = listener; } @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 TYPE_FAILED; } else if (contentLength == downloadedLength) { return TYPE_SUCCESS; } OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .addHeader("RANGE","bytes=" + downloadedLength + "-") .url(downloadUrl) .build(); Response response = client.newCall(request).execute(); if (response != null) { is = response.body().byteStream(); 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 (isCanceled) { return TYPE_CANCELED; } else if (isPaused) { return TYPE_PAUSED; } else { total += len; savedFile.write(b,0,len); int progress = (int) ((total + downloadedLength) * 100 / contentLength); publishProgress(progress); } } response.body().close(); return TYPE_SUCCESS; } } 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 TYPE_FAILED; } @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_FAILED: listener.onFailed(); break; case TYPE_PAUSED: listener.onPaused(); break; case TYPE_CANCELED: listener.onCanceled(); break; default: break; } } public void pauseDownload() { isPaused = true; } public void cancelDownload() { isCanceled = true; } private long getContentLength(String downloadUrl) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(downloadUrl).build(); Response response = client.newCall(request).execute(); if (response != null && response.isSuccessful()) { long contentLength = response.body().contentLength(); response.close(); return contentLength; } return 0; } }
8.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,getNotification("Download...",progress)); } @Override public void onSuccess() { downloadTask = null; stopForeground(true); getNotificationManager().notify(1,getNotification("Download Success",-1)); Toast.makeText(DownloadService.this,"Download Success",Toast.LENGTH_SHORT).show(); } @Override public void onFailed() { downloadTask = null; stopForeground(true); getNotificationManager().notify(1,getNotification("Download Failed",-1)); Toast.makeText(DownloadService.this,"Download Failed",Toast.LENGTH_SHORT).show(); } @Override public void onPaused() { 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(); } }; private DownloadBinder mBinder = new DownloadBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } class DownloadBinder extends Binder { public void startDownload(String url) { if (downloadTask == null) { downloadUrl = url; downloadTask = new DownloadTask(listener); downloadTask.execute(downloadUrl); startForeground(1, getNotification("Downloading...", 0)); Toast.makeText(DownloadService.this, "Downloading...", Toast.LENGTH_SHORT).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(); } } } } private NotificationManager getNotificationManager() { return (NotificationManager) getSystemService(NOTIFICATION_SERVICE); } private Notification getNotification(String title, int progress) { Intent intent = new Intent(this,MainActivity.class); PendingIntent pi = PendingIntent.getActivity(this,0,intent,0); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentIntent(pi); builder.setContentTitle(title); if (progress > 0) { builder.setContentText(progress + "%"); builder.setProgress(100,progress,false); } return builder.build(); } }8.4 修改MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private DownloadService.DownloadBinder downloadBinder; 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 = (Button)findViewById(R.id.start_download); Button pauseDownload = (Button) findViewById(R.id.pause_download); Button cancelDownload = (Button) findViewById(R.id.cancel_download); 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) { if (downloadBinder == null) { return; } switch (v.getId()) { case R.id.start_download: String url = "https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe"; downloadBinder.startDownload(url); break; case R.id.pause_download: downloadBinder.pauseDownload(); break; case R.id.cancel_download: downloadBinder.cancelDownload(); break; default: break; } } @Override public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) { switch (requestCode) { case 1: if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this,"denied will use this app",Toast.LENGTH_SHORT).show(); finish(); } break; default: } } @Override protected void onDestroy() { super.onDestroy(); unbindService(connection); } }8.5 在manifest中声明网络和存储权限
private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder { public void startDownload() { Log.d("MyService","start Download"); } public int getProgress() { Log.d("MyService","getProgress"); return 0; } }