Android中使用okhttp实现程序自动更新

实现程序自动更新,简单来说就是两步:

1、把自动更新apk程序下载到本地;

2、安装下载的apk程序


关于实现程序自动更新服务端相关操作可参考Spring Boot实现文件上传与下载

1、检查更新服务

public class UpdateService {

    private static OkHttpClient okHttpClient;

    public static void download(final String fileName, final UpdateCallback callback) {
        String url = "http://127.0.0.1:8090/springbootdemo/log/download/" + fileName;
        Request request = new Request.Builder()
                .addHeader("Accept-Encoding", "identity")
                .url(url).build();

        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient();
        }

        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callback.onFailure();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.body() == null) {
                    callback.onFailure();
                    return;
                }

                File filePath = new File(CommonConstants.DOWNLOAD_PATH);
                if (!filePath.exists()) {
                    filePath.mkdirs();
                }

                long contentLength = response.body().contentLength();
                byte[] buffer = new byte[1024];
                File file = new File(filePath.getCanonicalPath(), fileName);
                try (InputStream is = response.body().byteStream();
                     FileOutputStream fos = new FileOutputStream(file)) {
                    LoggerUtils.getLogger().info("保存路径:" + file);

                    int length;
                    long sum = 0;
                    while ((length = is.read(buffer)) != -1) {
                        fos.write(buffer, 0, length);
                        sum += length;
                        int progress = (int) (sum * 1.0f / contentLength * 100);
                        callback.onProgress(progress);
                    }
                    fos.flush();

                    callback.onSuccess();
                } catch (Exception e) {
                    callback.onFailure();
                }
            }
        });
    }

    public interface UpdateCallback {

        void onSuccess();

        void onProgress(int progress);

        void onFailure();
    }
}

2、检查更新界面

@ActivityLayoutInject(R.layout.activity_update)
public class UpdateActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @OnClick(R.id.menuBtnCheckUpdate)
    public void onClickCheckUpdate() {
        final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setCancelable(true);
        dialog.setTitle("正在下载");
        dialog.setMessage("请稍后...");
        dialog.setProgress(0);
        dialog.setMax(100);
        dialog.show();

        String fileName = "AndroidDemo-v1.0.0.0.apk";
        UpdateService.download(fileName, new UpdateService.UpdateCallback() {
            @Override
            public void onSuccess() {
                dialog.dismiss();

                if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    return;
                }

                File file = new File(CommonConstants.DOWNLOAD_PATH + fileName);
                try {
                    LoggerUtils.getLogger().info("安装文件目录:" + file);
                    LoggerUtils.getLogger().info("准备安装");
                    installApk(file);
                } catch (Exception e) {
                    LoggerUtils.getLogger().info("获取打开方式错误", e);
                }
            }

            @Override
            public void onProgress(int progress) {
                dialog.setProgress(progress);
            }

            @Override
            public void onFailure() {
                dialog.dismiss();
            }
        });
    }

    private void installApk(File file) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Uri fileUri;

        //Android7.0以上
        if (Build.VERSION.SDK_INT >= 24) {
            fileUri = FileProvider.getUriForFile(this,
                    BuildConfig.APPLICATION_ID + ".provider", file);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            fileUri = Uri.fromFile(file);
        }

        intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
        startActivity(intent);
    }
}

如果你的Android机器是7.0以下,到这里就可以了,但是如果是7.0以上,还需如下操作。

3、新建file_paths.xml文件

res\xml文件夹下新建file_paths.xml,path就是下载的apk存放目录

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="download"
        path="AndroidDemo/download/" />
</paths>

4、注册FileProvider

在AndroidManifest.xml的application下注册

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="cn.wbnull.androiddemo.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

5、注册读写权限

在AndroidManifest.xml中注册读写和网络权限

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

好了,到这里我们就实现最上视频中所示效果了。




GitHub:https://github.com/dkbnull/AndroidDemo




发布了92 篇原创文章 · 获赞 126 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/dkbnull/article/details/104088585