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中的配置

  <!-- 7.0安裝 -->
        <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加上一下權限

  <!-- 8.0手機安裝軟件 -->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <!-- 允許裝載和卸載文件系統權限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />


好啦,到這裏就完成了,我在開發中遇到解析包出現錯誤就是這麼操作的,然後解決了,今天拿出來和大家分享,共同成長!


————————————————
版權聲明:本文爲CSDN博主「SpringflowerXu」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_42221857/article/details/100542116

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章