Android笔记之版本更新

安卓版本更新
 
1.在应用首界面onCreate中调用initVersion();
 
/**
      * 更新版本
      */
      private   void  initVersion() {
            //  TODO  Auto-generated method stub
            // 获取版本号
           getLocalVersion();
           String url = Urls. VERSION_CODE ;
           Log. i ("更新版本url---" , url);
           Request<String> request = NoHttp. createStringRequest (url,
                     RequestMethod. POST );
           queue .add(222, request,  new  OnResponseListener<String>() {
                 @Override
                 public   void  onStart( int  what) {
                      //  TODO  Auto-generated method stub
                }
                 @Override
                 public   void  onSucceed( int  what, Response<String> response) {
                      //  TODO  Auto-generated method stub
                     Log. i ("onSucceed---" , response.get());
                     Gson gson =  new  Gson();
                     VersionUpdate update = gson.fromJson(response.get(),
                                VersionUpdate. class );
                     String apkUrl = update.appmanage .appUrl ;
                      // 最新 apk 下载地址
                     String newversion_code = update.appmanage .version_code ;
                      int  new_version_code = Integer. parseInt (newversion_code);
                     String errorCodes = update.errorCode ;
                     Log. i ("appUrl---" , apkUrl);
                     Log. i ("version_code---" , newversion_code);
                     Log. i ("errorCode2---" , errorCodes);
                      if  ("0" .equals(errorCodes)) {
                            // 0 没有获取到后台版本号
                     }  else   if  ("1" .equals(errorCodes)) {
                            // 1 获取到后台版本号
                            if  (new_version_code == localCode ) {
                                 // 相同 说明当前已经是最新版本
                                 return ;
                           }  else  {
                                 // 说明有新版本需要更新
                                 // 弹对话框提示用户去下载新版本
                                showUpdateDialog(apkUrl);
                           }
                     }
                }
                 @Override
                 public   void  onFailed( int  what, String url, Object tag,
                           Exception exception,  int  responseCode,  long  networkMillis) {
                      //  TODO  Auto-generated method stub
                }
                 @Override
                 public   void  onFinish( int  what) {
                      //  TODO  Auto-generated method stub
                }
           });
     }
 
 
2. 获取应用当前版本号
 
      private  int  localCode;
   
      /**
      * 获取应用当前版本号
      */
      private  void getLocalVersion() {
         // 如何拿到版本信息?
        pm = context.getPackageManager();
       
         // 获取到对应的包下面的信息
         // 写0获取到所有的 其他的代表写谁获取谁
         try {
             // PackageInfo 是对整个清单文件的封装
            PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
             // ApplicationInfo 是Application节点的封装
            localCode = packageInfo.versionCode;
             //这里只获取localCode进行判断
       }  catch (PackageManager.NameNotFoundException e){
             //  TODO  Auto-generated catch block
            e.printStackTrace();
        }
    }
 
 
 
