android中service和Asnyctask没有写过综合应用,最近也在看东西没有段时间发过博文了。今天发表一个综合应用记录,代码是来源于郭神的第一行代码,自己进行分析,算事研读吧。要知道的都在注释里。这是一个下载文件的demo并且在系统通知栏显示。
activity:
package com.example.zobject.http; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.IBinder; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.jar.Manifest; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private MyService.DownLoadBinder downLoadBinder;//首先获得DownLoadBinder的实例 private ServiceConnection connection =new ServiceConnection() { //实现ServiceConnection内部类就可以在activity中调用 service中的方法了 @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { downLoadBinder= (MyService.DownLoadBinder) iBinder; } @Override public void onServiceDisconnected(ComponentName componentName) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.strat); Button button1 = (Button) findViewById(R.id.pause); Button button2 = (Button) findViewById(R.id.cancel); button.setOnClickListener(this); button1.setOnClickListener(this); button2.setOnClickListener(this); Intent intent =new Intent(this,MyService.class); startService(intent);//启动服务 bindService(intent,connection,BIND_AUTO_CREATE);//绑定服务 if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){//权限检查 ActivityCompat.requestPermissions(MainActivity.this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},1); } } @Override public void onClick(View view) {//三种方法的调用 if (downLoadBinder==null){ return; } switch (view.getId()){ case R.id.strat: String url="https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe"; downLoadBinder.startDownload(url); break; case R.id.pause: downLoadBinder.PauseDownload(); break; case R.id.cancel: downLoadBinder.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,"ju",Toast.LENGTH_LONG); } break; default: } } @Override protected void onDestroy() {//在activity销毁的时候解绑service 因为在service还在运行会造成内存泄露 super.onDestroy(); unbindService(connection); } }
listener接口
public interface DownLoadListener { // service和底层的通行接口 void onProgess(int progess); void Success(); void Failed(); void onPaused(); void onCanceled(); }service层:package com.example.zobject.http; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Binder; import android.os.Environment; import android.os.IBinder; import android.support.v4.app.NotificationCompat; import android.widget.Toast; import java.io.File; public class MyService extends Service { private String downloadUrl; private DownLoad downLoad; private DownLoadListener downLoadListener = new DownLoadListener() {//实现定义的接口 @Override public void onProgess(int progess) { getNoti().notify(1, notification("Download.......", progess)); } @Override public void Success() { downLoad = null; stopForeground(true);//把进程放到前台进行避免被杀掉 getNoti().notify(1, notification("DownSuccess", -1)); Toast.makeText(MyService.this, "Successs", Toast.LENGTH_SHORT).show(); } @Override public void Failed() { downLoad = null; stopForeground(true); getNoti().notify(1, notification("DownloadFailed", -1)); Toast.makeText(MyService.this, "Failed", Toast.LENGTH_LONG).show(); } @Override public void onPaused() { downLoad = null; Toast.makeText(MyService.this, "Pause", Toast.LENGTH_LONG).show(); } @Override public void onCanceled() { downLoad = null; stopForeground(true); Toast.makeText(MyService.this, "Cancelded", Toast.LENGTH_LONG).show(); } }; private NotificationManager getNoti() {//进行进度条的显示和定义 return (NotificationManager) getSystemService(NOTIFICATION_SERVICE); } private Notification notification(String title, int progess) { 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.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)); builder.setContentIntent(pendingIntent); builder.setContentTitle(title); if (progess > 0) { builder.setContentText(progess + "%"); builder.setProgress(100, progess, false); } return builder.build(); } private DownLoadBinder downLoadBind = new DownLoadBinder(); @Override public IBinder onBind(Intent intent) { return downLoadBind; } class DownLoadBinder extends Binder {//继承binder 供上层进行调用 public void startDownload(String url) { if (downLoad == null) { downloadUrl = url; downLoad = new DownLoad(downLoadListener);//绑定一个listener给底层方便调用 startForeground(1, notification("download.......", 0)); downLoad.execute(downloadUrl);//在这开启ansyctask的异步调用 Toast.makeText(MyService.this, "startdownload........", Toast.LENGTH_LONG).show(); } } public void PauseDownload() { if (downLoad != null) { downLoad.pauseDown(); } } public void cancelDownload() { if (downLoad != null) {// 这个是下载直接停止 downLoad.canelDown(); } else { if (downloadUrl != null) {// 这部分是暂停后取消 String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/")); String dectoty = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); File file = new File(dectoty + fileName); if (file.exists()) { file.exists(); } getNoti().cancel(1); stopForeground(true); Toast.makeText(MyService.this, "Canceled", Toast.LENGTH_LONG).show(); } } } } }Asyn:package com.example.zobject.http; import android.os.AsyncTask; import android.os.Environment; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** * Created by zobject on 2017/1/11. */ public class DownLoad extends AsyncTask<String, Integer, Integer> {///异步处理接受三个参数第一个是url地址,第二个和第三个进度反馈用int型 public static final int SUCCESS = 0; public static final int FAILED = 1; public static final int PAUSEE = 2; public static final int CANCELED = 3; private DownLoadListener downLoadListener; private boolean isCancelde = false; private boolean isPause = false; private int lastProgess; public DownLoad(DownLoadListener listener) { this.downLoadListener = listener; }//接受一个接受进来 @Override protected Integer doInBackground(String... strings) {//接受 第一个参数进来 InputStream inputStream = null; RandomAccessFile saveFile = null;//随机存储方法 File file = null; try { long DownLoadLength = 0; String downLoadUrl = strings[0]; String fileName = downLoadUrl.substring(downLoadUrl.lastIndexOf("/"));//通过路径获得到文件的名字 String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();//获取到downloadd的文件路径 file = new File(directory + fileName);//文件的路径为file if (file.exists()) { DownLoadLength = file.length();//判读路径是否存在,下载的长度文件的文件的当前长度,这个段代码用来读取当前的下载数目,用来实现暂停后继续下载 } long ContentLength = getContentLength(downLoadUrl);//求的文件的总的长度 if (ContentLength == 0) { return FAILED; } else if (ContentLength == DownLoadLength) { return SUCCESS; } OkHttpClient okhettp = new OkHttpClient();//这里是继续下载的操作 Request requset = new Request.Builder().addHeader("RANGE", "bytes" + DownLoadLength + "-").url(downLoadUrl).build();//跳过下载过的文件 Response response = okhettp.newCall(requset).execute(); if (response != null) {//这段就是存储下载好的文件了,如果返回的不是空值就进行存储 inputStream = response.body().byteStream(); saveFile = new RandomAccessFile(file, "rw"); saveFile.seek(DownLoadLength); byte[] b = new byte[1024]; int total = 0; int len; while ((len = inputStream.read()) != -1) { if (isCancelde) { return CANCELED;//如果前台进行了取消操作就返回取消的标识符 } else if (isPause) { return PAUSEE;//如果前台返进行了暂停就返回暂停的标识符 } else { total += len; saveFile.write(b, 0, len); int progess = (int) ((total + DownLoadLength) * 100 / ContentLength);//这里就是下载进度的实时反馈 publishProgress(progess);//切换到主线程进行京进度条的加载 } } response.body().close();//下载完成 return SUCCESS; } } catch (IOException e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } if (saveFile != null) { saveFile.close(); } if (isCancelde && file != null) { file.delete();//如果取消了下载,就删除文件 } } catch (Exception e) { e.printStackTrace(); } } return FAILED; } @Override protected void onProgressUpdate(Integer... values) { int progress = values[0]; if (progress > lastProgess) { downLoadListener.onProgess(progress);//实时的反馈下砸进度 lastProgess = progress; } } @Override protected void onPostExecute(Integer integer) {//四种结果的反馈结果提供给借口进行回掉 switch (integer) { case SUCCESS: downLoadListener.Success(); break; case FAILED: downLoadListener.Failed(); break; case PAUSEE: downLoadListener.onPaused(); break; case CANCELED: downLoadListener.onCanceled(); break; default: break; } } public void pauseDown() { isPause = true; }//提供给服务层进行调用让本层进行一定的操作 public void canelDown() { isCancelde = true; } private long getContentLength(String downLoadUrl) throws IOException {//返回文件的长度显示计算的百分比 OkHttpClient client = new OkHttpClient(); Request requset = new Request.Builder().url(downLoadUrl).build(); Response res = client.newCall(requset).execute(); if (res != null && res.isSuccessful()) { long reslength = res.body().contentLength(); res.close(); return reslength; } return 0; } }效果图:
x