Android安卓应用自动更新

1.判断版本

public static void judgeVersion() {
    ApiService.getAndroidAppVersion().subscribe(new CallBack<UpdateEntity>() {
        @Override
        protected void errorBody(String code, String message, String result) {
            ToastUtils.showToast(message);
        }

        @Override
        protected void requestBody(UpdateEntity data, String message) {
            UpdateEntity.AvBean av = data.getAv();
            if (av == null) {
                return;
            }
            int myVersionCode = Integer.parseInt(av.getAndroidCode());
            try {
                int currentVersionCode = BaseApplication.getCurrentActivity().getPackageManager().getPackageInfo(BaseApplication.getCurrentActivity().getPackageName(), 0).versionCode;
                if (currentVersionCode < myVersionCode) {
                    DialogUpdate dialog = DialogUpdate.newInstance(JsonUtils.ObjectToJson(av));
                    dialog.show(BaseApplication.getCurrentActivity().getFragmentManager(), "DialogUpdate");
                }
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
        }
    });
}

2.更新弹窗

public class DialogUpdate extends DialogFragment {


    @BindView(R.id.strUpgradeDialogVersionLabel)
    TextView strUpgradeDialogVersionLabel;
    @BindView(R.id.tv_content)
    TextView tvContent;
    @BindView(R.id.tv_update)
    TextView tvUpdate;
    @BindView(R.id.iv_close)
    ImageView ivClose;
    private UpdateEntity.AvBean avBean;

    public static DialogUpdate newInstance(String value) {
        DialogUpdate dialog = new DialogUpdate();
        Bundle args = new Bundle();
        args.putString("value", value);
        dialog.setArguments(args);
        return dialog;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String value = getArguments().getString("value");
        avBean = JsonUtils.jsonToObject(value, UpdateEntity.AvBean.class);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        getDialog().setCanceledOnTouchOutside(false);
        getDialog().setCancelable(false);
        // 重新返回方法,禁止返回键
        getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    return true;
                } else {
                    return false;
                }
            }
        });
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        View view = LayoutInflater.from(getActivity()).inflate(R.layout.upgrade_dialog, null);
        ButterKnife.bind(this, view);
        //设置值
        setData();
        builder.setView(view);
        return builder.create();
    }

    /**
     *
     */
    private void setData() {
        //是否强制更新
        String androidStatus = avBean.getAndroidStatus();
        if (androidStatus!=null&&"0".equals(androidStatus)) {
            ivClose.setVisibility(View.VISIBLE);
        }else {
            ivClose.setVisibility(View.GONE);
        }
        //版本号
        strUpgradeDialogVersionLabel.setText(avBean.getAndroidVersion());
        //内容
        if (avBean.getAndroidContent().contains("\\n")) {
            String replace = avBean.getAndroidContent().replace("\\n", "\n");
            tvContent.setText(replace);
        } else {
            tvContent.setText(avBean.getAndroidContent());
        }
    }


    @OnClick({R.id.tv_update, R.id.iv_close})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.tv_update:
                DownApkUptils.down(avBean.getAndroidDownUrl(), tvUpdate);
                break;
            case R.id.iv_close:
                getDialog().dismiss();
                break;
        }
    }
}

3.弹窗布局

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/bg_transparent_0fff"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="560mm"
        android:layout_height="wrap_content">

        <ImageView
            android:layout_width="560mm"
            android:layout_height="239mm"
            android:scaleType="centerCrop"
            android:src="@mipmap/upgrade" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="77mm"
            android:layout_marginTop="90mm"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="全新升级"
                android:textColor="@color/White"
                android:textSize="@dimen/jl_36" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/strUpgradeDialogVersionLabel"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="1.0"
                    android:textColor="@color/White"
                    android:textSize="@dimen/font_40"
                    android:textStyle="bold" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="版"
                    android:textColor="@color/White"
                    android:textSize="@dimen/jl_36" />
            </LinearLayout>

        </LinearLayout>
    </RelativeLayout>

    <LinearLayout
        android:layout_width="560mm"
        android:layout_height="wrap_content"
        android:background="@color/White"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:paddingBottom="@dimen/jl_60"
        android:paddingLeft="@dimen/jl_40"
        android:paddingRight="@dimen/jl_40"
        android:paddingTop="@dimen/jl_44">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="全新升级来啦"
            android:textColor="@color/font_0"
            android:textSize="@dimen/font_40"
            android:textStyle="bold" />

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="@dimen/jl_200"
            android:scrollbars="vertical"
            android:layout_marginTop="@dimen/jl_50">

            <TextView
                android:id="@+id/tv_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:lineSpacingExtra="@dimen/jl_39"
                android:textColor="@color/font_0"
                android:textSize="@dimen/font_28" />
        </ScrollView>

        <TextView
            android:id="@+id/tv_update"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/jl_60"
            android:background="@drawable/shape_btn_bg_f329"
            android:gravity="center"
            android:paddingBottom="@dimen/jl_28"
            android:paddingTop="@dimen/jl_28"
            android:text="立即升级"
            android:textColor="@color/White"
            android:textSize="@dimen/font_34"
            android:textStyle="bold" />
    </LinearLayout>

    <ImageView
        android:id="@+id/iv_close"
        android:layout_width="@dimen/jl_80"
        android:layout_height="@dimen/jl_80"
        android:layout_marginTop="@dimen/jl_50"
        android:src="@mipmap/update_close" />
