Android软件在线更新实战

android软件内在线更新已经算是android开发中必不可少的环节了,我也是因为项目需求,花了半天的时候调试好了前后端,期间参考了诸多博客,由于没有做记录,这里就不引用了。不多bb,直接上代码:

下面是工具类:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 文件下载工具类(单例模式)
 */

public class DownloadUtil {

    private static DownloadUtil downloadUtil;
    private final OkHttpClient okHttpClient;

    public static DownloadUtil get() {
        if (downloadUtil == null) {
            downloadUtil = new DownloadUtil();
        }
        return downloadUtil;
    }

    public DownloadUtil() {
        okHttpClient = getUnsafeOkHttpClient();

    }
    private  OkHttpClient getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[] {
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            OkHttpClient okHttpClient = builder.build();
            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称,后面记得拼接后缀,否则手机没法识别文件类型
     * @param listener     下载监听
     */

    public void download(final String url, final String destFileDir, final String destFileName, final OnDownloadListener listener) {

        Request request = new Request.Builder()
                .url(url)
                .build();

        //异步请求
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 下载失败监听回调
                listener.onDownloadFailed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;

                //储存下载文件的目录
                File dir = new File(destFileDir);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dir, destFileName);

                try {

                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        //下载中更新进度条
                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    //下载完成
                    listener.onDownloadSuccess(file);
                } catch (Exception e) {
                    listener.onDownloadFailed(e);
                }finally {

                    try {
                        if (is != null) {
                            is.close();
                        }
                        if (fos != null) {
                            fos.close();
                        }
                    } catch (IOException e) {

                    }

                }


            }
        });
    }


    public interface OnDownloadListener{

        /**
         * 下载成功之后的文件
         */
        void onDownloadSuccess(File file);

        /**
         * 下载进度
         */
        void onDownloading(int progress);

        /**
         * 下载异常信息
         */

        void onDownloadFailed(Exception e);
    }
}

下面是应用:

	private static ProgressDialog progressDialog = null;
	private final static int MAXVALUE = 100;
	private String apkFilePath=null;

	/**
     * 文件下载
     */
    private void downFile(String url) {
        DownloadUtil.get().download(url, apkFilePath, "kylvd.apk",
                new DownloadUtil.OnDownloadListener() {
                    @Override
                    public void onDownloadSuccess(File file) {
                        Log.e("tag","down success");
                        sendMsg(2,0);
                        sendMsg(3,0);
                    }


                    @Override
                    public void onDownloading(int progress) {
                        sendMsg(1,progress);

                    }

                    @Override
                    public void onDownloadFailed(Exception e) {
                        sendMsg(2,0);
                        Log.e("tag","down Failed");

                    }
                });
    }
	//安装apk,这里需要注意,8.0之后不可以把url直接暴露,需要先建立一个共享文件,再安装
	private void installAPK() {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        File apkFile = new File(apkFilePath+"/xxxx.apk");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri uri = FileProvider.getUriForFile(MainActivity.this, "com.example.administrator.provider", apkFile);//com.example.administrator.provider即是共享文件区
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
        }
        startActivity(intent);

    };
    //软件更新对话框
    private void alertSofetUpdata(){
        final TextView tv=new TextView(this);
        tv.setText("\n    检测到有新版本软件,点击确定更新\n\n");
        tv.setTextSize(alert_text_size);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("警告")
                .setIcon(R.mipmap.warning)
                .setView(tv)
                .setPositiveButton("    确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        if (progressDialog ==null){
                            progressDialog = new ProgressDialog(MainActivity.this);
                            progressDialog.setMax(MAXVALUE);
                            progressDialog.setTitle("软件下载中");
                            progressDialog.setMessage("软件下载中,请稍后...");
                            //这里设置为不可以通过按取消按钮关闭进度条
                            progressDialog.setCancelable(false);
                            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                            //这里设置的是是否显示进度,设为false才是显示的哦!
                            progressDialog.setIndeterminate(false);
                            progressDialog.show();
                        }
                        downFile("http://xxxx");
                    }
                })
                .setNegativeButton("取消    ",null);
        AlertDialog dialog = builder.create();
        dialog.show();
        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextSize(24);
        dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextSize(24);

    }
     /**
     * 发送Handler
     */
    public void sendMsg(int what, Object object) {
        Message msg = new Message();
        msg.what = what;
        msg.obj = object;
        mHandler.sendMessage(msg);
    }

    /**
     * Handler
     */
    private Handler mHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    progressDialog.setProgress((int)msg.obj);
                    break;
                case 2:
                    progressDialog.dismiss();
                    progressDialog=null;
                    break;
                case 3:
                    installAPK();
                    break;
                }
            }
       };

在Manifest中添加共享文件,注意,android:authorities=“com.example.administrator.provider"需要修改为自己的包名,android:resource=”@xml/filepaths"为文件路径

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.administrator.provider"
            android:exported="false"
            android:grantUriPermissions="true"
            tools:ignore="WrongManifestParent">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>

下面建立在res下建立xml/filepaths文件,path修改为自己的包名

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="files_root" path="Android/data/com.example.administrator.demo/"/>
</paths>

以上是android端的代码,后端实现起来比较简单了,建立一个文件下载服务器,建立一个http服务器,android请求服务,对比服务器版本和当前版本,不一致则下载更新。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值