Android版本升级下载Apk文件通知栏显示,进度条显示,自定义圆环显示,下载完成自动安装

Android版本升级下载Apk文件通知栏显示,进度条显示,自定义圆环显示,下载完成自动安装,第1张

版本升级简单思路就是,访问服务器,根据服务器返回数据,是否显示升级的d窗。如果点确定升级,就访问服务器上返回–下载地址的url(okhttp,DownloadManager),下载的进度条显示方式通知栏、d窗进度条百分比、自定义圆环显示。




一、下载Apk的两种方式(okhttp,DownloadManager)
1.DownloadManager
它自带通知栏显示,因此代码比较简单,在调用之前先判断下下载管理器是否被禁用。

    public static boolean isDownloadManagerAvailable(Context context) {
        int state = context.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");
        //检测下载管理器是否被禁用
        if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
                || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
            return false;
        }
        return true;
    }


DownLoadApk这个类下载状态做逻辑处理

public class DownLoadApk {
    public static void download(Context context, String url, String title, final String appName) {
        //获取存储id
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        long downloadId = sp.getLong(DownloadManager.EXTRA_DOWNLOAD_ID, -1L);
        if (downloadId != -1L) {
            FileDownloadManager fdm = FileDownloadManager.getInstance(context);
            int status = fdm.getDownloadStatus(downloadId);//获取下载状态
            switch (status) {
                case DownloadManager.STATUS_SUCCESSFUL:
                    //启动更新界面
                    Uri uri = fdm.getDownloadUri(downloadId);// 获取保存文件的路径
                    if (uri != null) {
                        if (compare(context, uri)) {
                            //本地的版本大于当前程序的版本直接安装
                            String path = getDownloadFilePath(context,downloadId);
                            startInstall(context, path);
                            return;
                        } else {
                            //从FileDownloadManager中移除这个任务
                            fdm.getDownloadManager().remove(downloadId);
                        }
                    }
                    //重新下载
                    start(context, url, title, appName);
                    break;
                case DownloadManager.STATUS_FAILED:
                    //失败
                    start(context, url, title, appName);
                    break;
                case DownloadManager.STATUS_RUNNING:
                    LogUtils.d("downloadId=" + downloadId + " ,status = STATUS_RUNNING");
                    break;
                case DownloadManager.STATUS_PENDING:
                    LogUtils.d("downloadId=" + downloadId + " ,status = STATUS_PENDING");
                    break;
                case DownloadManager.STATUS_PAUSED:
                    LogUtils.d("downloadId=" + downloadId + " ,status = STATUS_PAUSED");
                    break;
                default:
                    LogUtils.d("downloadId=" + downloadId + " ,status = " + status);
                    break;

            }
        } else {
            start(context, url, title, appName);
        }
    }

    private static void start(Context context, String url, String title, String appName) {
        long id = FileDownloadManager.getInstance(context).startDownload(context,url, title, "下载完成后点击打开", appName);
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        sp.edit().putLong(DownloadManager.EXTRA_DOWNLOAD_ID, id).apply();
        LogUtils.d("apk start download" + id);
    }

    public static void startInstall(Context context, String path) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri cDownloadUri = Uri.parse(path);
        if (cDownloadUri != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                File file = new File(cDownloadUri.getPath());
                String authority = context.getPackageName() + ".provider";
                Uri contentUri = FileProvider.getUriForFile(context, authority, file);
                intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                context.startActivity(intent);
            } else {
                intent.setDataAndType(cDownloadUri, "application/vnd.android.package-archive");
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            }

        }


    }
    /**
     * 获取apk程序信息[packageName,versionName...]
     *
     * @param context Context
     * @param path    apk path
     */
    private static PackageInfo getApkInfo(Context context, String path) {
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }
        PackageManager pm = context.getPackageManager();
        return pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
    }

    /**
     * 下载的apk和当前程序版本比较
     *
     * @param context Context 当前运行程序的Context
     * @param uri     apk file's location
     * @return 如果当前应用版本小于apk的版本则返回true;如果当前没有安装也返回true
     */
    public static boolean compare(Context context, Uri uri) {

        String realPathUri = getRealPathFromURI(context, uri);

        PackageInfo apkInfo = getApkInfo(context, realPathUri);
        if (apkInfo == null) {
            return false;
        }

        try {
            PackageInfo currentPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            //如果下载的apk包名和当前应用不同,则不执行更新 *** 作
             if (apkInfo.packageName.equals(currentPackageInfo.packageName))  {
                if (apkInfo.versionCode > currentPackageInfo.versionCode) {
                    return true;
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return true; //如果程序没有安装
        }
        return false;
    }

    private static String getRealPathFromURI(Context context, Uri contentURI) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Cursor cursor = context.getContentResolver().query(contentURI, null,
                    null, null, null);
            if (cursor != null) {
                try {
                    cursor.moveToFirst();
                    int index = cursor.getColumnIndex(MediaStore.MediaColumns.DATA);
                    return cursor.getString(index);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    cursor.close();
                }
            }
        } else {
            return contentURI.getPath();
        }
        return null;
    }


    @SuppressLint("Range")
    public static String getDownloadFilePath(Context context, long downloadId) {
        //获取下载管理器服务的实例
        DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        //创建一个查询对象
        DownloadManager.Query query = new DownloadManager.Query();
        //根据下载id过滤结果
        query.setFilterById(downloadId);
        //根据状态过滤结果
        query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
        //执行查询
        Cursor cursor = manager.query(query);
        if (!cursor.moveToFirst()) {
            cursor.close();
            return null;
        }
        String downloadFilePath;
        // 下载文件在本地保存的路径(Android 7.0以后COLUMN_LOCAL_FILENAME字段被弃用,
        // 需要用COLUMN_LOCAL_URI字段来获取本地文件路径的Uri)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            downloadFilePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
        } else {
            downloadFilePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
            downloadFilePath = downloadFilePath.startsWith("file://") ? downloadFilePath : "file://" + downloadFilePath;
        }
        //已下载字节大小
        long downloadedSoFar = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
        //下载文件总大小
        long totalSize = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
        if (downloadedSoFar == totalSize) {
            return downloadFilePath;
        }

        return null;
    }

}