</LinearLayout>

4.更新文件下载

public class DownApkUptils {
    private static long downloadLength = 0;
    private static long contentLength = 0;
//    private static File file;

    public static void down(final String downloadUrl, final TextView textView) {
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                downApk(downloadUrl, emitter);
            }
        }).subscribeOn(Schedulers.io())// 将被观察者切换到子线程
                .observeOn(AndroidSchedulers.mainThread())// 将观察者切换到主线程
                .subscribe(new Observer<Integer>() {

                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(Integer result) {
                        //设置ProgressDialog 进度条进度
//                        progressBar.setProgress(result);
                        textView.setText(result + "%");
                    }

                    @Override
                    public void onError(Throwable e) {
                        ToastUtils.showToast("网络异常!请重新下载");
                        textView.setEnabled(true);
                    }

                    @Override
                    public void onComplete() {
                        ToastUtils.showToast("服务器异常!请重新下载");
                        textView.setEnabled(true);
                    }
                });
    }

    /**
     * //下载apk
     *
     * @param downloadUrl
     * @param emitter
     */
    private static void downApk(final String downloadUrl, final ObservableEmitter<Integer> emitter) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(downloadUrl)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //下载失败
                breakpoint(downloadUrl, emitter);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.body() == null) {
                    //下载失败
                    breakpoint(downloadUrl, emitter);
                    return;
                }
                InputStream is = null;
                FileOutputStream fos = null;
                byte[] buff = new byte[2048];
                int len;
                try {
                    is = response.body().byteStream();
                    File  file = createFile();
                    fos = new FileOutputStream(file);
                    long total = response.body().contentLength();
                    contentLength = total;
                    long sum = 0;
                    while ((len = is.read(buff)) != -1) {
                        fos.write(buff, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        //下载中,更新下载进度
                        emitter.onNext(progress);
                        downloadLength = sum;
                    }
                    fos.flush();
                    //4.下载完成,安装apk
                    installApk(BaseApplication.getCurrentActivity(), file);
                } catch (Exception e) {
                    e.printStackTrace();
                    breakpoint(downloadUrl, emitter);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                        if (fos != null)
                            fos.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * //断点续传
     *
     * @param downloadUrl
     * @param emitter
     */
    private static void breakpoint(final String downloadUrl, final ObservableEmitter<Integer> emitter) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(downloadUrl)
                .addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //下载失败
                breakpoint(downloadUrl, emitter);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.body() == null) {
                    //下载失败
                    breakpoint(downloadUrl, emitter);
                    return;
                }
                InputStream is = null;
                RandomAccessFile randomFile = null;
                byte[] buff = new byte[2048];
                int len;

                try {
                    is = response.body().byteStream();
                    //文件路径是公共的DCIM目录下的/apk
                    String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "apkname";
                    File storageDir = new File(storagePath);
                    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
                    storageDir.mkdirs();
                    File  file = File.createTempFile(timeStamp, ".apk", storageDir);
                    randomFile = new RandomAccessFile(file, "rwd");
                    randomFile.seek(downloadLength);
                    long total = contentLength;
                    long sum = downloadLength;
                    while ((len = is.read(buff)) != -1) {
                        randomFile.write(buff, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        //下载中,更新下载进度
                        emitter.onNext(progress);
                        downloadLength = sum;
                    }
                    //4.下载完成,安装apk
                    installApk(BaseApplication.getCurrentActivity(), file);
                } catch (Exception e) {
                    e.printStackTrace();
                    breakpoint(downloadUrl, emitter);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                        if (randomFile != null)
                            randomFile.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * 路径为根目录
     */
    private static File createFile() {

        //文件路径是公共的DCIM目录下的/camerademo目录
        String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "apkname";
        File storageDir = new File(storagePath);
        storageDir.mkdirs();
        File file = null;
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        try {
            if (file != null && file.exists()) {
                file.delete();
            }
            file = File.createTempFile(timeStamp, ".apk", storageDir);
            return file;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * //安装apk,包含7.0
     * @param context
     * @param file
     */
    private static void installApk(Context context, File file) {
        if (context == null) {
            return;
        }

        String authority = context.getApplicationContext().getPackageName() + ".fileprovider";
        Uri apkUri = FileProvider.getUriForFile(context, authority, file);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //判读版本是否在7.0以上
        if (Build.VERSION.SDK_INT >= 24) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
        }
        context.startActivity(intent);
        //弹出安装窗口把原程序关闭。
        //避免安装完毕点击打开时没反应
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                Process.killProcess(android.os.Process.myPid());
            }
        },1000);
    }
}

5.清单文件里的配置

 		<!-- 用于应用更新 -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="包名.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/update_file_paths" />
        </provider>

6.res文件下的xml文件provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
    <external-path name="beta_external_path" path="Download/"/>
    <!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
    <external-path name="beta_external_files_path" path="Android/data/"/>
</paths>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杨Army

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值