通过NotificationManager一键更新下载apk安装包

如何使用?
直接new一个对象,把apk的下载链接传入即可.如果想取消,调用interrupt()方法即可.本源码不需要再引用其他代码和资源文件.

一.关于下载完的apk存储路径
1.优先存储于外部存储的应用缓存中,即通过context.getExternalCacheDir()获得,前提是要有android.permission.WRITE_EXTERNAL_STORAGE权限
2.其次再存储在应用内部缓存中,即通过context.getCacheDir()获得

二.下载步骤
1.判断下载链接是否有效
2.启动线程下载
3.调用系统Notification通知下载进度
4.下载完成,执行apk与当前应用校验
5.校验成功后,安装apk.

废话不多说,直接上源码

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import static android.os.Environment.MEDIA_MOUNTED;

public class CWJApkDownload extends Thread {

    private static final int DOWN_UPDATE = 1;
    private static final int DOWN_OVER = 2;
    private static final int DOWN_CANCEL = 3;
    private static final String TAG = "CWJ_APK_DOWNLOAD";
    private static int progress;

    private Down_handler handler;

    private static int length;
    private static int count;

    private Context context;
    private static File apkFile;
    private String apkUrl;
    private String saveFileName;

    public CWJApkDownload(Context context) {
        this.context = context;
        handler = new Down_handler(context);
    }

    public CWJApkDownload(Context context, String apkUrl) {
        this.context = context;
        this.apkUrl=apkUrl;

        if(TextUtils.isEmpty(apkUrl)){
            Toast.makeText(context, "下载链接不能为空", Toast.LENGTH_LONG).show();
            return ;
        }
        if(apkUrl.indexOf("/")>0){
            saveFileName=apkUrl.substring(apkUrl.lastIndexOf("/")+1,apkUrl.length());
        }else{
            saveFileName="NewVsersion.apk";
        }

        Notification.Builder builder=notificationInit();
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
        handler = new Down_handler(context, builder, notificationManager);
    }

    private class Down_handler extends Handler {
        WeakReference<Context> mContextReference;
        Notification.Builder builder;
        NotificationManager notificationManager;

        Down_handler(Context context) {
            mContextReference = new WeakReference<>(context);
        }

        Down_handler(Context context, Notification.Builder builder, NotificationManager notificationManager) {
            mContextReference = new WeakReference<>(context);
            this.builder = builder;
            this.notificationManager = notificationManager;
        }

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        @Override
        public void handleMessage(Message msg) {
            Context context = mContextReference.get();
            switch (msg.what) {
                case DOWN_UPDATE:
                    builder.setProgress(length, count, false)
                            .setContentText("下载进度:" + progress + "%");
                    notificationManager.notify(1115, builder.build());
                    break;
                case DOWN_OVER:
                    builder.setTicker("下载完成");
                    notificationManager.notify(1115, builder.build());
                    notificationManager.cancel(1115);
                    length = 0;
                    count = 0;

                    if (checkApk()) {
                        Log.i(TAG, "APK路径:" + apkFile);
                        if (!apkFile.exists()) {
                            return;
                        }
                        Intent i = new Intent(Intent.ACTION_VIEW);
                        i.setDataAndType(Uri.parse("file://" + apkFile.toString()),
                                "application/vnd.android.package-archive");
                        context.startActivity(i);
                    }
                    break;
                case DOWN_CANCEL:
                    builder.setTicker("下载取消");
                    notificationManager.notify(1115, builder.build());
                    notificationManager.cancel(1115);
                    break;
                default:
                    break;
            }
        }

    }