需要在清单application中加入

 
            
        

二、使用okhttp下载,自己写d窗或者通知栏显示进度




调用

   DownloadUtils.getInstance().download(down_url, getFilePath(MainActivity.this), "QQ.apk", new DownloadUtils.OnDownloadListener() {

其中参数要传下载路径地址,保存文件的路径,文件的名称

 /**
     * 获得文件存储路径
     */
    private static String getFilePath(Context context) {

        if (Environment.MEDIA_MOUNTED.equals(Environment.MEDIA_MOUNTED) || !Environment.isExternalStorageRemovable()) {//如果外部储存可用
            return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator;
        } else {
            return context.getFilesDir().getPath();//直接存在/data/data里,非root手机是看不到的
        }
    }

下面是通知栏显示或者d窗显示
2.1通知栏显示

  private Notification.Builder builder;
  private NotificationManager mNotifyMgr;
  private static final int NO_3 = 0x3;
//下载的方法
 public void downloadApk(final Activity context, String down_url) {
        //标题栏
        initNotifications();
        mNotifyMgr.notify(NO_3, builder.build());
          DownloadUtils.getInstance().download(down_url, getFilePath(MainActivity.this), "QQ.apk", new DownloadUtils.OnDownloadListener() {
            @Override
            public void onDownloadSuccess() {
                //标题栏
                 mNotifyMgr.cancel(NO_3);//设置关闭通知栏
                String successDownloadApkPath = getFilePath(MainActivity.this) + "QQ.apk";
                installApk1(MainActivity.this, successDownloadApkPath);
            }

            @Override
            public void onDownloading(int progressInfo) {
                //标题栏
                mNotifyMgr.notify(NO_3, builder.build());
            }

            @Override
            public void onDownloadFailed() {
                //标题栏
                 mNotifyMgr.cancel(NO_3);//设置关闭通知栏
            }
        });


}

针对通知栏8.0处理

通用安装方法

private void installApk1(Context context, String downloadApkPath) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //是否有安装位置来源的权限
            boolean haveInstallPermission = getPackageManager().canRequestPackageInstalls();
            if (haveInstallPermission) {
                Log.d("测试", "8.0手机已经拥有安装未知来源应用的权限,直接安装!");
                AppUtils.installApk(context, downloadApkPath);
            } else {
                new CakeResolveDialog(context, "安装应用需要打开安装未知来源应用权限,请去设置中开启权限", () -> {
                    Uri packageUri = Uri.parse("package:" + context.getPackageName());
                    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri);
                    startActivityForResult(intent, 10086);
                }).show();
            }


        } else {
            AppUtils.installApk(context, downloadApkPath);
        }


    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 10086) {
            Log.d("测试", "设置了安装未知应用后的回调。。。");
            String successDownloadApkPath = getFilePath(MainActivity.this) + "QQ.apk";
            installApk1(MainActivity.this, successDownloadApkPath);
        }
    }
//------AppUtils 
public class AppUtils {
    public static  void installApk(Context context, String downloadApk) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        File file = new File(downloadApk);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            String authority = context.getPackageName() + ".provider";
            Uri contentUri = FileProvider.getUriForFile(context, authority, file);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            Uri uri = Uri.fromFile(file);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        }
        context.startActivity(intent);

    }
}

