使用OKGO进行软件版本更新、下载、安装等操作

在各大APP软件中都含有一个功能,就是在软件中进行检查软件版本号,并进行下载安装的操作。
今天,我也记录一下,我使用OkGo网络协议进行软件版本更新的操作。
一、基础配置
1.如果安卓版本号是安卓9或更高版本,如要在application中添加
android:usesCleartextTraffic=“true” 。这句话。因为在安卓高版本中,谷歌对设备访问网络做了限制,具体原因可以去查询。
2. 在Mainfest.xml中,添加权限。

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 <uses-permission android:name="android.permission.INTERNET"/>

 <!--下面这个权限一定还要添加,否则程序不会自动安装-->
 <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

开启未知应用安装权限的入口,并设置允许安装。
3.创建一个空类,继承自FileProvider

//空类
public class MyFileProvider extends FileProvider {

}

4.创建res/xml/fiel_path.xml文件

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">

   <!-- 其中external-path节点表示Environment.getExternalStorageDirectory()路径
    path表示apk文件在Environment.getExternalStorageDirectory()路径下的文件夹名称-->

    <external-path name="external_storage_root" path="download" />
</paths>

5.清单文件中添加provider

<provider
      android:name="com.example.updatesoft.MyFileProvider"
       android:authorities="${applicationId}.MyFileProvider"
       android:exported="false"
       android:grantUriPermissions="true">
       <meta-data
           android:name="android.support.FILE_PROVIDER_PATHS"
           android:resource="@xml/file_paths"/>
</provider>

二.在MainActivity的布局文件中

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <!--更新按钮-->
    <TextView
        android:id="@+id/text_iew"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="更新软件按钮"
        android:layout_gravity="center"
        android:layout_marginTop="50dp"
        android:background="@drawable/bg_button_pressed"
        android:padding="10dp"/>
   
    <!--版本信息-->    
    <TextView
        android:id="@+id/version_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="这是1.0版本"
        android:layout_marginTop="50dp"/>

    <!--下载进程圆圈-->
    <ProgressBar
        android:id="@+id/progress_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:visibility="gone"/>

    <!--下载进程-->
    <TextView
        android:id="@+id/tvDownloadSize"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text=""
        android:layout_marginTop="50dp"/>
</LinearLayout>

三.安卓6.0之后需要动态添加权限,需要访问本地文件

