<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Android檢查更新下載安裝

      檢查更新是任何app都會用到功能,任何一個app都不可能第一個版本就能把所有的需求都能實現,通過不斷的挖掘需求迭代才能使app變的越來越好。檢查更新自動下載安裝分以下幾個步驟:

      • 請求服務器判斷是否有最新版本(通過versionCode)
      • 如果有最新版本,就把最新的apk文件下載到本地
      • 下載完成之后給系統發起一個安裝的Intent。

      打開項目下面app下面build.gradle文件,我們可以看到里面有兩個屬性versionCode跟versionName,versionCode是一個int類型的值,用他來更新版本,versionName是一個浮點型的值,給用戶看的,告訴用戶當前的是幾點幾版本。每次app升級的時候,都要對這兩個值進行增加。這里我們就用默認的值好了。

      startup_process

      因為檢查更新需要請求服務器,所以我們引入之前封裝的okhttp庫:

      compile 'com.ansen.http:okhttpencapsulation:1.0.1'
      

      需要訪問網絡跟寫入sdcard的權限,記得在AndroidManifest.xml鐘增加權限。

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

      需要重寫Application,并且在AndroidManifest.xml文件中給application標簽name屬性指向重寫的MyApplication,在MyApplication中初始化HTTPCaller。

      public class MyApplication extends Application {
          @Override
          public void onCreate() {
              super.onCreate();
      
              HttpConfig httpConfig = new HttpConfig();
              httpConfig.setAgent(true);//有代理的情況能不能訪問
              httpConfig.setDebug(true);//是否debug模式 如果是debug模式打印log
              httpConfig.setTagName("ansen");//打印log的tagname
      
              //可以添加一些公共字段 每個接口都會帶上
              httpConfig.addCommonField("pf", "android");
              httpConfig.addCommonField("version_code", "" + Utils.getVersionCode(getApplicationContext()));
      
              //初始化HTTPCaller類
              HTTPCaller.getInstance().setHttpConfig(httpConfig);
          }
      }
      

      我們把version_code作為公共參數,通過Utils類的getVersionCode方法獲取值。getVersionCode方法需要傳入一個context對象,通過Context獲取包管理器,調用PackageManager的getPackageInfo方法獲取包信息,調用他的公有屬性versionCode獲取當前版本號。

      public static int getVersionCode(Context ctx) {
          // 獲取packagemanager的實例
          int version = 0;
          try {
              PackageManager packageManager = ctx.getPackageManager();
              //getPackageName()是你當前程序的包名
              PackageInfo packInfo = packageManager.getPackageInfo(ctx.getPackageName(), 0);
              version = packInfo.versionCode;
          } catch (Exception e) {
              e.printStackTrace();
          }
          return version;
      }
      

      MainActivity對應的activity_main.xml文件比較簡單,上面一個TextView用來顯示當前版本號,下面一個檢查更新按鈕。

      <?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="match_parent"
          android:orientation="vertical"
          android:padding="10dp">
      
          <TextView
              android:id="@+id/tv_current_version_code"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:gravity="center_horizontal"
              android:textSize="16sp"
              android:text="當前版本"/>
      
          <Button
              android:id="@+id/btn_check_update"
              android:layout_marginTop="10dp"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="檢查更新"/>
      </LinearLayout>
      

      MainActivity.java(為了方便講解先看一部分代碼),在onCreate中給顯示當前版本的TextView賦值,跟檢查更新的按鈕設置點擊監聽。點擊按鈕發送一個get請求服務器。我們知道有沒有新版本是通過versionCode的值來判斷的,但是我們這里卻沒有在請求url后面加參數,因為我們在MyApplication中已經把versionCode設置成了公共參數。

      public class MainActivity extends AppCompatActivity implements View.OnClickListener{
          private ProgressDialog progressDialog;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              TextView tvCurrentVersionCode= (TextView) findViewById(R.id.tv_current_version_code);
              tvCurrentVersionCode.setText("當前版本:"+ Utils.getVersionCode(this));
      
              findViewById(R.id.btn_check_update).setOnClickListener(this);
          }
      
          @Override
          public void onClick(View v) {
              switch (v.getId()){
                  case R.id.btn_check_update://檢查更新
                      HTTPCaller.getInstance().get(CheckUpdate.class,"http://139.196.35.30:8080/OkHttpTest/checkUpdate.do",null,requestDataCallback);
                      break;
              }
          }
         
         ·············
      }
      

      get請求回調監聽,先判斷返回的狀態碼,如果狀態碼等于0就是有新版本,有新版本的話下載url也是有值的,把下載url傳給showUpdaloadDialog方法。

      private RequestDataCallback<CheckUpdate> requestDataCallback=new RequestDataCallback<CheckUpdate>(){
              @Override
              public void dataCallback(CheckUpdate obj) {
                  if(obj!=null){
                      if(obj.getErrorCode()==0){//有新版本
                          showUpdaloadDialog(obj.getUrl());
                      }else{//沒有新版本
                          Toast.makeText(MainActivity.this,obj.getErrorReason(),Toast.LENGTH_LONG).show();
                      }
                  }
              }
      };
      

      顯示是否更新對話框,彈一個對話框讓用戶去判斷要不要更新,總是友好一點。我看國內一些很大公司的app如果用戶的手機有wifi的話都是直接后臺下載更新包,而不經過用戶的同意,我覺得這種做法太不考慮用戶的感受了。Android系統的開放性總是用來干一些影響用戶體驗的事情。這里我們談一個確認更新對話框。如果用戶點擊了確認按鈕就調用startUpload方法。當前點擊取消按鈕關閉對話框啥都不干了。

      private void showUpdaloadDialog(final String downloadUrl){
          // 這里的屬性可以一直設置,因為每次設置后返回的是一個builder對象
          AlertDialog.Builder builder = new AlertDialog.Builder(this);
          // 設置提示框的標題
          builder.setTitle("版本升級").
                  setIcon(R.mipmap.ic_launcher). // 設置提示框的圖標
                  setMessage("發現新版本!請及時更新").// 設置要顯示的信息
                  setPositiveButton("確定", new DialogInterface.OnClickListener() {// 設置確定按鈕
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
                          startUpload(downloadUrl);//下載最新的版本程序
                      }
                  }).setNegativeButton("取消", null);//設置取消按鈕,null是什么都不做,并關閉對話框
          AlertDialog alertDialog = builder.create();
          // 顯示對話框
          alertDialog.show();
      }
      

      開始更新方法,首先創建一個進度條對話框,設置進度條樣式,設置messgage,然后調用Utils類的getSaveFilePath靜態方法獲取一個sdcard的路徑,把下載下來的apk文件就保存在這個路徑。然后調用HTTPCaller類的downloadFile方法去下載文件。有三個參數:下載url,文件保存路徑,下載進度回調。下載進度回調是一個ProgressUIListener接口,用內部內的方式重寫三個方法。onUIProgressStart下載開始時把總文件長度賦值給進度條的總長度,顯示進度條。onUIProgressChanged下載進度變化時更新進度條。onUIProgressFinish下載完成銷毀進度條,調用openAPK方法。

      private void startUpload(String downloadUrl){
          progressDialog=new ProgressDialog(this);
          progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
          progressDialog.setMessage("正在下載新版本");
          progressDialog.setCancelable(false);//不能手動取消下載進度對話框
      
          final String fileSavePath=Utils.getSaveFilePath(downloadUrl);
          HTTPCaller.getInstance().downloadFile(downloadUrl,fileSavePath,null,new ProgressUIListener(){
      
              @Override
              public void onUIProgressStart(long totalBytes) {//下載開始
                  progressDialog.setMax((int)totalBytes);
                  progressDialog.show();
              }
      
              //更新進度
              @Override
              public void onUIProgressChanged(long numBytes, long totalBytes, float percent, float speed) {
                  progressDialog.setProgress((int)numBytes);
              }
      
              @Override
              public void onUIProgressFinish() {//下載完成
                  Toast.makeText(MainActivity.this,"下載完成",Toast.LENGTH_LONG).show();
                  progressDialog.dismiss();
                  openAPK(fileSavePath);
              }
          });
      }
      

      下載完成安裝apk,給系統發送一個intent。

      private void openAPK(String fileSavePath){
          Intent intent = new Intent();
          intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          intent.setAction(Intent.ACTION_VIEW);
          intent.setDataAndType(Uri.parse("file://"+fileSavePath),"application/vnd.android.package-archive");
          startActivity(intent);
      }
      

      運行源碼,效果圖如下:
      這里寫圖片描述

      注意事項:

      這里我們為什么有新版本?

      我們看第一張效果圖當前的版本是1,我早就打包了一個versionCode等于2的簽名apk放到服務器上了,所以只要我們給的參數versionCode的值小于2都是可以升級的。

      覆蓋安裝簽名問題

      我們都知道在調試的時候直接運行app裝到手機上安裝包是臨時簽名,所以再企業開發中每次打這個版本的最后包的時候都會正式簽名一下,保證所有版本的安裝包都是一個簽名,只有簽名一樣才能覆蓋安裝。所以你們拿到源碼的時候直接運行app,點擊更新,下載完成,點擊安裝的時候會出現應用未安裝的情況。在項目的根目錄下我有新建一個jks文件夾,里面包含了簽名文件,還有一個已經簽好名的1.0版本,如果你想先看效果可以把1.0版本的apk文件通過社交軟件什么的發送到手機上,安裝升級能覆蓋安裝的。當然你也可以自己簽名。簽名文件跟密碼都在jks文件夾下。

      源碼下載

      如果你想第一時間看我的后期文章,掃碼關注公眾號,每周不定期推送Android開發實戰教程文章...

            Android開發666 - 安卓開發技術分享
                   掃描二維碼加關注
      

      Android開發666

      posted @ 2017-09-05 15:47  安輝  閱讀(6408)  評論(3)    收藏  舉報
      主站蜘蛛池模板: jlzz大jlzz大全免费| 国产免费一区二区不卡| 亚洲国产成人综合自在线| 中文字幕日韩国产精品| 麻豆a级片| 美女一区二区三区亚洲麻豆| 九九热久久只有精品2| 日韩不卡1卡2卡三卡网站| 石狮市| 国产精品一区二区日韩精品| 国内极度色诱视频网站| 日韩精品 在线 国产 丝袜| 成av人电影在线观看| 日韩av不卡一区二区在线| 国内精品无码一区二区三区| 欧美丰满熟妇xxxx性| 亚洲男人第一无码av网| 午夜亚洲AV日韩AV无码大全| 桦甸市| 一区二区三区四区自拍视频| 国产一卡2卡三卡4卡免费网站| 日本三级香港三级三级人!妇久| 亚洲男人天堂一级黄色片| 免费无码成人AV片在线| 久久精品女人天堂av| 极品美女自拍偷精品视频| jizz视频在线观看| 成年女性特黄午夜视频免费看| 亚洲精品码中文在线观看| 精品偷拍一区二区三区| 色老板精品视频在线观看| 九九热在线精品视频99| 重口SM一区二区三区视频| 亚洲欧洲美洲在线观看| 久久国产精品99久久蜜臀| 亚洲中文字幕一区二区| 久久久久香蕉国产线看观看伊| 亚洲精品一区二区三区色| AV老司机色爱区综合| 国产成人高清亚洲综合| 久久国产免费直播|