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