3. 下载新版本
private  AlertDialog alertDialog ;
      /**
      * 下载新版本
      *
      *  @param  info
      *  @param  apkUrl
      */
      private   void   showUpdateDialog ( final  String apkUrl) {
            // 普通对对话框
            final  AlertDialog.Builder builder =  new  AlertDialog.Builder(context );
           alertDialog  = builder.create();
           LayoutInflater inflater = ((Activity) context ).getLayoutInflater();
            final  View layout = inflater.inflate(R.layout. dialogversion null );
            // TextView tv_info = (TextView)
            // layout.findViewById(R.id.tv_dialoge_info);
            Butt on bt_cancle = (Button) layout.findViewById(R.id. bt_cancle_dialog );
           Button bt_sure = (Button) layout.findViewById(R.id. bt_sure_dialog );
            // tv_info.setText(info);
           alertDialog .setView(layout);
           alertDialog .setIcon(R.drawable. zc );
            // 设置ProgressDialog 是否可以按退回按键取消
           alertDialog .setCancelable( false );
            // 如果不想让对话框关闭
            // builder.setCancelable(false);
            // 给对话框设置一个消失的监听
           alertDialog .setOnCancelListener( new  DialogInterface.OnCancelListener() {
                 @Override
                 public   void  onCancel(DialogInterface dialog) {
                }
           });
           bt_cancle.setOnClickListener( new  View.OnClickListener() {
                 @Override
                 public   void  onClick(View view) {
                      //  TODO  点击的是(暂不更新)
                     alertDialog .dismiss();
                }
           });
           bt_sure.setOnClickListener( new  View.OnClickListener() {
                 @Override
                 public   void  onClick(View view) {
                      //  TODO  点击的是(立即更新)
                     alertDialog .dismiss();
                    
//android6.0以后动态申请读写权限
int permission_write=ContextCompat.checkSelfPermission(MainActivity.this,
        Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permission_read=ContextCompat.checkSelfPermission(MainActivity.this,
        Manifest.permission.READ_EXTERNAL_STORAGE);
if(permission_write!= PackageManager.PERMISSION_GRANTED
        || permission_read!=PackageManager.PERMISSION_GRANTED){
    Toast.makeText(mContext, "正在请求权限", Toast.LENGTH_SHORT).show();
    //申请权限,特征码自定义为1,可在回调时进行相关判断
    ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},1);
}else{
    downloadApk(apkUrlstr);

}
                    
                }
           });
           alertDialog .show();
     }
 
 
 
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode){
        case 1:
            if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
                //权限已成功申请
                MyLog.i("权限已成功申请=============",apkUrlstr);
                downloadApk(apkUrlstr);
            }else{
                //用户拒绝授权
                Toast.makeText(this, "无法获取SD卡读写权限", Toast.LENGTH_SHORT).show();
                finish();
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}
 
 
 
 
3.1 dialogversion布局
<? 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:layout_marginLeft= "50dp"
    android:layout_marginRight= "50dp"
   android:background= "@drawable/shape_dialoge"
    android:orientation= "vertical">
    < TextView
        android:id= "@+id/tv_dialoge_title"
        android:layout_width= "match_parent"
        android:layout_height= "wrap_content"
        android:layout_margin= "10dp"
         android:text = "检测到新版本"
        android:textColor= "@color/black"
           android:gravity= "center"
         android:textSize = "20dp"  />
     < ImageView
        android:layout_width= "match_parent"
        android:layout_height= "1dp"
        android:background= "#3EB3F9"  />
    <!--  <TextView
        android:id="@+id/tv_content_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="更新内容:"
        android:textColor="@color/black"
        android:textSize="18dp" />
    <TextView
        android:id="@+id/tv_dialoge_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="XXXXXXXXXXXXXX "
        android:textColor="@color/black"
        android:textSize="16dp" /> -->
     < ImageView
        android:layout_width= "match_parent"
        android:layout_height= "1dp"
        android:background= "#3EB3F9"  />
    < LinearLayout
        android:layout_width= "match_parent"
        android:layout_height= "wrap_content"
        android:orientation= "horizontal">
        < Button
            android:id= "@+id/bt_cancle_dialog"
            android:layout_width= "0dp"
            android:layout_height= "wrap_content"
            android:layout_weight= "100"
            android:background= "#fff"
              android:text = "暂不更新"
            android:textColor= "#919191"
              android:textSize = "20dp"  />
    < ImageView
            android:layout_width= "0dp"
            android:layout_height= "match_parent"
            android:layout_weight= "1"
            android:background= "#3EB3F9"  />
        < Button
            android:id= "@+id/bt_sure_dialog"
            android:layout_width= "0dp"
            android:layout_height= "wrap_content"
            android:layout_weight= "100"
            android:background= "#fff"
              android:text = "立即更新"
            android:textColor= "#3EB3F9"
              android:textSize = "20dp"  />
    </ LinearLayout>
</ LinearLayout>
 
3.2 zc样式
<? xml version= "1.0" encoding= "utf-8"?>
< layer-list xmlns:android= " http://schemas.android.com/apk/res/android" ;>
    < item>
        < shape>
            < solid android:color= "#dddddd" />
        </ shape>
    </ item>
    < item
        android:left= "1dp"
        android:right= "1dp"
        android:top= "1dp"
        android:bottom= "1dp">
        < shape>
            < solid android:color= "#f4f4f4"/>
        </ shape>
    </ item>