//android6.0之后要动态获取权限
    private void checkPermission(Activity activity) {
        // Storage Permissions
        final int REQUEST_EXTERNAL_STORAGE = 1;
        String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE};
        try {
            //检测是否有写的权限
            int permission = ActivityCompat.checkSelfPermission(MainActivity.this,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 没有写的权限,去申请写的权限,会弹出对话框
                ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

四.进行版本号比较
获取本地的版本号与云端版本号。通过比较两个版本号信息,判断时候需要进行版本更新操作。如果本地的版本号小于云端版本号,就可以进行下载并安装的操作。但是本地的版本号与云端版本号相同,就无需进行下载安装,并可以对用户进行提示。
获取本地版本号的方法:

/**
     * 获取当前软件版本信息
     * 根据包名获取应用程序相关信息
     * flags:指定信息的标签,指定了标签就会获取相应的相关信息
     * getPackageName():获取应用程序的包名
     */
    public static String getPresentVersion(Context context) {
        String presentVersion = "";
        PackageManager packageManager = context.getPackageManager();    //包的管理者,获取应用程序中清单文件中的信息
        try {
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            presentVersion = packageInfo.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();                                      //找不到包的异常
        }
        return presentVersion;
    }

版本号比较大小的方法:

/**
     * 版本号比较
     * 0代表相等,1代表version1大于version2,-1代表version1小于version2
     *
     * @param version1
     * @param version2
     * @return
     */
    private static int compareVersion(String version1, String version2) {
        if (version1.equals(version2)) {
            return 0;
        }
        String[] version1Array = version1.split("\\.");
        String[] version2Array = version2.split("\\.");
        int index = 0;
        // 获取最小长度值
        int minLen = Math.min(version1Array.length, version2Array.length);
        int diff = 0;
        // 循环判断每位的大小
        while (index < minLen
                && (diff = Integer.parseInt(version1Array[index])
                - Integer.parseInt(version2Array[index])) == 0) {
            index++;
        }
        if (diff == 0) {
            // 如果位数不一致,比较多余位数
            for (int i = index; i < version1Array.length; i++) {
                if (Integer.parseInt(version1Array[i]) > 0) {
                    return 1;
                }
            }

            for (int i = index; i < version2Array.length; i++) {
                if (Integer.parseInt(version2Array[i]) > 0) {
                    return -1;
                }
            }
            return 0;
        } else {
            return diff > 0 ? 1 : -1;
        }
    }

通过OkGo获取云端版本号并进行版本比较的方法

public void upApk(){
        //StyledDialog.buildMdLoading("正在获取新版本信息,请稍等").show();
        OkGo.<String>post("这里填写获取APK的云端服务器地址")
                .tag(this)
                .params("appId","1")          //向服务器传送请求appId为1的软件信息,这里根据自己的实际情况进行填写。
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        JSONObject jsonObject = null;
                        try {
                            jsonObject = new JSONObject(response.body());
                            String dataStr = jsonObject.getString("data");
                            JSONObject dataObj = new JSONObject(dataStr);
                            String cloudVersion = dataObj.getString("version");        //获取云端版本号
                            String presentVersion = getPresentVersion(MainActivity.this);
                            String apkPath=dataObj.getString("apk");//获取云端软件的下载地址
                            if (compareVersion(presentVersion,cloudVersion)==-1) {        //比较两个版本号,判断是否需要下载
                                Toast.makeText(MainActivity.this, "可以更新", Toast.LENGTH_LONG).show();
                                downloadApk(apkPath);
                            }else{
                             Toast.makeText(MainActivity.this, "已是最新版本", Toast.LENGTH_LONG).show();
                             }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onError(Response<String> response) {
                        Toast.makeText(MainActivity.this, "访问出错了", Toast.LENGTH_LONG).show();
                        super.onError(response);
                    }

                    @Override
                    public void onFinish() {
                        super.onFinish();
                        //StyledDialog.dismissLoading(MainActivity.this);
                    }
                });
    }

五.下载APK

/**
 * @description  下载APK
 */
public void downloadApk(String apkPath){
    String headStr = "这里填写获取APK的云端服务器地址";
    final String downloadFile = headStr + apkPath;
    final String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/download"; //APK的下载目录
    final String fileName = "abc.apk";  //下载的APK的新文件名
    file = new File(filePath + "/" + fileName);
    file = new File(filePath);
    if (file.exists())
        file.delete();

    final Context finalContext = context;
    OkGo.<File>post(downloadFile)
            .tag(context)
            .execute(new FileCallback(filePath,fileName) {
                @Override
                public void onSuccess(Response<File> response) {
                    String absolutePath = response.body().getAbsolutePath();
                    File apkFile = response.body().getAbsoluteFile();
                }
                //@Override
                @SuppressLint("SetTextI18n")
                public void downloadProgress(Progress progress) {
                    super.downloadProgress(progress);
                    //如何拿到当前的下载进度
                    progressBar.setVisibility(View.VISIBLE);
                    //progressBar.setProgress((int)(progress.fraction*100));
                    //这里回调下载进度(该回调在主线程,可以直接更新ui)
                    //currentSize totalSize以字节byte为单位
                    Log.e("currentSize", String.valueOf(progress.currentSize));     //当前下载大小
                    Log.e("totalSize", String.valueOf(progress.totalSize));         //APK总的大小值
                    Log.e("speed", String.valueOf(progress.speed));                 //下载速度
                    tvDownloadSize.setText(progress.currentSize + "/" + progress.totalSize);
                    if (progress.currentSize==progress.totalSize){
                        progressBar.setVisibility(View.GONE);
                        installApk();                                              //下载完后进行安装APK
                    }
                }
            });
}

六.安装APK

private void installApk() {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        String type = "application/vnd.android.package-archive";
        Uri uri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            uri = FileProvider.getUriForFile(MainActivity.this, "com.example.updatesoft.MyFileProvider",getApkFile());
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            uri = Uri.fromFile(getApkFile());
        }
        intent.setDataAndType(uri, type);
        MainActivity.this.startActivity(intent);
    }

获取本地APK文件

/**
 * 获取本地Apk文件
 */
private static File getApkFile() {
    String apkDir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
            + "download" + File.separator;
    String apkName = "abc.apk";
    File newApkFile = new File(apkDir, apkName);       //File()的第一个参数为文件的父路径,第二个参数是文件名
    return newApkFile;
}

整个操作流程到此就完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nanjumufeng

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值