android检测最新版本并更新+安装apk是提示解析包错误

每个程序都会随着时间的推移更新新的版本,下面来介绍一下检测到新的版本并提示更新

思路:首先检测当前版本是否是最近版本,是无需任何操作,不是,就需要下载新的程序版本替换旧版本,并安装(大概就是这么个思路,下面就是具体的操作)

package cn.xu.test;

import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import cn.xu.test.utils.CommomDialog;

public class UpdateVersionActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_version);
    
        //实际开发中请求网络,对比服务器上的版本和当前本地上的版本   ,不同的提示版本更新
        //我本地的版本号是1,我将版本号写3,大于他
        try {
            if (3 > getCurrentVersionCode()) {
            //todo   这里是一个自定义弹出框,我在上一篇文章中有介绍是怎么封装的,不知道怎么写的小伙伴可以看我的上一篇文章在这里我附上上一章的地址https://blog.csdn.net/qq_42221857/article/details/100518167
                new CommomDialog(UpdateVersionActivity.this, R.style.dialog, "这里写提示更新的内容",
                        new CommomDialog.OnCloseListener() {
                            @Override
                            public void onClick(Dialog dialog, boolean confirm) {
                                if (confirm) {
                                    dialog.dismiss();
                                    //下载apk安装  todo注这里需要换上自己下载apk的地址
                                    downLoadApk("这里放下载apk安装包的地址,这个也是后台返回过来的地址");
                                }

                            }
                        }).setTitle("版本更新").show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
/**
*下载apk
*@param url 下载的地址
*/
    protected void downLoadApk(final String url) {
        //进度条
        final ProgressDialog pd;
        pd = new ProgressDialog(this);
        pd.setProgressNumberFormat("%1d M /%2d M");
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pd.setMessage("正在下载更新");
        pd.setCanceledOnTouchOutside(false);
        pd.setCancelable(true);//todo 点击返回取消
        pd.show();
        new Thread() {
            @Override
            public void run() {
                try {
                    File file = getFileFromServer(url, pd);
                    //安装APK
                    installApk(file);
                    pd.dismiss(); //结束掉进度条对话框
                } catch (Exception e) {
                }
            }
        }.start();

    }



    /**
     * 下载apk具体操作
     *
     * @param path 下载的地址
     * @param pd   下载进度条
     * @return
     * @throws Exception
     */
    public static File getFileFromServer(String path, ProgressDialog pd) throws Exception {
        //如果相等的话表示当前的sdcard挂载在手机上并且是可用的
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            //获取到文件的大小
            pd.setMax(conn.getContentLength() / 1024 / 1024);
            InputStream is = conn.getInputStream();
            File file = new File(Environment.getExternalStorageDirectory(), "soujianzhu.apk");
            FileOutputStream fos = new FileOutputStream(file);
            BufferedInputStream bis = new BufferedInputStream(is);
            byte[] buffer = new byte[1024];
            int len;
            int total = 0;
            while ((len = bis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
                total += len;
                //获取当前下载量
                pd.setProgress(total / 1024 / 1024);
            }
            fos.close();
            bis.close();
            is.close();
            return file;
        } else {
            return null;
        }

    }

    //安装程序
    protected void installApk(File file) {

        if (!file.exists()) {
            Toast.makeText(this, "下载的安装包不存在", Toast.LENGTH_SHORT).show();
            return;
        }
        //判读版本是否在7.0以上 todo 这里是7.0安装是会出现解析包的错误
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

            // todo 在AndroidManifest中的android:authorities值  当前应用的包名:cn.xu.test+FileProvider(数据共享)
            Uri apkUri = FileProvider.getUriForFile(this,
                    "cn.xu.test.FileProvider", file);
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            install.setDataAndType(apkUri, "application/vnd.android.package-archive");
            this.startActivity(install);

        } else {
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            this.startActivity(install);
        }

    }


    /**
     * 获取当前版本系统的版本号
     *
     * @return
     * @throws Exception
     */
    private int getCurrentVersionCode() throws Exception {
        //获取packagemanager的实例
        PackageManager packageManager = getPackageManager();
        //getPackageName()是你当前类的包名,0代表是获取版本信息
        PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0);
        return packageInfo.versionCode;
    }


}

AndroidManifest中的配置

  
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="cn.xu.test.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        provider>

在res下创建一个xml文件,在xml文件下创建file_paths.xml文件


<paths>
<external-path
    name="files_root"
    path="Android/data/cn.soujianzhu/" />
<external-path
    name="external_storage_root"
    path="." />
paths>

到这里就基本上完成了,如果安装上还是出现解析包错误的话,就在AndroidManifest加上一下权限

  
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

好啦,到这里就完成了,我在开发中遇到解析包出现错误就是这么操作的,然后解决了,今天拿出来和大家分享,共同成长!

你可能感兴趣的:(android检测最新版本并更新+安装apk是提示解析包错误)