Android应用开发之Android应用版本更新,断点下载并安装方法
凌雪 2018-10-24 来源 :网络 阅读 844 评论 0

摘要:本文将带你了解Android应用开发之Android应用版本更新,断点下载并安装方法,希望本文对大家学Android有所帮助。

本文将带你了解Android应用开发之Android应用版本更新,断点下载并安装方法,希望本文对大家学Android有所帮助。

Android应用版本更新,断点下载并安装方法。
1.依赖:
//《Okhttp网络请求依赖》implementation   'com.squareup.okhttp3:okhttp:3.10.0'//《Gson解析依赖》implementation   'com.google.code.gson:gson:2.8.2'//《Butterknife依赖(黄油刀)》implementation   'com.jakewharton:butterknife:8.8.1'annotationProcessor   'com.jakewharton:butterknife-compiler:8.8.1'
 .权限
<uses-permission   android:name="android.permission.INTERNET"/><uses-permission   android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"      tools:ignore="ProtectedPermissions"   /><uses-permission   android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

3.封装的外层Bean
 package   com.example.dell.versionupdatedemo05.bean; public   class   MessageBean{    private   Boolean   Success;    private   String   msg;    private   T data;     public   Boolean getSuccess()   {        return   Success;    }     public   void setSuccess(Boolean success)   {        Success   =   success;    }     public   String getMsg()   {        return   msg;    }     public   void setMsg(String msg)   {        this.msg   =   msg;    }     public   T getData() {        return   data;    }     public   void setData(T data) {        this.data   = data;    }}
