Android app更新方案

来源:互联网 发布:ipad直播软件 编辑:程序博客网 时间:2024/06/05 02:37

Android app更新方案:兼容6.0,7.0系统 包含强制更新,非强制后台更新,浏览器更新

项目中app更新功能是必不可少的  项目中遇到到的动态权限问题,文件权限问题 

根据需求的不同 有时需要用户强制更新 有时更新对于用户是可选的 可以放在后台更新

最简单直接的方法直接打开浏览器更新 完全不用适配什么6.0 什么7.0 几行代码搞定 代码如下:

/** * 打开浏览器 * @param url */public void browerUpdate(String url) {    Intent intent = new Intent();    intent.setAction("android.intent.action.VIEW");    Uri content_url = Uri.parse(url);    intent.setData(content_url);    AppManager.getInstance().getTopActivity().startActivity(intent);}


好了开始入正题,更新无非就是强制更新和后台更新 
2 强制更新采用的是Android 原生的DownloadManager实现文件的下载
3 后台更新采用的是xutils实现的文件下载  

强制更新 完整代码:

package com.langj.update.appconfig;import android.app.DownloadManager;import android.app.ProgressDialog;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.database.ContentObserver;import android.database.Cursor;import android.net.Uri;import android.os.Handler;import android.os.Message;import android.widget.Toast;import com.langj.update.R;import com.langj.update.app.Constant;import com.langj.update.utils.AppManager;import com.langj.update.utils.SPUtil;import org.xutils.x;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;/public class DownloadUtils {    private DownloadManager downloadManager;    private Context mContext;    private long downloadId;    private ProgressDialog progressDialog;    private DownloadChangeObserver downloadObserver;    public static final int HANDLE_DOWNLOAD = 0x001;    private ScheduledExecutorService scheduledExecutorService;    public DownloadUtils(Context context) {        this.mContext = context;    }    public void downloadAPK(String url) {        downloadObserver = new DownloadChangeObserver();        showProcess();        registerContentObserver();        //创建下载任务        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));        //移动网络情况下是否允许漫游        request.setAllowedOverRoaming(false);        request.setMimeType("application/vnd.android.package-archive");        //在通知栏中显示,默认就是显示的        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);        request.setTitle("新版本" + x.app().getResources().getString(R.string.app_name));        request.setDescription("正在下载" + x.app().getResources().getString(R.string.app_name));        request.setVisibleInDownloadsUi(true);        //设置下载的路径//        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, " myApp.apk");        request.setDestinationInExternalFilesDir(mContext.getApplicationContext(), "phoenix", "phoenix.apk");        //获取DownloadManager        downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);        //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等        downloadId = downloadManager.enqueue(request);        registerBroadcast();    }    /**     * 正在下载中的进度条     */    public void showProcess() {        progressDialog = new ProgressDialog(AppManager.getInstance().getTopActivity());        progressDialog.setCancelable(false);        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);        progressDialog.setMax(100);        progressDialog.setMessage("正在下载...");        progressDialog.show();    }    /**     * 注册广播     */    private void registerBroadcast() {        IntentFilter intentFilter = new IntentFilter();        intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);        intentFilter.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);        mContext.registerReceiver(receiver, intentFilter);    }    /**     * 注册ContentObserver     */    private void registerContentObserver() {        /** observer download change **/        if (downloadObserver != null) {            mContext.getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true, downloadObserver);        }    }    private BroadcastReceiver receiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            checkStatus();        }    };    //检查下载状态    private void checkStatus() {        DownloadManager.Query query = new DownloadManager.Query();        //通过下载的id查找        query.setFilterById(downloadId);        Cursor c = downloadManager.query(query);        if (c != null && c.moveToFirst()) {            int state = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));            switch (state) {                //下载暂停                case DownloadManager.STATUS_PAUSED:                    break;                case DownloadManager.ERROR_CANNOT_RESUME:                    //下载延迟                case DownloadManager.STATUS_PENDING:                    break;                //正在下载                case DownloadManager.STATUS_RUNNING:                    break;                //下载完成                case DownloadManager.STATUS_SUCCESSFUL:                    //下载完成安装APK                    close();                    progressDialog.setProgress(100);                    unregisterBroadcast();                    unregisterContentObserver();                    Uri downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId);                    SPUtil.put(Constant.SP_DOWNLOAD_PATH, downloadFileUri.getPath());                    installApk(downloadFileUri);                    break;                //下载失败                case DownloadManager.STATUS_FAILED:                    Toast.makeText(mContext, "下载失败", Toast.LENGTH_SHORT).show();                    break;            }        }        c.close();    }    /**     * 安装APK     *     * @param apkPath 安装包的路径     */    public void installApk(Uri apkPath) {        Intent intent = new Intent();        intent.setAction(Intent.ACTION_VIEW);        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.setDataAndType(apkPath, "application/vnd.android.package-archive");        mContext.startActivity(intent);    }    public Handler downLoadHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if (HANDLE_DOWNLOAD == msg.what) {                float i = (msg.arg1 / (float) msg.arg2);                int k = (int) (i * 100);                if (k >= 0) {                    progressDialog.setProgress(k);                }            }        }    };    /**     * 关闭定时器,线程等操作     */    private void close() {        if (scheduledExecutorService != null && !scheduledExecutorService.isShutdown()) {            scheduledExecutorService.shutdown();        }        if (downLoadHandler != null) {            downLoadHandler.removeCallbacksAndMessages(null);        }    }    /**     * 注销广播     */    private void unregisterBroadcast() {        if (receiver != null) {            mContext.unregisterReceiver(receiver);            receiver = null;        }    }    /**     * 注销ContentObserver     */    private void unregisterContentObserver() {        if (downloadObserver != null) {            mContext.getContentResolver().unregisterContentObserver(downloadObserver);        }    }    private Runnable progressRunnable = new Runnable() {        @Override        public void run() {            int[] bytesAndStatus = getBytesAndStatus(downloadId);            downLoadHandler.sendMessage(downLoadHandler.obtainMessage(HANDLE_DOWNLOAD, bytesAndStatus[0], bytesAndStatus[1], bytesAndStatus[2]));        }    };    private int[] getBytesAndStatus(long downloadId) {        int[] bytesAndStatus = new int[]{                -1, -1, 0        };        DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);        Cursor cursor = null;        try {            cursor = downloadManager.query(query);            if (cursor != null && cursor.moveToFirst()) {                //已经下载文件大小                bytesAndStatus[0] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));                //下载文件的总大小                bytesAndStatus[1] = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));                //下载状态                bytesAndStatus[2] = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));            }        } finally {            if (cursor != null) {                cursor.close();            }        }        return bytesAndStatus;    }    private class DownloadChangeObserver extends ContentObserver {        public DownloadChangeObserver() {            super(downLoadHandler);            scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();        }        /**         * 当所监听的Uri发生改变时,就会回调此方法         *         * @param selfChange 此值意义不大, 一般情况下该回调值false         */        @Override        public void onChange(boolean selfChange) {            scheduledExecutorService.scheduleAtFixedRate(progressRunnable, 0, 2, TimeUnit.SECONDS);        }    }}

后台更新:

package com.langj.update.appconfig;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.net.Uri;import android.os.Build;import android.os.IBinder;import android.os.SystemClock;import android.support.annotation.Nullable;import android.support.v4.content.FileProvider;import com.langj.update.R;import com.langj.update.utils.AppManager;import org.xutils.x;import java.io.File;/** */public class DownLoadService extends Service {    String download_url;    private int requestCode = (int) SystemClock.uptimeMillis();    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public void onCreate() {        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        download_url = intent.getStringExtra("download_url");        Intent intent_noti = new Intent();        intent_noti.setAction(Intent.ACTION_VIEW);//        intent_noti.setDataAndType(Uri.fromFile(mFile), "application/vnd.android.package-archive");        PendingIntent rightPendIntent = PendingIntent.getActivity(this,                requestCode, intent_noti, PendingIntent.FLAG_UPDATE_CURRENT);        int smallIcon = R.mipmap.ic_launcher;        String ticker = "正在更新" + x.app().getResources().getString(R.string.app_name);        NotifyUtil notify7 = new NotifyUtil(this, 7);        notify7.notify_progress(rightPendIntent, smallIcon, ticker, x.app().getResources().getString(R.string.app_name) + "升级程序", "正在下载中",                false, false, false, download_url, new NotifyUtil.DownLoadListener() {                    @Override                    public void OnSuccess(File file) {                        DownLoadService.this.stopSelf();                        install(file);                    }                    @Override                    public void onFailure(Throwable t, int errorNo, String strMsg) {                    }                });        return super.onStartCommand(intent, flags, startId);    }    /**     * 安装APk     * @param file     */    public static void install(File file) {        Uri apkUri;        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            apkUri = FileProvider.getUriForFile(AppManager.getInstance().getTopActivity(), "com.langj.update.fileprovider", file);        } else {            apkUri = Uri.fromFile(file);        }        Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");        AppManager.getInstance().getTopActivity().startActivity(intent);    }}

后台更新用到的通知类“

package com.langj.update.appconfig;import android.annotation.SuppressLint;import android.app.Activity;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Build;import android.os.SystemClock;import android.support.v7.app.NotificationCompat;import android.widget.RemoteViews;import android.widget.Toast;import com.langj.update.R;import com.langj.update.utils.AppManager;import com.langj.update.utils.FileManager;import org.xutils.common.Callback;import org.xutils.common.task.PriorityExecutor;import org.xutils.http.RequestParams;import org.xutils.x;import java.io.File;import java.util.ArrayList;@SuppressLint("NewApi")public class NotifyUtil {    private static final int FLAG = Notification.FLAG_INSISTENT;    int requestCode = (int) SystemClock.uptimeMillis();    private int NOTIFICATION_ID;    private NotificationManager nm;    private Notification notification;    private NotificationCompat.Builder cBuilder;    private Notification.Builder nBuilder;    private Context mContext;    public NotifyUtil(Context context, int ID) {        this.NOTIFICATION_ID = ID;        mContext = context;        // 获取系统服务来初始化对象        nm = (NotificationManager) mContext                .getSystemService(Activity.NOTIFICATION_SERVICE);        cBuilder = new NotificationCompat.Builder(mContext);    }    /**     * 设置在顶部通知栏中的各种信息     *     * @param pendingIntent     * @param smallIcon     * @param ticker     */    private void setCompatBuilder(PendingIntent pendingIntent, int smallIcon, String ticker,                                  String title, String content, boolean sound, boolean vibrate, boolean lights) {//        // 如果当前Activity启动在前台,则不开启新的Activity。//        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);//        // 当设置下面PendingIntent.FLAG_UPDATE_CURRENT这个参数的时候,常常使得点击通知栏没效果,你需要给notification设置一个独一无二的requestCode//        // 将Intent封装进PendingIntent中,点击通知的消息后,就会启动对应的程序//        PendingIntent pIntent = PendingIntent.getActivity(mContext,//                requestCode, intent, FLAG);        cBuilder.setContentIntent(pendingIntent);// 该通知要启动的Intent        cBuilder.setSmallIcon(smallIcon);// 设置顶部状态栏的小图标        cBuilder.setLargeIcon((BitmapFactory.decodeResource(AppManager.getInstance().getTopActivity().getResources(), R.mipmap.ic_launcher)));// 设置顶部状态栏的小图标        cBuilder.setTicker(ticker);// 在顶部状态栏中的提示信息        cBuilder.setContentTitle(title);// 设置通知中心的标题        cBuilder.setContentText(content);// 设置通知中心中的内容        cBuilder.setWhen(System.currentTimeMillis());      /*         * 将AutoCancel设为true后,当你点击通知栏的notification后,它会自动被取消消失,       * 不设置的话点击消息后也不清除,但可以滑动删除       */        cBuilder.setAutoCancel(true);        // 将Ongoing设为true 那么notification将不能滑动删除        // notifyBuilder.setOngoing(true);        /*         * 从Android4.1开始,可以通过以下方法,设置notification的优先级,       * 优先级越高的,通知排的越靠前,优先级低的,不会在手机最顶部的状态栏显示图标       */        cBuilder.setPriority(NotificationCompat.PRIORITY_MAX);        /*         * Notification.DEFAULT_ALL:铃声、闪光、震动均系统默认。       * Notification.DEFAULT_SOUND:系统默认铃声。       * Notification.DEFAULT_VIBRATE:系统默认震动。       * Notification.DEFAULT_LIGHTS:系统默认闪光。       * notifyBuilder.setDefaults(Notification.DEFAULT_ALL);       */        int defaults = 0;        if (sound) {            defaults |= Notification.DEFAULT_SOUND;        }        if (vibrate) {            defaults |= Notification.DEFAULT_VIBRATE;        }        if (lights) {            defaults |= Notification.DEFAULT_LIGHTS;        }        cBuilder.setDefaults(defaults);    }    /**     * 设置builder的信息,在用大文本时会用到这个     *     * @param pendingIntent     * @param smallIcon     * @param ticker     */    private void setBuilder(PendingIntent pendingIntent, int smallIcon, String ticker, boolean sound, boolean vibrate, boolean lights) {        nBuilder = new Notification.Builder(mContext);        // 如果当前Activity启动在前台,则不开启新的Activity。//        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);//        PendingIntent pIntent = PendingIntent.getActivity(mContext,//                requestCode, intent, FLAG);        nBuilder.setContentIntent(pendingIntent);        nBuilder.setSmallIcon(smallIcon);        nBuilder.setTicker(ticker);        nBuilder.setWhen(System.currentTimeMillis());        nBuilder.setPriority(Notification.PRIORITY_MAX);        int defaults = 0;        if (sound) {            defaults |= Notification.DEFAULT_SOUND;        }        if (vibrate) {            defaults |= Notification.DEFAULT_VIBRATE;        }        if (lights) {            defaults |= Notification.DEFAULT_LIGHTS;        }        nBuilder.setDefaults(defaults);    }    /**     * 普通的通知     * <p/>     * 1. 侧滑即消失,下拉通知菜单则在通知菜单显示     *     * @param pendingIntent     * @param smallIcon     * @param ticker     * @param title     * @param content     */    public void notify_normal_singline(PendingIntent pendingIntent, int smallIcon,                                       String ticker, String title, String content, boolean sound, boolean vibrate, boolean lights) {        setCompatBuilder(pendingIntent, smallIcon, ticker, title, content, sound, vibrate, lights);        sent();    }    /**     * 进行多项设置的通知(在小米上似乎不能设置大图标,系统默认大图标为应用图标)     *     * @param pendingIntent     * @param smallIcon     * @param ticker     * @param title     * @param content     */    public void notify_mailbox(PendingIntent pendingIntent, int smallIcon, int largeIcon, ArrayList<String> messageList,                               String ticker, String title, String content, boolean sound, boolean vibrate, boolean lights) {        setCompatBuilder(pendingIntent, smallIcon, ticker, title, content, sound, vibrate, lights);        // 将Ongoing设为true 那么notification将不能滑动删除        //cBuilder.setOngoing(true);                Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), largeIcon);        cBuilder.setLargeIcon(bitmap);        cBuilder.setDefaults(Notification.DEFAULT_ALL);// 设置使用默认的声音        //cBuilder.setVibrate(new long[]{0, 100, 200, 300});// 设置自定义的振动        cBuilder.setAutoCancel(true);        // builder.setSound(Uri.parse("file:///sdcard/click.mp3"));        // 设置通知样式为收件箱样式,在通知中心中两指往外拉动,就能出线更多内容,但是很少见        //cBuilder.setNumber(messageList.size());        NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();        for (String msg : messageList) {            inboxStyle.addLine(msg);        }        inboxStyle.setSummaryText("[" + messageList.size() + "条]" + title);        cBuilder.setStyle(inboxStyle);        sent();    }    /**     * 自定义视图的通知     *     * @param remoteViews     * @param pendingIntent     * @param smallIcon     * @param ticker     */    public void notify_customview(RemoteViews remoteViews, PendingIntent pendingIntent,                                  int smallIcon, String ticker, boolean sound, boolean vibrate, boolean lights) {        setCompatBuilder(pendingIntent, smallIcon, ticker, null, null, sound, vibrate, lights);        notification = cBuilder.build();        notification.contentView = remoteViews;        // 发送该通知        nm.notify(NOTIFICATION_ID, notification);    }    /**     * 可以容纳多行提示文本的通知信息 (因为在高版本的系统中才支持,所以要进行判断)     *     * @param pendingIntent     * @param smallIcon     * @param ticker     * @param title     * @param content     */    public void notify_normail_moreline(PendingIntent pendingIntent, int smallIcon, String ticker,                                        String title, String content, boolean sound, boolean vibrate, boolean lights) {        final int sdk = Build.VERSION.SDK_INT;        if (sdk < Build.VERSION_CODES.JELLY_BEAN) {            notify_normal_singline(pendingIntent, smallIcon, ticker, title, content, sound, vibrate, lights);            Toast.makeText(mContext, "您的手机低于Android 4.1.2,不支持多行通知显示!!", Toast.LENGTH_SHORT).show();        } else {            setBuilder(pendingIntent, smallIcon, ticker, true, true, false);            nBuilder.setContentTitle(title);            nBuilder.setContentText(content);            nBuilder.setPriority(Notification.PRIORITY_HIGH);            notification = new Notification.BigTextStyle(nBuilder).bigText(content).build();            // 发送该通知            nm.notify(NOTIFICATION_ID, notification);        }    }    /**     * 有进度条的通知,可以设置为模糊进度或者精确进度     *     * @param pendingIntent     * @param smallIcon     * @param ticker     * @param title     * @param content     */    public void notify_progress(PendingIntent pendingIntent, int smallIcon,                                String ticker, String title, String content,                                boolean sound, boolean vibrate, boolean lights,                                String download_url,  final DownLoadListener listener) {        setCompatBuilder(pendingIntent, smallIcon, ticker, title, content, sound, vibrate, lights);        /*         * 因为进度条要实时更新通知栏也就说要不断的发送新的提示,所以这里不建议开启通知声音。       * 这里是作为范例,给大家讲解下原理。所以发送通知后会听到多次的通知声音。       */        String path = FileManager.getCompressFilePath() + x.app().getResources().getString(R.string.app_name) + ".apk";        RequestParams params = new RequestParams(download_url);        params.setSaveFilePath(path);        params.setAutoResume(true);        params.setExecutor(new PriorityExecutor(2, true));        params.setCancelFast(false);        x.http().get(params, new Callback.ProgressCallback<File>() {            @Override            public void onWaiting() {            }            @Override            public void onStarted() {            }            @Override            public void onLoading(long total, long current, boolean isDownloading) {                double a = total;                double b = current;                double currentPro = (b / a) * 100;                cBuilder.setProgress(100, (int) currentPro, false);                sent();            }            @Override            public void onSuccess(File result) {                cBuilder.setContentText("下载完成").setProgress(0, 0, false);                sent();                listener.OnSuccess(result);            }            @Override            public void onError(Throwable ex, boolean isOnCallback) {                ex.printStackTrace();            }            @Override            public void onCancelled(CancelledException cex) {            }            @Override            public void onFinished() {            }        });    }    /**     * 容纳大图片的通知     *     * @param pendingIntent     * @param smallIcon     * @param ticker     * @param title     * @param bigPic     */    public void notify_bigPic(PendingIntent pendingIntent, int smallIcon, String ticker,                              String title, String content, int bigPic, boolean sound, boolean vibrate, boolean lights) {        setCompatBuilder(pendingIntent, smallIcon, ticker, title, null, sound, vibrate, lights);        NotificationCompat.BigPictureStyle picStyle = new NotificationCompat.BigPictureStyle();        final BitmapFactory.Options options = new BitmapFactory.Options();        options.inScaled = true;        options.inSampleSize = 2;        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),                bigPic, options);        picStyle.bigPicture(bitmap);        picStyle.bigLargeIcon(bitmap);        cBuilder.setContentText(content);        cBuilder.setStyle(picStyle);        sent();    }    /**     * 里面有两个按钮的通知     *     * @param smallIcon     * @param leftbtnicon     * @param lefttext     * @param leftPendIntent     * @param rightbtnicon     * @param righttext     * @param rightPendIntent     * @param ticker     * @param title     * @param content     */    public void notify_button(int smallIcon, int leftbtnicon, String lefttext, PendingIntent leftPendIntent, int rightbtnicon, String righttext, PendingIntent rightPendIntent, String ticker,                              String title, String content, boolean sound, boolean vibrate, boolean lights) {        requestCode = (int) SystemClock.uptimeMillis();        setCompatBuilder(rightPendIntent, smallIcon, ticker, title, content, sound, vibrate, lights);        cBuilder.addAction(leftbtnicon,                lefttext, leftPendIntent);        cBuilder.addAction(rightbtnicon,                righttext, rightPendIntent);        sent();    }    public void notify_HeadUp(PendingIntent pendingIntent, int smallIcon, int largeIcon,                              String ticker, String title, String content, int leftbtnicon, String lefttext, PendingIntent leftPendingIntent, int rightbtnicon, String righttext, PendingIntent rightPendingIntent, boolean sound, boolean vibrate, boolean lights) {        setCompatBuilder(pendingIntent, smallIcon, ticker, title, content, sound, vibrate, lights);        cBuilder.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), largeIcon));        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {            cBuilder.addAction(leftbtnicon,                    lefttext, leftPendingIntent);            cBuilder.addAction(rightbtnicon,                    righttext, rightPendingIntent);        } else {            Toast.makeText(mContext, "版本低于Andriod5.0,无法体验HeadUp样式通知", Toast.LENGTH_SHORT).show();        }        sent();    }    /**     * 发送通知     */    private void sent() {        notification = cBuilder.build();        // 发送该通知        nm.notify(NOTIFICATION_ID, notification);    }    /**     * 根据id清除通知     */    public void clear() {        // 取消通知        nm.cancelAll();    }    DownLoadListener listener;    public void setOnDownLoadListener(DownLoadListener l) {        listener = l;    }    public interface DownLoadListener {        void OnSuccess(File file);        void onFailure(Throwable t, int errorNo, String strMsg);    }}

更新管理类:

package com.langj.update.appconfig;import android.Manifest;import android.app.Dialog;import android.content.Context;import android.content.Intent;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.net.Uri;import android.os.Build;import android.telephony.TelephonyManager;import android.text.TextUtils;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.google.gson.Gson;import com.langj.update.R;import com.langj.update.app.Constant;import com.langj.update.net.ApiListener;import com.langj.update.net.ApiTool;import com.langj.update.utils.AppManager;import com.langj.update.utils.JSONUtils;import com.langj.update.utils.SPUtil;import com.tbruyelle.rxpermissions.RxPermissions;import org.xutils.common.Callback;import org.xutils.common.util.LogUtil;import org.xutils.http.RequestParams;import org.xutils.x;import java.io.File;import java.sql.Timestamp;import java.util.Map;import rx.functions.Action1;public class UpdateManager {    /**     * FoceUpdate        强制更新     * BrowSerUpdate     浏览器更新     * BackGroundUpdate  后台更新     */    public static final String FoceUpdate = "foceupdate";    public static final String BrowSerUpdate = "browserupdate";    public static final String BackGroundUpdate = "backgroundupdate";    private static UpdateManager manager = new UpdateManager();    private checkVersionListen checkVersionListen;    /**     * 检查更新     *     * @param url          效验url     * @param hasHint      如果是最新版本是否显示提示     * @param isFoceUpdate 是否强制更新     */    public static final void checkUpdate(String url, boolean hasHint, String isFoceUpdate) {        manager.check(url, hasHint, isFoceUpdate);    }    public void setCheckVersionListen(checkVersionListen checkVersionListen) {        this.checkVersionListen = checkVersionListen;    }    public interface checkVersionListen {        void checkVerssion(String str);    }    public void check(String url, final boolean hasHint, final String updateType) {        removeOldApk();        RequestParams params = new RequestParams(url);        params.addBodyParameter("command", "config.app.update.check");        params.addBodyParameter("pubsJson", getPubJson());        ApiTool apiTool = new ApiTool();        apiTool.postApi(params, new ApiListener() {            @Override            public void onCancelled(Callback.CancelledException cex) {                if (checkVersionListen != null) {                    checkVersionListen.checkVerssion("0");                }            }            @Override            public void onComplete(RequestParams params, String result, String type) {                Map<String, String> map = JSONUtils.parseKeyAndValueToMap(result);                if (map.get("hasNewVersion").equals("1")) {                    if (checkVersionListen != null) {                        checkVersionListen.checkVerssion("1");                    }                    switch (updateType) {                        case UpdateManager.FoceUpdate:                            startDownload(map.get("downloadUrl"));                            break;                        case UpdateManager.BackGroundUpdate://                            showBuilder(result, "");                            break;                        case UpdateManager.BrowSerUpdate:                            browerUpdate(map.get("downloadUrl"));                            break;                    }                } else {                    if (checkVersionListen != null) {                        checkVersionListen.checkVerssion("0");                    }                    if (hasHint) Toast.makeText(x.app(), "已是最新版本", Toast.LENGTH_SHORT).show();                }            }            @Override            public void onError(Map<String, String> var1, RequestParams var2) {                LogUtil.e(var1.get("message"));                if (checkVersionListen != null) {                    checkVersionListen.checkVerssion("0");                }            }            @Override            public void onExceptionType(Throwable var1, RequestParams params, String type) {                if (checkVersionListen != null) {                    checkVersionListen.checkVerssion("0");                }            }        }, "");    }    /**     * 更新     * @param url     * @param updateType     */    public void update(final String url, String updateType) {        switch (updateType) {            case UpdateManager.FoceUpdate:                startDownload(url);                break;            case UpdateManager.BackGroundUpdate:                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {                    RxPermissions.getInstance(AppManager.getInstance().getTopActivity())                            // 申请权限                            .request(Manifest.permission.WRITE_EXTERNAL_STORAGE)                            .subscribe(new Action1<Boolean>() {                                @Override                                public void call(Boolean granted) {                                    if (granted) {                                        showBuilder("", url);                                    } else {                                    }                                }                            });                } else {                    showBuilder("", url);                }                break;            case UpdateManager.BrowSerUpdate:                browerUpdate(url);                break;        }    }    /**     * 打开浏览器     * @param url     */    public void browerUpdate(String url) {        Intent intent = new Intent();        intent.setAction("android.intent.action.VIEW");        Uri content_url = Uri.parse(url);        intent.setData(content_url);        AppManager.getInstance().getTopActivity().startActivity(intent);    }    public void showBuilder(String result, final String url) {        final Map<String, String> map = JSONUtils.parseKeyAndValueToMap(result);        View view = View.inflate(AppManager.getInstance().getTopActivity(), R.layout.dlg_update, null);        TextView tv_content = (TextView) view.findViewById(R.id.update_description);        TextView tv_no = (TextView) view.findViewById(R.id.buildeexti_tv_no);        TextView tv_ok = (TextView) view.findViewById(R.id.builderexit_tv_ok);        final Dialog dialog = new Dialog(AppManager.getInstance().getTopActivity(), R.style.dialog);//        tv_content.setText(map.get("new_features"));        if (map != null && !TextUtils.isEmpty(map.get("newVersionDescribe"))) {            tv_content.setText(map.get("newVersionDescribe"));        }        tv_no.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dialog.cancel();            }        });        tv_ok.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dialog.cancel();                Intent intent = new Intent(AppManager.getInstance().getTopActivity(), DownLoadService.class);                if (map != null && !TextUtils.isEmpty(map.get("downloadUrl"))) {                    intent.putExtra("download_url", map.get("downloadUrl"));                } else {                    intent.putExtra("download_url", url);                }                AppManager.getInstance().getTopActivity().startService(intent);            }        });        dialog.setContentView(view);        dialog.setCancelable(false);        dialog.show();    }    public void startDownload(final String url) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {            RxPermissions.getInstance(AppManager.getInstance().getTopActivity())                    // 申请权限                    .request(Manifest.permission.WRITE_EXTERNAL_STORAGE)                    .subscribe(new Action1<Boolean>() {                        @Override                        public void call(Boolean granted) {                            if (granted) {                                downloadFile(url);                            } else {                            }                        }                    });        } else {            downloadFile(url);        }    }    /**     * 更新之前先移除残留app文件     */    private void removeOldApk() {        File fileName = new File(SPUtil.getString(Constant.SP_DOWNLOAD_PATH, ""));        if (fileName != null && fileName.exists() && fileName.isFile()) {            fileName.delete();        }    }    // 下载文件    private synchronized void downloadFile(String url) {        DownloadUtils downloadUtils = new DownloadUtils(AppManager.getInstance().getTopActivity());        downloadUtils.downloadAPK(url);    }    // 获取版本号    private String getVersionCode() {        try {            PackageInfo packageInfo = x.app().getPackageManager().getPackageInfo(x.app().getPackageName(), 0);            return packageInfo.versionName;        } catch (PackageManager.NameNotFoundException e) {            e.printStackTrace();            return "";        }    }    public String getPubJson() {        PubsJson pubsJson = new PubsJson();        pubsJson.setImei(getIMSI());        pubsJson.setOs("Android");        pubsJson.setOsVersion(Build.DISPLAY);        pubsJson.setAppVersion(getVersionCode());        pubsJson.setTimestamp(getTimesTamp());        Gson gson = new Gson();        String s1 = gson.toJson(pubsJson);        return s1;    }    /**     * 获取手机IMSI号     */    public String getIMSI() {        TelephonyManager mTelephonyMgr = (TelephonyManager) x.app().getSystemService(Context.TELEPHONY_SERVICE);        String imsi = mTelephonyMgr.getSubscriberId();        return imsi;    }    public String getTimesTamp() {        Timestamp now = new Timestamp(System.currentTimeMillis());//获取系统当前时间        return now.toString();    }}

项目用到的第三方:

compile 'org.xutils:xutils:3.3.36'   //文件下载compile 'com.zhy:autolayout:1.4.3'   //适配compile 'com.tbruyelle.rxpermissions:rxpermissions:0.7.0@aar'  //权限申请compile 'io.reactivex:rxjava:1.1.6'compile 'com.google.code.gson:gson:2.8.2'

最后在Activity中调用更新:

package com.langj.update;import android.os.Bundle;import android.view.View;import com.langj.update.appconfig.UpdateManager;import com.langj.update.utils.AppManager;import com.zhy.autolayout.AutoLayoutActivity;import org.xutils.view.annotation.Event;import org.xutils.x;public class MainActivity extends AutoLayoutActivity {    private UpdateManager manager;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        AppManager.getInstance().addActivity(this);        x.view().inject(this);        manager = new UpdateManager();    }    @Event(value = {R.id.btn_01, R.id.btn_02, R.id.btn_03})    private void onTestBaidulClick(View view) {        switch (view.getId()) {            case R.id.btn_01:                //浏览器更新                manager.update("http://dakaapp.troila.com/download/daka.apk?v=3.0", UpdateManager.BrowSerUpdate);                break;            case R.id.btn_02:                //后台更新更新                manager.update("http://dakaapp.troila.com/download/daka.apk?v=3.0", UpdateManager.BackGroundUpdate);                break;            case R.id.btn_03:                //强制更新                manager.update("http://dakaapp.troila.com/download/daka.apk?v=3.0", UpdateManager.FoceUpdate);                break;        }    }}

核心代码到此结束,完整源码请后续看我GitHub地址

 
原创粉丝点击