    public void run() {
        URL url = null;
        HttpURLConnection conn = null;
        InputStream is = null;
        try {
            url = new URL(apkUrl);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        Log.i(TAG, String.format("ApkDownloadUrl:%s", apkUrl));
        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            length = conn.getContentLength();
            is = conn.getInputStream();
        } catch (FileNotFoundException e0) {
//            e0.printStackTrace();
            try {
                conn.disconnect();
                conn = (HttpURLConnection) url.openConnection();
                conn.setInstanceFollowRedirects(false);
                conn.connect();
                String location = new String(conn.getHeaderField("Location").getBytes("ISO-8859-1"), "UTF-8").replace(" ", "");
                url = new URL(location);
                conn = (HttpURLConnection) url.openConnection();
                conn.connect();
                length = conn.getContentLength();
                is = conn.getInputStream();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        } catch (IOException e2) {
            e2.printStackTrace();
        }


        try {
            File file = getCacheDirectory();
            if (!file.exists()) {
                file.mkdir();
            }

            apkFile = new File(file, saveFileName);
            FileOutputStream fos = new FileOutputStream(apkFile);
            long tempFileLength = file.length();
            byte buf[] = new byte[1024];
            int times = 0; //这很重要
            int numread;
            do {
                numread = is.read(buf);
                count += numread;
                progress = (int) (((float) count / length) * 100);
                if ((times == 512) || (tempFileLength == length)) {
                    handler.sendEmptyMessage(DOWN_UPDATE);
                    times = 0;
                }
                times++;
                if (numread <= 0) {
                    handler.sendEmptyMessage(DOWN_OVER);
                    break;
                }
                fos.write(buf, 0, numread);
            } while (true);
            fos.flush();
            fos.close();
            is.close();
            conn.disconnect();

        } catch (IOException e3) {
            e3.printStackTrace();
        }
    }

    @Override
    public void interrupt() {
        handler.sendEmptyMessage(DOWN_CANCEL);
        super.interrupt();
    }

    //检查当前app与下载的apk包名是否一致
    private  boolean checkApk() {
        String apkName = getAPKPackageName(apkFile.toString());
        String appName = context.getPackageName();
        if (apkName.equals(appName)) {
            Log.i(TAG, "apk检验:包名相同,安装apk");
            return true;
        } else {
            Log.i(TAG, String.format("apk检验:包名不同。该app包名:%s,apk包名:%s", appName, apkName));
            Toast.makeText(context, "apk检验:包名不同,不进行安装", Toast.LENGTH_LONG).show();
            return false;
        }
    }
    //获取apk的包名
    private  String getAPKPackageName(String apkPath) {
        PackageManager pm = context.getPackageManager();
        PackageInfo info = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
        if (info != null) {
            ApplicationInfo appInfo = info.applicationInfo;
            return appInfo.packageName;
        }
        return null;
    }
    //获取app应用名称
    private String getAppName() {
        String appName = "";
        try {
            PackageInfo pi = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            appName = pi.applicationInfo.loadLabel(context.getPackageManager()).toString();
            if (appName == null || appName.length() <= 0) {
                return "";
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return appName;
    }
    //Notification初始化
    private  Notification.Builder notificationInit() {
        Intent intent = new Intent(context, context.getClass());
        PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);

        Notification.Builder builder = new Notification.Builder(context);
        builder.setSmallIcon(android.R.drawable.stat_sys_download)
                .setTicker("开始下载")
                .setContentTitle(getAppName())
                .setContentText("正在更新")
                .setContentIntent(pIntent)
                .setWhen(System.currentTimeMillis());
        return builder;
    }
    //获取apk存储路径
    public  File getCacheDirectory() {
        File appCacheDir = null;
        if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission()) {
            appCacheDir = context.getExternalCacheDir();
        }
        if (appCacheDir == null) {
            appCacheDir = context.getCacheDir();
        }
        if (appCacheDir == null) {
            Log.w(TAG, "Can't define system cache directory! The app should be re-installed.");
        }
        return appCacheDir;
    }
    //判断是否有读写条件
    private  boolean hasExternalStoragePermission() {
        int perm = context.checkCallingOrSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE");
        return perm == PackageManager.PERMISSION_GRANTED;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值