4.封装的内层Bean
 package   com.example.dell.versionupdatedemo05.bean; public   class VersionInfo {    private   int last_must_update;//需强制更新的版本      private int   last_version;//需更新的版本      private String   md5;//Md5码      private String   url;//下载地址      public int getLast_must_update()   {        return   last_must_update;    }     public   void setLast_must_update(int   last_must_update)   {        this.last_must_update   =   last_must_update;    }     public   int getLast_version()   {        return   last_version;    }     public   void setLast_version(int   last_version) {        this.last_version   =   last_version;    }     public   String getMd5() {        return   md5;    }     public   void setMd5(String md5)   {        this.md5   =   md5;    }     public   String getUrl()   {        return   url;    }     public   void setUrl(String url)   {        this.url   = url;    }}
 
5.定义成功与失败的接口
package   com.example.dell.versionupdatedemo05; //定义成功与失败的方法public   interface NetCallBack   {    void Success(Object   o);    void Error(Throwable   t);}
6.网络请求的工具类
package   com.example.dell.versionupdatedemo05.utils; import   android.os.Handler;import   com.example.dell.versionupdatedemo05.NetCallBack;import   com.google.gson.Gson;import   java.io.IOException;import   java.lang.reflect.Type;import   okhttp3.Call;import   okhttp3.Callback;import   okhttp3.OkHttpClient;import   okhttp3.Request;import   okhttp3.Response; public class   HttpUtils {    //1.创建一个私有的静态的单列模式      private static volatile HttpUtils   instance;    //13.创建一个公有的Handler      public Handler handler   = new Handler()   {};    private final OkHttpClient   client;    //2.创建一个私有的构造方法      private   HttpUtils(){        //9.创建OkHttpClient          client = new   OkHttpClient();    }    //3.提供一个公有的静态方法      public static HttpUtils   getInstance(){        //4.判空          if(instance==null){            //5.添加同步锁              synchronized   (HttpUtils.class){                if(null==instance){                    //6.双向判空后 进行创建                      instance = new   HttpUtils();                }            }        }        //7.返回instance          return   instance;    }    //8.创建一个方法 进行请求数据      public void getData(String url,   final Type type, final   NetCallBack netCallBack){        //10.创建Request对象          final Request request =   new   Request.Builder()                .url(url)                .get()                .build();        //11.创建Call对象          Call call =   client.newCall(request);        //12.进行异步请求          call.enqueue(new Callback()   {            //失败的方法              @Override            public   void onFailure(Call call,final   IOException e)   {                //19.将失败的信息进行返回                  handler.post(new   Runnable() {                    @Override                    public   void run() {                        netCallBack.Error(new   Throwable(e));                    }                });            }            //成功的方法              @Override            public   void onResponse(final Call call,   Response response) throws IOException   {                //14.创建NetCallBack的接口                  // 15.解析数据                  String data =   response.body().string();                //16.使用Gson进行解析                  Gson gson = new   Gson();              final    Object o = gson.fromJson(data,   type);                //17.使用handler发送消息                  handler.post(new   Runnable() {                    @Override                    public   void run() {                        //18.将传给的信息进行返回                          netCallBack.Success(o);                    }                });            }        });    }}
7.获取应用版本的工具类
package   com.example.dell.versionupdatedemo05.utils; import   android.content.Context;import   android.content.pm.PackageInfo;import   android.content.pm.PackageManager; public   class VersionUtils {    //创建方法 得到本地版本      public static int   getVersionCode(Context   context){        //拿到包的管理器          PackageManager packageManager =   context.getPackageManager();        PackageInfo   packageInfo=null;        try   {            //通过包名拿到版本号              packageInfo =   packageManager.getPackageInfo(context.getPackageName(),   0);        } catch   (PackageManager.NameNotFoundException e)   {            e.printStackTrace();        }        //返回版本号          return   packageInfo.versionCode;    }}
 18.MD5判断的工具类
package   com.example.dell.versionupdatedemo05.utils; import   java.io.File;import   java.io.FileInputStream;import   java.math.BigInteger;import   java.security.MessageDigest; public class   FileMd5Utils {    public   static String getFileMD5(File file)   {        if   (!file.isFile())   {            return   null;        }        MessageDigest   digest =   null;        FileInputStream   in = null;        byte   buffer[] = new   byte[1024];        int   len;        try   {            digest   =   MessageDigest.getInstance("MD5");            in   = new   FileInputStream(file);            while   ((len = in.read(buffer, 0, 1024)) != -1)   {                digest.update(buffer,   0,   len);            }            in.close();        }   catch (Exception e)   {            e.printStackTrace();            return   null;        }        BigInteger   bigInt = new BigInteger(1,   digest.digest());        return   bigInt.toString(16);    }}
   
    9.Activity
 package   com.example.dell.versionupdatedemo05; import   android.app.ProgressDialog;import   android.content.DialogInterface;import   android.content.Intent;import   android.content.SharedPreferences;import   android.net.Uri;import   android.os.Bundle;import   android.os.Environment;import   android.support.v7.app.AlertDialog;import   android.support.v7.app.AppCompatActivity;import   android.util.Log;import   android.widget.Button;import   android.widget.TextView;import   android.widget.Toast;import   com.example.dell.versionupdatedemo05.bean.MessageBean;import   com.example.dell.versionupdatedemo05.bean.VersionInfo;import   com.example.dell.versionupdatedemo05.utils.FileMd5Utils;import   com.example.dell.versionupdatedemo05.utils.HttpUtils;import   com.example.dell.versionupdatedemo05.utils.VersionUtils;import   com.google.gson.reflect.TypeToken;import   java.io.File;import   java.io.IOException;import   java.io.InputStream;import java.io.RandomAccessFile;import   java.lang.reflect.Type;import   butterknife.BindView;import   butterknife.ButterKnife;import butterknife.OnClick;import   okhttp3.Call;import   okhttp3.Callback;import   okhttp3.OkHttpClient;import   okhttp3.Request;import okhttp3.Response; public   class MainActivity extends   AppCompatActivity   {     @BindView(R.id.mian_show)    TextView   mian_Show;    @BindView(R.id.mian_btn)    Button   mian_Btn;    private   Boolean isMust =   false;//定义状态默认为false      private File   file;//初始化地址      private ProgressDialog   dialog;//初始化下载进度条      private static final int   INTENT_APK =   0X123;//创建十六进制数      private SharedPreferences   sp;//数据存储      private long fileLength   = 0;//初始化数据总汉长度为0      private Boolean isSaved   = false;//定义标识 是否已经存储过长度      @Override    protected void   onCreate(Bundle savedInstanceState)   {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        //初始化SharedPreferences          sp =   getSharedPreferences("info",MODE_PRIVATE);        fileLength   =   sp.getLong("Length",0);        isSaved   =   sp.getBoolean("is_saved",false);//初始化没有存储          //判断外置存储是否挂载          if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){            //若挂载 则创建存放位置(SDK中)              File externalStorageDirectory =   Environment.getExternalStorageDirectory();            String   path = externalStorageDirectory.getAbsolutePath() +   File.separator +   "new.apk";            Log.e("+++++存入路径",   "onCreate: "+path   );            file   = new   File(path);            //判断文件是否存在 不存在则创建              if(!file.exists()){                try   {                    file.createNewFile();                }   catch (IOException e)   {                    e.printStackTrace();                }            }        }         //创建下载进度条          dialog = new   ProgressDialog(this);        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//进度条样式为水平          dialog.setMax(100);//设置最大值为100          dialog.setTitle("下载");    }     //点击时 进行版本检查      @OnClick(R.id.mian_btn)    public   void onViewClicked()   {        //创建检测版本有无更新的方法          CheckVersion();    }     //定义检测版本有无更新的方法      private void CheckVersion()   {        Type type =   new   TypeToken<messagebean>() {        }.getType();        HttpUtils.getInstance().getData("https://www.xieast.com/api/checkversion.php",   type, new NetCallBack()   {            //成功的方法              @Override            public   void Success(Object o) {                //强转成我们所需的数据集合                  MessageBeanmessageBean =   (MessageBean)   o;                //Log.e("+++++",   "Success:   "+messageBean.getMsg());                  VersionInfo info =   messageBean.getData();                //创建判断当前版本是否需要更新的方法                  isNeedUpdate(info);            }            //失败的方法              @Override            public   void Error(Throwable t) {                Log.e("+++++",   "Error: " +   t.getMessage());            }        });    }     //定义判断当前版本是否需要更新的方法      private void   isNeedUpdate(final VersionInfo   info) {        //拿到当前的版本号          int currentversionCode =   VersionUtils.getVersionCode(this);        //判断当前版本号是否小于网络请求的需更新的版本号          if (currentversionCode <   info.getLast_version())   {            //创建弹出对话框              AlertDialog.Builder builder = new   AlertDialog.Builder(this)                    .setTitle("版本更新")                    .setMessage("检查到新的版本");            //需要更新 判断当前的版本是否小于等于网络请求的需强制更新的版本号              if (currentversionCode <   info.getLast_must_update())   {                //需强制更新 将状态值变成false                  isMust =   false;                builder.setPositiveButton("立即更新",   new DialogInterface.OnClickListener()   {                    @Override                    public   void onClick(DialogInterface dialog, int   which) {                        //创建更新APK文件的方法                          downLoadApk(info.getUrl(),info.getMd5());                        //设置监听事件                      }                }).setOnCancelListener(new   DialogInterface.OnCancelListener()   {                    @Override                    public   void onCancel(DialogInterface dialog)   {                        //   若不想更新 则点击模拟器返回按钮 关闭页面                          finish();                    }                });            }   else {                //可更新  不更新则将状态值变成false                  isMust =   true;                builder.setPositiveButton("更新",   new DialogInterface.OnClickListener()   {                    @Override                    public   void onClick(DialogInterface dialog, int   which) {                        //创建更新APK文件的方法                          downLoadApk(info.getUrl(),info.getMd5());                    }                    //也可不更新                  }).setNegativeButton("取消",   null);            }            //显示弹出框              AlertDialog dialog =   builder.create();            //设置强制更新时 弹出框点外部不会消失              //isMust为true 失去焦点不隐藏              dialog.setCanceledOnTouchOutside(isMust);//设置弹出框失去焦点是否隐藏,即点击屏蔽其它地方是否隐藏              dialog.show();        }   else   {            //   吐司提示              Toast.makeText(this,   "当前版本已经是最新版本了!",   Toast.LENGTH_SHORT).show();        }    }     //更新下载APK文件的方法      private void downLoadApk(String url,   final String md5)   {        Log.e("+++++",   "downLoadApk: 开始下载"   );        String range   = "";//定义变量          //进行判断          if(isSaved){            //若存储过文件总长度 则直接将总长度赋给range即可              range =   "bytes="+file.length()+"-"+fileLength;        }else{            //若没有存储过 则直接指定range为0              range =   "bytes="+file.length()+"-";        }         //使用原生OkHttpClient进行请求          OkHttpClient client = new   OkHttpClient();        final   Request request = new   Request.Builder()                .url(url)                .addHeader("range",range)                .get()                .build();        Call   call =   client.newCall(request);        //下载是显示进度条          dialog.show();        call.enqueue(new   Callback() {            @Override   //失败              public void onFailure(Call call,   IOException e)   {                dialog.dismiss();//失败时,进度条不显示                  Log.e("+++++",   "onFailure:下载失败   ");            }             @Override   //成功              public void onResponse(Call call,   Response response) throws IOException   {                long   contentLength   =0;                if(fileLength==0){                    //得到数据的总长度                      contentLength =   response.body().contentLength();                    //并存入数据存储中                      sp.edit().putLong("Length",contentLength).commit();                }else{                    contentLength   =fileLength;                }                 Log.e("++++文件大小",   "onResponse:   "+contentLength);                int   length = 0;                long   sum = file.length() ;//定义一个总长度                  //创建随机存储的类 rw:可读可写模式                  RandomAccessFile raf = new   RandomAccessFile(file,"rw");                //移动到目前已经下载的文件大小的位置                  raf.seek(sum);                //拿到流文件  InputStream输入流:往内存写数据                  InputStream inputStream =   response.body().byteStream();                //按照2048个字节进行写入                  byte[] bytes = new   byte[2048];                //循环写入                  while ((length =   inputStream.read(bytes,0,bytes.length))!=-1){                    sum+=length;//每次循环读取的数据赋给sum                      raf.write(bytes,0,length);                    raf.seek(sum);                     //总长度*100/文件长度 = 进度                      int progress =   (int) (sum * 100 / contentLength);                    //子线程不能更新UI,但是dialog内部已经回调到主线程了                      dialog.setProgress(progress);//将进度赋给进度条                      if(progress>99){                        //下载完成 安装APK  并关闭dialog                          dialog.dismiss();                        //创建校验MD5值的方法                          checkAPk(file,md5);                        break;//循环完毕 跳出循环                      }                }                //关流                  inputStream.close();            }        });    }    //创建校验MD5的方法      private void checkAPk(File file,   String md5) {        //校验成功后再进行安装          String fileMD5 =   FileMd5Utils.getFileMD5(file);        Log.e("+++++",   "checkAPk:源文件的MD5值   "+fileMD5   );        Log.e("+++++",   "checkAPk: 下载的MD5值"+md5   );        //toLowerCase:全部转为小写  equalsIgnoreCase:忽略大小写          if(fileMD5.equalsIgnoreCase(md5))   {            installAPK(file);//创建安装APK方法          }else{            Log.e("++++",   "checkAPk:文件不合法 "   );        }    }     //安装APK的方法      private void installAPK(File file)   {        Log.e("++++",   "installAPK:进行安装 "   );        Intent   intent = new   Intent();        intent.setAction(Intent.ACTION_VIEW);        intent.addCategory(Intent.CATEGORY_DEFAULT);        intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//启动另一个任务栈          startActivityForResult(intent,INTENT_APK);        System.exit(0);//安装完成后 退出即可      }}
10.主布局
xml   version="1.0"   encoding="utf-8"?><LinearLayout      xmlns:android="https://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical">     <TextView          android:id="@+id/mian_show"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:text="Hello   World!"   />    <Button          android:id="@+id/mian_btn"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:text="版本检查"/> LinearLayout>    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

 

本文由 @凌雪 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程