Android实现版本更新通知栏下载

来源:互联网 发布:网络拓扑绘制开源工具 编辑:程序博客网 时间:2024/05/27 03:28

一、概述

本篇文章主要实现在应用内发现新版本,用户点击下载apk,同时在通知栏下实现下载进度更新,下载完成后自动弹出安装窗口等等功能,这是apk常见的功能模块!代码亲测有效。
实现效果图如下:
这里写图片描述

二、具体实现

1.下载监听回调接口UpdateDownloadListener.java

package com.czhappy.appupdate.utils;/** * Description: * User: chenzheng * Date: 2016/12/14 0014 * Time: 16:23 */public interface UpdateDownloadListener {    public void onStarted();    public void onProgressChanged(int progress, String downloadUrl);    public void onFinished(float completeSize, String downloadUrl);    public void onFailure();}

2.文件下载及线程通信UpdateDownloadRequest.java

package com.czhappy.appupdate.utils;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.Log;import java.io.IOException;import java.io.InputStream;import java.io.InterruptedIOException;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import java.text.DecimalFormat;/** * Description:文件下载及线程间通信 * User: chenzheng * Date: 2016/12/14 0014 * Time: 16:24 */public class UpdateDownloadRequest implements Runnable{    private String downloadUrl;    private String localFilePath;    private UpdateDownloadListener listener;    private boolean isDownloading = false;    private long currentLength;    private DownloadResponseHandler downloadResponseHandler;    public UpdateDownloadRequest(String downloadUrl, String localFilePath, UpdateDownloadListener listener){        this.downloadUrl = downloadUrl;        this.localFilePath = localFilePath;        this.listener = listener;        this.isDownloading = true;        downloadResponseHandler = new DownloadResponseHandler();    }    private String getTwoPointFloatStr(float value){        DecimalFormat df = new DecimalFormat("0.00000000000");        return df.format(value);    }    private void makeRequest() throws IOException, InterruptedIOException{        if(!Thread.currentThread().isInterrupted()){            try {                URL url = new URL(downloadUrl);                HttpURLConnection connection = (HttpURLConnection) url.openConnection();                connection.setRequestMethod("GET");                connection.setConnectTimeout(5000);                connection.setRequestProperty("Connection", "Keep-Alive");                connection.connect();                currentLength = connection.getContentLength();                if(!Thread.currentThread().isInterrupted()){                    downloadResponseHandler.sendResponseMessage(connection.getInputStream());                }            }catch (Exception e){                throw e;            }        }    }    @Override    public void run() {        try{            makeRequest();        }catch (IOException e){        }    }    /**     * 下载过程中的异常     */    public enum FailureCode{        UnknownHost, Socket, SocketTimeout, connectionTimeout,IO, HttpResponse,        Json, Interrupted    }    public class DownloadResponseHandler{        protected static final int SUCCESS_MESSAGE = 0;        protected static final int FAILURE_MESSAGE = 1;        protected static final int START_MESSAGE = 2;        protected static final int FINISH_MESSAGE = 3;        protected static final int NETWORK_OFF = 4;        private static final int PROGRESS_CHANGED = 5;        private float completeSize = 0;        private int progress = 0;        private Handler handler;        public DownloadResponseHandler(){            handler = new Handler(Looper.getMainLooper()) {                @Override                public void handleMessage(Message msg) {                    handleSelfMessage(msg);                }            };        }        protected void sendFinishMessage(){            sendMessage(obtainMessage(FINISH_MESSAGE, null));        }        private void sendProgressChangedMessage(int progress){            sendMessage(obtainMessage(PROGRESS_CHANGED, new Object[]{progress}));        }        protected void sendFailureMessage(FailureCode failureCode){            sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[]{failureCode}));        }        protected void sendMessage(Message msg){            if(handler!=null){                handler.sendMessage(msg);            }else{                handleSelfMessage(msg);            }        }        protected Message obtainMessage(int responseMessge, Object response){            Message msg = null;            if(handler!=null){                msg = handler.obtainMessage(responseMessge, response);            }else{                msg = Message.obtain();                msg.what = responseMessge;                msg.obj = response;            }            return msg;        }        protected void handleSelfMessage(Message msg){            Object[] response;            switch (msg.what){                case FAILURE_MESSAGE:                    response = (Object[]) msg.obj;                    sendFailureMessage((FailureCode) response[0]);                    break;                case PROGRESS_CHANGED:                    response = (Object[]) msg.obj;                    handleProgressChangedMessage(((Integer)response[0]).intValue());                    break;                case FINISH_MESSAGE:                    onFinish();                    break;            }        }        protected void handleProgressChangedMessage(int progress){            listener.onProgressChanged(progress, downloadUrl);        }        protected void onFinish(){            listener.onFinished(completeSize, "");        }        private void handleFailureMessage(FailureCode failureCode){            onFailure(failureCode);        }        protected void onFailure(FailureCode failureCode){            listener.onFailure();        }        void sendResponseMessage(InputStream is){            RandomAccessFile randomAccessFile = null;            completeSize=0;            try{                byte[] buffer = new byte[1024];                int length=-1;//读写长度                int limit=0;                randomAccessFile = new RandomAccessFile(localFilePath, "rwd");                while((length = is.read(buffer))!=-1){                    if(isDownloading){                        randomAccessFile.write(buffer, 0 ,length);                        completeSize += length;                        if(completeSize < currentLength){                            Log.e("tag", "completeSize="+completeSize);                            Log.e("tag", "currentLength="+currentLength);                            progress = (int)(Float.parseFloat(getTwoPointFloatStr(completeSize/currentLength))*100);                            Log.e("tag", "下载进度:"+progress);                            if(limit % 30==0 && progress <= 100){//隔30次更新一次notification                                sendProgressChangedMessage(progress);                            }                            limit++;                        }                    }                }                sendFinishMessage();            }catch(IOException e){                sendFailureMessage(FailureCode.IO);            }finally{                try{                    if(is!=null){                        is.close();                    }                    if(randomAccessFile!=null){                        randomAccessFile.close();                    }                }catch(IOException e){                    sendFailureMessage(FailureCode.IO);                }            }        }    }}

3.文件下载对外方法UpdateManager.java

package com.czhappy.appupdate.utils;import android.util.Log;import java.io.File;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.ThreadPoolExecutor;/** * Description: * User: chenzheng * Date: 2016/12/14 0014 * Time: 16:24 */public class UpdateManager {    private static UpdateManager updateManager;    private ThreadPoolExecutor threadPoolExecutor;    private UpdateDownloadRequest request;    private UpdateManager(){        threadPoolExecutor = (ThreadPoolExecutor) Executors.newCachedThreadPool();    }    static{        updateManager = new UpdateManager();    }    public static UpdateManager getInstance(){        return updateManager;    }    public void startDownloads(String downloadUrl, String localPath, UpdateDownloadListener listener){        if(request != null){            return;        }        checkLocalFilePath(localPath);        request = new UpdateDownloadRequest(downloadUrl, localPath, listener);        Future<?> future = threadPoolExecutor.submit(request);    }    /**     * 检查文件路径是否存在     * @param path     */    private void checkLocalFilePath(String path) {        Log.e("tag", path);        File dir = new File(path.substring(0, path.lastIndexOf("/")+1));        if(!dir.exists()){            dir.mkdir();        }        File file = new File(path);        if(!file.exists()){            try{                file.createNewFile();            }catch (Exception e){            }        }    }}

4.通知栏进度更新进程UpdateService.java

package com.czhappy.appupdate.utils;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.net.Uri;import android.os.Environment;import android.os.IBinder;import android.support.annotation.Nullable;import android.support.v7.app.NotificationCompat;import android.util.Log;import com.czhappy.appupdate.R;import java.io.File;/** * Description:更新下载后台进程 * User: chenzheng * Date: 2016/12/14 0014 * Time: 16:24 */public class UpdateService extends Service{    private String apkUrl;    private String filePath;    private NotificationManager notificationManager;    private Notification notification;    @Override    public void onCreate() {        Log.e("tag", "UpdateService onCreate()");        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);        filePath = Environment.getExternalStorageDirectory()+"/AppUpdate/czhappy.apk";    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("tag", "UpdateService onStartCommand()");        if(intent==null){            notifyUser(getString(R.string.update_download_failed), getString(R.string.update_download_failed), 0);            stopSelf();        }        apkUrl = intent.getStringExtra("apkUrl");        notifyUser(getString(R.string.update_download_start), getString(R.string.update_download_start), 0);        startDownload();        return super.onStartCommand(intent, flags, startId);    }    private void startDownload() {        UpdateManager.getInstance().startDownloads(apkUrl, filePath, new UpdateDownloadListener() {            @Override            public void onStarted() {                Log.e("tag", "onStarted()");            }            @Override            public void onProgressChanged(int progress, String downloadUrl) {                Log.e("onProgressChanged", progress+"");                notifyUser(getString(R.string.update_download_progressing), getString(R.string.update_download_progressing), progress);            }            @Override            public void onFinished(float completeSize, String downloadUrl) {                Log.e("tag", "onFinished()");                notifyUser(getString(R.string.update_download_finish), getString(R.string.update_download_finish), 100);                stopSelf();            }            @Override            public void onFailure() {                Log.e("tag", "onFailure()");                notifyUser(getString(R.string.update_download_failed), getString(R.string.update_download_failed), 0);                stopSelf();            }        });    }    /**     * 更新notification     * @param result     * @param msg     * @param progress     */    private void notifyUser(String result, String msg, int progress){        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);        builder.setSmallIcon(R.mipmap.ic_launcher)                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))                .setContentTitle(getString(R.string.app_name));        if(progress>0 && progress<=100){            builder.setProgress(100,progress,false);        }else{            builder.setProgress(0, 0, false);        }        builder.setAutoCancel(true);        builder.setWhen(System.currentTimeMillis());        builder.setTicker(result);        builder.setContentIntent(progress>=100 ? getContentIntent() :                PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT));        notification = builder.build();        notificationManager.notify(0, notification);    }    /**     * 进入apk安装程序     * @return     */    private PendingIntent getContentIntent() {        Log.e("tag", "getContentIntent()");        File apkFile = new File(filePath);        Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.setDataAndType(Uri.parse("file://"+apkFile.getAbsolutePath()),                "application/vnd.android.package-archive");        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);        startActivity(intent);        return pendingIntent;    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }}

5.测试类MainActivity.java

package com.czhappy.appupdate.activity;import android.content.DialogInterface;import android.content.Intent;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import com.czhappy.appupdate.R;import com.czhappy.appupdate.dialog.CommonDialog;import com.czhappy.appupdate.utils.UpdateService;public class MainActivity extends AppCompatActivity {    private Button update_btn;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        update_btn = (Button) this.findViewById(R.id.update_btn);        update_btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                checkVersion();            }        });        checkVersion();    }    private void checkVersion(){        //这里不发送检测新版本网络请求,直接进入下载新版本安装        CommonDialog.Builder builder = new CommonDialog.Builder(this);        builder.setTitle("升级提示");        builder.setMessage("发现新版本,请及时更新");        builder.setPositiveButton("立即升级", new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                dialog.dismiss();                Intent intent = new Intent(MainActivity.this, UpdateService.class);                intent.putExtra("apkUrl", "http://121.42.53.175:8080/hello_project/resources/upload/TianQiBao201605231.apk");                startService(intent);            }        });        builder.setNegativeButton("下次再说", new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                dialog.dismiss();            }        });        builder.create().show();    }}

三、源代码下载
http://download.csdn.net/detail/chenzheng8975/9712326

0 0