</ layer-list>
 
 
4.下载appk过程
private AlertDialog pd;
      private  void downloadApk(String apkurl) {
            // 下载维护的线程池数
           DownloadQueue downloadQueue = NoHttp. newDownloadQueue();
           Log. i("sdcard--", MyResource. DOWNLOAD_PATH);
            // 下载请求
           DownloadRequest downloadRequest = NoHttp. createDownloadRequest(apkurl,
                     RequestMethod. GET, MyResource. DOWNLOAD_PATH,
                     "example.apk",  truetrue);
            // 下载请求添加在下载队列里
           downloadQueue.add(3, downloadRequest,  new DownloadListener() {
                 private ProgressBar pb_progress;
                 private TextView tv_max;
                 private TextView tv_progress;
                 public  long allCount;
                 @Override
                 public  void onDownloadError( int what, Exception exception) {
                     Toast. makeText(context, "服务器忙,下载失败", Toast. LENGTH_SHORT).show();
                     Toast. makeText(context, exception.getMessage(),
                                Toast. LENGTH_SHORT).show();
                      // 对话框消失掉
                      if (pd !=  null) {
                           pd.dismiss();
                     }
                }
                 @Override
                 public  void onStart( int what,  boolean isResume,  long rangeSize,
                           Headers responseHeaders,  long allCount) {
                      this.allCount = allCount;
                      final AlertDialog.Builder builder =  new AlertDialog.Builder(
                                context);
                     pd = builder.create();
                     LayoutInflater inflater = ((Activity) context)
                                .getLayoutInflater();
                      final View layout = inflater.inflate(R.layout. dialog_download,
                                 null);
                     tv_progress = (TextView) layout.findViewById(R.id. tv_progress);
                     tv_max = (TextView) layout.findViewById(R.id. tv_max);
                     pb_progress = (ProgressBar)  layout
                                .findViewById(R.id. pb_progress);
                     pd.setView(layout);
                     DecimalFormat df =  new DecimalFormat("##.##");
                     tv_max.setText(df.format((allCount / 1024.00 / 1024.00)) + "M");
                     pd.setCancelable( false);
                     pb_progress.setMax(100);
                     pd.show();
                }
                 @Override
                 public  void onProgress( int what,  int progress,  long fileCount) {
                      //正在下载
                      // 更新进度条
                     pb_progress.setProgress(progress);
                     DecimalFormat df =  new DecimalFormat("##.##");
                     tv_progress.setText(df.format(( double) progress
                                * (allCount / 1024.00 / 1024.00 / 100.00))
                                + "M");
                }
                 @Override
                 public  void onFinish( int what, String filePath) {
                      // 下载完成
                      // 对话框消失掉
                      if (pd !=  null) {
                           pd.dismiss();
                     }
                     ToastUtils. toast(context, "下载成功");
                  
//先获取是否有安装未知来源应用的权限
checkInstall();
 
                }
                
                 @Override
                 public  void onCancel( int what) {
                      //  TODO  Auto-generated method stub
                      // 对话框消失掉
                      if (pd !=  null) {
                           pd.dismiss();
                     }
                }
           });
     }
 
 
4.1  MyResource工具类
/**
 * 用来存放一些公用的资源 比如 下载的路径
 *  @author  Administrator
 *
 */
public  class MyResource {
      // 我们将跟我们软件相关的所有的文件放在 sd 卡的同一个路径下
        //apk名字
      private  static  final String  ROOT = "example";
     
      //    / mnt / sdcard /example
      public  static  final String  ROOT_PATH = Environment. getExternalStorageDirectory().getAbsolutePath()+"/"+ ROOT;
     
      // 这个目录只跟下载的东西相关
      //   / mnt / sdcard /example/download
      public  static  final String  DOWNLOAD_PATH =  ROOT_PATH+"/download";
     
}
 
 
4.2   dialog_download布局
 
<? 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 = "#fff"
     android:orientation = "vertical" >
     < TextView
         android:id = "@+id/tv_dialoge_title"
         android:layout_width = "match_parent"
         android:layout_height = "wrap_content"
         android:layout_margin = "10dp"
        android:text = "下载中。。。"
            android:gravity = "center"
         android:textSize = "20dp"  />
   
 
     < ImageView
         android:layout_width = "match_parent"
         android:layout_height = "@dimen/x1"
         android:background = "#20abff"  />
     < ProgressBar
         android:id = "@+id/pb_progress"
         style = "?android:attr/progressBarStyleHorizontal"
         android:layout_width = "match_parent"
         android:layout_height = "20dp"
       android:progressDrawable="@drawable/progressbar_background"
        android:layout_marginBottom = "5dp"
         android:layout_marginRight = "20dp"
         android:layout_marginLeft = "20dp"
         android:layout_marginTop = "20dp"
          />
 
     < LinearLayout
         android:layout_marginBottom = "10dp"
         android:layout_width = "match_parent"
         android:layout_height = "wrap_content"
         android:gravity = "right"
         android:orientation = "horizontal" >
         < LinearLayout
             android:layout_marginRight = "40dp"
             android:orientation = "horizontal"
             android:layout_width = "wrap_content"
             android:layout_height = "wrap_content" >
             < TextView
                 android:id = "@+id/tv_progress"
                 android:layout_width = "wrap_content"
                 android:layout_height = "wrap_content"
                 android:text = "3M"
                 android:textSize = "16dp"  />
             < TextView
                 android:layout_width = "wrap_content"
                 android:layout_height = "wrap_content"
                 android:text = " / "
                 android:textSize = "16dp"  />
             < TextView
                 android:id = "@+id/tv_max"
                 android:layout_width = "wrap_content"
                 android:layout_height = "wrap_content"
                 android:text = "5M"
                 android:textSize = "16dp"  />
         </ LinearLayout >
     </ LinearLayout >
