android 服务的最佳实践代码解析

DownloadTask类 //完成下载的模块
package com.example.administrator.servicebestpractice;

import android.app.DownloadManager;
import android.content.Intent;
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 Administrator on 2018/10/29 0029.
 */
//让此模块继承AsyncTask,实现在子线程中执软件的下载操作
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;
    // 根据 isCanceled ,isPaused来判断是否继续下载
    private boolean isCanceled =false;
    private boolean isPaused=false;
    private int lastProgress;
    //构造一个含有listener的下载任务
    public DownloadTask(DownloadListener listener) {
        this.listener=listener;
    }
    //取得要下载文件的长度
    private long getContentLength(String downloadUrl) throws IOException
    {
        OkHttpClient client = new OkHttpClient();
        //设置request
        Request request = new Request.Builder()
                            .url(downloadUrl)
                            .build();
        Response response = client.newCall(request).execute();
        //根据response是否为空,若不为则返回正确的长度,若为则返回长度为0
        if(response!=null&&response.isSuccessful())
        {
            Long contentLength = response.body().contentLength();
            response.body().close();
            return contentLength;
        }
return 0;
    }
    @Override
    //AsyncTask的执行具体操作的方法,在这个方法中进行下载操作
    protected Integer doInBackground(String... params)  { 
        InputStream is =null;
        RandomAccessFile savaedFile =null;

            File file = null;
        try {
            long downloadedLength = 0;
            String downloadUrl = params[0];//根据传入的参数取得url
            String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));//拆分url取得文件名
            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)//若为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();//取得response对象的字节流
                savaedFile = new RandomAccessFile(file, "rw");
                savaedFile.seek(downloadedLength);
                byte[] b = new byte[1024];
                int total = 0;
                int len;
                while ((len = is.read(b)) != -1) {
                    if (isCanceled)
                        return Type_CANCELED;
                    if (isPaused)
                        return Type_PAUSED;
                    else
                        total += len;
                    savaedFile.write(b, 0, len);
                    int progress = (int) ((total + downloadedLength) * 100 / contentLength);
                    //调用这个方法去执行onProgressUpdates(),更行前台的服务的下载进度
                    publishProgress(progress);
                }
            }
            response.body().close();
            return TYPE_SUCCESS;

        } catch (IOException e) {
            e.printStackTrace();
        }finally {


                try {
                    if(is!=null)
                    is.close();
                    if(savaedFile!=null)
                        savaedFile.close();
                    if(isCanceled&&file !=null)
                        file.delete();

                } catch (IOException 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 integer) {
        switch (integer) {
            case TYPE_SUCCESS:
                listener.onSuccess();
                break;
            case  Type_CANCELED:
                listener.onCanceled();
                break;
            case Type_FAILED :
                listener.onFailed();
                break;
            case  Type_PAUSED :
                listener.onPaused();
                break;
            default:break;
        }
    }
    //修改下载状态
    public void pauseDownload()
    {
        isPaused=true;
    }
    public void cancelDownload()
    {
        isCanceled=true;
    }


}

DownloadService类
package com.example.administrator.servicebestpractice;


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 DownlsService {
  
     private  DownloadTask downloadTask;
    private String downloadUrl;
    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.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));
        builder.setContentIntent(pi);
        builder.setContentTitle(title);
        if(progress>=0)
        {
            builder.setContentText(progress+"%");
            builder.setProgress(100,progress,false);
        }
        return builder.build();

    }
    private  DownloadListener listener= new DownloadListener() {
        @Override
        public void onProgress(int progress) {
            getNotificationManager().notify(1,getNotification("Downloading......",progress));

        }

        @Override
        public void onSuccess() {
            downloadTask=null;
            stopForeground(true);
            getNotificationManager().notify(1,getNotification("Downloading.......",-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();
        }

    };
    //在活动中操作的方法
    class DownloadBinder extends Binder{
    	开始下载
        public void startDownload(String url)
        {		若下载任务为空
            if(downloadTask==null)
            {
                downloadUrl=url;
                //新建下载任务
                downloadTask = new DownloadTask(listener);
                //我的理解是执行doInBackGround方法
                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();
            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  DownloadBinder mBinder= new DownloadBinder();
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mBinder;
    }
}
MainActivity类
package com.example.administrator.servicebestpractice;

import android.Manifest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
	//声明一个服务中的Binder对象
    private DownloadService.DownloadBinder downloadBinder;
	
    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downloadBinder = (DownloadService.DownloadBinder) service;
        }

    };

    @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, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);
    }

}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值