2.2d窗进度条

   progressDialog1 = new ProgressDialog(MainActivity.this);
        progressDialog1.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog1.setTitle("正在下载");
        progressDialog1.setMessage("请稍后...");
        progressDialog1.setProgress(0);
        progressDialog1.setMax(100);
        progressDialog1.show();
        progressDialog1.setCancelable(false);
        DownloadUtils.getInstance().download(down_url, getFilePath(MainActivity.this), "QQ.apk", new DownloadUtils.OnDownloadListener() {
            @Override
            public void onDownloadSuccess() {
                if (progressDialog1 != null && progressDialog1.isShowing()) {
                    progressDialog1.dismiss();
                }
                String successDownloadApkPath = getFilePath(MainActivity.this) + "QQ.apk";
                installApk1(MainActivity.this, successDownloadApkPath);
            }

            @Override
            public void onDownloading(int progressInfo) {
                progressDialog1.setProgress(progressInfo);
            }

            @Override
            public void onDownloadFailed() {
              progressDialog1.dismiss();
            }
        });

2.3简易圆环

public class DownloadCircleView extends View {
    Paint mBgPaint;
    Paint mStepPaint;
    Paint mTxtCirclePaint;
    Paint mTxtPaint;
    int outsideRadius=DpPxUtils.dp2px(100);
    int progressWidth =DpPxUtils.dp2px(2);
    float progressTextSize  = DpPxUtils.dp2px(12);
    Context context;
    public DownloadCircleView(Context context) {
        super(context);
    }
    public DownloadCircleView(Context context,  AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    public DownloadCircleView(Context context,  AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width;
        int height;
        int size = MeasureSpec.getSize(widthMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);

        if (mode == MeasureSpec.EXACTLY) {
            width = size;
        } else {
            width = (int) ((2 * outsideRadius) + progressWidth);
        }
        size = MeasureSpec.getSize(heightMeasureSpec);
        mode = MeasureSpec.getMode(heightMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            height = size;
        } else {
            height = (int) ((2 * outsideRadius) + progressWidth);
        }
        setMeasuredDimension(width, height);
    }

    private void init(Context context) {
        int progressColor = Color.parseColor("#FF5836");//进度球颜色
        this.context = context;
        //灰色背景圆环
        mBgPaint = new Paint();
        mBgPaint.setStrokeWidth(progressWidth);
        mBgPaint.setColor(Color.GRAY);
        this.mBgPaint.setAntiAlias(true);
        this.mBgPaint.setStyle(Paint.Style.STROKE); //绘制空心圆
        //进度圆环
        mStepPaint = new Paint();
        mStepPaint.setStrokeWidth(progressWidth);
        mStepPaint.setColor(progressColor);
        this.mStepPaint.setAntiAlias(true);
        this.mStepPaint.setStyle(Paint.Style.STROKE); //绘制空心圆
        //进度卫星球
        mTxtCirclePaint = new Paint();
        mTxtCirclePaint.setColor(progressColor);
        this.mTxtCirclePaint.setAntiAlias(true);
        this.mTxtCirclePaint.setStyle(Paint.Style.FILL); //绘制实心圆
        //进度文字5%
        mTxtPaint = new Paint();
        mTxtPaint.setTextSize(progressTextSize);
        mTxtPaint.setColor(Color.WHITE);
        this.mTxtPaint.setAntiAlias(true);

    }
    float maxProgress=100f;
    float progress  =0f;

    public void setProgress(float progress) {
        this.progress = progress;
        postInvalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //灰色圆圈
        int circlePoint = getWidth() / 2;
        canvas.drawCircle(circlePoint, circlePoint, outsideRadius, mBgPaint); //画出圆
        //进度
        RectF oval = new RectF();
        oval.left=circlePoint - outsideRadius;
        oval.top=circlePoint - outsideRadius;
        oval.right=circlePoint + outsideRadius;
        oval.bottom=circlePoint + outsideRadius;
        float range = 360 * (progress / maxProgress);
        canvas.drawArc(oval, -90,  range, false, mStepPaint);  //根据进度画圆弧
        //轨道圆和文字
        double x1 = circlePoint + outsideRadius * Math.cos((range-90) * 3.14 / 180);
        double y1 = circlePoint + outsideRadius * Math.sin((range-90) * 3.14 / 180);
        canvas.drawCircle((float) x1, (float) y1, progressTextSize*1.3f, mTxtCirclePaint);
        String txt = (int) progress + "%";
        float strwid  = mTxtPaint.measureText(txt);//直接返回参数字符串所占用的宽度
        canvas.drawText(txt,(float) x1-strwid/2, (float) y1+progressTextSize/2-progressWidth/2,mTxtPaint);

    }
}



    

    

    

public class DownloadCircleDialog extends Dialog {
    public DownloadCircleDialog(Context context) {
        super(context, R.style.Theme_Ios_Dialog);
    }
    DownloadCircleView circleView;
    TextView tvMsg;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.download_circle_dialog_layout);
        this.setCancelable(false);//设置点击d出框外部,无法取消对话框
        circleView = findViewById(R.id.cir);
        tvMsg = findViewById(R.id.tv_msg);
    }
    public void setProgress(int progress) {
        circleView.setProgress(progress);
    }
    public void setMsg(String msg){
        tvMsg.setText(msg);
    }
}

只是记录下,写的不完美,如果你看到了这篇文章,有帮助的话,还是很棒的,毕竟资源现在都是要会员。或者有问题请联系。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/992779.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存