</ LinearLayout >
 
 
 
4.3  @drawable/progressbar_background  布局
 
<? xml version= "1.0" encoding= "utf-8"?>
< layer-list xmlns:android= " http://schemas.android.com/apk/res/android" ; >
     < item android:id= "@android:id/background">
        < shape>
            < corners android:radius= "5dp" />
            < solid android:color= "#A5D1DB" />          //这个颜色是pro gressbar的背景颜色
        </ shape>
    </ item>
    < item android:id= "@android:id/progress">
        < clip>
            < shape>
                < corners android:radius= "5dp" />
                < solid android:color= "#1E90FF" />       //这个颜色是progressbar的进度颜色
            </ shape>
        </ clip>
    </ item>
</ layer-list>
 
 
4.4checkInstall   (先获取是否有安装未知来源应用的权限)
private void checkInstall() {
    boolean haveInstallPermission;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        //先获取是否有安装未知来源应用的权限
        haveInstallPermission = getPackageManager().canRequestPackageInstalls();
        if (!haveInstallPermission) {//没有权限
            AlertDialog alertDialog = new AlertDialog.Builder(this)
                    .setTitle("请开启未知来源权限")
                    .setMessage("应用需要打开安装未知来源应用权限,请去设置中开启权限")
                    .setCancelable(false)
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            ToastUtil.showToast(MainActivity.this,"您拒绝了权限,应用无法正常使用!");
                            finish();
                        }
                    })
                    .setPositiveButton("去设置", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            toInStallPermissionSettingActivity();
                        }
                    }).create();
            alertDialog.show();
            return;
        }
    }
    //有权限,进行安装操作
    installAPK();

}
protected static final int REQUEST_CODE_INSTALL_PERMISSION = 2;
private void toInStallPermissionSettingActivity() {
    Uri packageURI = Uri.parse("package:" + getPackageName());
    //注意这个是8.0新API
    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
    startActivityForResult(intent, REQUEST_CODE_INSTALL_PERMISSION);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == RESULT_OK && requestCode == REQUEST_CODE_INSTALL_PERMISSION){
        checkInstall();//以防万一,再次检查权限
    }

}

 

4.5.自动安装app

private void installAPK() {
    String fileName = MyResource.DOWNLOAD_PATH
            + "/example.apk";
    try {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Uri uri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //7.0 Android N
            //com.xxx.xxx.fileprovider为上述manifest中provider所配置相同
            MyLog.i("大于7.0","11111111111111111");
            uri = FileProvider.getUriForFile(mContext, "zz.bole.songjisn.fileprovider", new File(fileName));
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//7.0以后,系统要求授予临时uri读取权限,安装完毕以后,系统会自动收回权限,该过程没有用户交互

        } else {//7.0以下
            MyLog.i("7.0以下","7.0以下");
            uri = Uri.fromFile(new File(fileName));

        }
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        // 查询所有符合 intent 跳转目标应用类型的应用,注意此方法必须放置在 setDataAndType 方法之后
        List<ResolveInfo> resolveLists = mContext.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        // 然后全部授权
        for (ResolveInfo resolveInfo : resolveLists){
            String packageName = resolveInfo.activityInfo.packageName;
            mContext.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
        startActivity(intent);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    }catch (ActivityNotFoundException e){
        e.printStackTrace();
    }catch (Exception e){
        e.printStackTrace();
    }
}

4.6清单文件中加provider

 

<provider

android:authorities="你的包名.fileprovider"

android:name="android.support.v4.content.FileProvider"

android:grantUriPermissions="true"

android:exported="false">

<meta-data

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/filepaths"/>

</provider>

4.7@xml/filepaths res目录下新建xml目录

 

<?xml version="1.0" encoding="utf-8"?>

<resources>

<paths>

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

</paths>

</resources>

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值