Android 자동 업데이트 실현
필요:
우리 가 앱 을 개발 하 는 과정 에서 이런 수요 에 부 딪 힐 수 있다.앱 이 실 행 될 때 새 버 전이 나 왔 는 지 확인 하고 업데이트 합 니 다.앱 의 내부 자동 업 데 이 트 를 어떻게 실현 하 는 지 오늘 소개 한다.
인터페이스 가 져 오기
우선, 우 리 는 백 엔 드 에서 버 전 정보 데 이 터 를 얻 고 백 엔 드 에서 제공 하 는 인 터 페 이 스 를 통 해 데 이 터 를 되 돌려 야 합 니 다.데이터 형식 은 JSon 을 사용 합 니 다. 예제 텍스트 는 다음 과 같 습 니 다.
{
    "appname":"Will.apk",
    "serverVersion":"1.0.2",
    "serverFlag":"1",
    "lastForce":"1",
    "updateurl":"http://www.baidu.com",
    "upgrateinfo":"V1.0.2    ,      !"
}
  학습 과정 에서 백 엔 드 가 인 터 페 이 스 를 제공 하지 않 는 다 면 제 다른 글 을 참고 하여 Jhipster 를 사용 하여 간단 한 API 인 터 페 이 스 를 만 듭 니 다.Jhipster 단순 사용
실현 과정
다음은 우리 안 드 로 이 드 엔 드 의 실현 을 시작 하 겠 습 니 다.사고방식: 1. 백 엔 드 인 터 페 이 스 를 연결 하 는 데 사용 되 는 bean 의 업 데 이 트 를 실현 합 니 다. 2. retrofit 를 사용 하여 버 전의 업 데 이 트 를 요청 하 는 인터페이스 3. APK 다운로드 4. BroadcastReceiver 를 통 해 다운로드 완료 여 부 를 감청 합 니 다.
STEP 1: JSon 데 이 터 를 받 아들 이 는 클래스 만 들 기
인터페이스 에서 얻 은 JSon 데 이 터 는 다음 과 같은 클래스 로 분석 해 야 합 니 다.
public class UpdateAppInfo {
    private String appname;
    private String serverVersion;
    private String serverFlag;
    private String lastForce;
    private String updateurl;
    private String upgradeinfo;
    public String getAppname() {
        return appname;
    }
    public void setAppname(String appname) {
        this.appname = appname;
    }
    public String getServerVersion() {
        return serverVersion;
    }
    public void setServerVersion(String serverVersion) {
        this.serverVersion = serverVersion;
    }
    public String getServerFlag() {
        return serverFlag;
    }
    public void setServerFlag(String serverFlag) {
        this.serverFlag = serverFlag;
    }
    public String getLastForce() {
        return lastForce;
    }
    public void setLastForce(String lastForce) {
        this.lastForce = lastForce;
    }
    public String getUpdateurl() {
        return updateurl;
    }
    public void setUpdateurl(String updateurl) {
        this.updateurl = updateurl;
    }
    public String getUpgradeinfo() {
        return upgradeinfo;
    }
    public void setUpgradeinfo(String upgradeinfo) {
        this.upgradeinfo = upgradeinfo;
    }
    @Override
    public String toString() {
        return "UpdateAppInfo{" +
            "appname='" + appname + '\'' +
            ", serverVersion='" + serverVersion + '\'' +
            ", serverFlag='" + serverFlag + '\'' +
            ", lastForce='" + lastForce + '\'' +
            ", updateurl='" + updateurl + '\'' +
            ", upgradeinfo='" + upgradeinfo + '\'' +
            '}';
    }
}
  STEP 2: Retrofit + RxJava 네트워크 인터페이스 구현
먼저 가입 의존:
/ / Android 지원 Rxjava / / 여 기 는 RxJava 2 버 전 compile 'io. reactivex. rxjava 2: rxjava: 2.0.1' compile 'io. reactivex. rxjava 2: rxandroid: 2.0.1' / Android 지원 Retrofit compile 'com. squareup. retrofit 2: retrofit: 2.1.0' / 연결 Retrofit & RxJava 2 / 여 기 는 RxJava 2 버 전 compile 'com. jakewharton. retrofit: retrofit2-rxjava2-adapter:1.0.0'
다음 네트워크 인터페이스 만 들 기:
public interface NetService{
    @GET("/api/update-infos/1")
    Observable getUpdateInfo();
}
   공장 모드 를 통 해 NetService 를 만 듭 니 다.
public class ServiceFactory{
    private static final String BaseUrl = "http://10.10.2.87:8080"
    public static  T createServiceFrom(final Class serviceClass){
        Retrofit adapter = new Retrofit.Builder()
            .baseUrl(BaseUrl)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //   Rx   
                .addConverterFactory(GsonConverterFactory.create()) //   Gson   
                .build();
        return adapter.create(serviceClass);
    }
}
    단계 3: 검 측 버 전 업데이트 인터페이스 만 들 기
public class CheckUpdateUtils {
    @SuppressWarnings("unused")
    public static void checkUpdate(String appCode,String curVersion,final CheckCallBack updateCallback){
        ApiService apiService = ServiceFactory.createServiceFrom(ApiService.class);
        Log.e("check","       1");
        String appName = "hoolay";
        apiService.getCall()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subject() {
                    @Override
                    public boolean hasObservers() {
                        return false;
                    }
                    @Override
                    public boolean hasThrowable() {
                        return false;
                    }
                    @Override
                    public boolean hasComplete() {
                        return false;
                    }
                    @Override
                    public Throwable getThrowable() {
                        return null;
                    }
                    @Override
                    protected void subscribeActual(Observer super UpdateAppInfo> observer) {
                    }
                    @Override
                    public void onSubscribe(Disposable d) {
                    }
                    @Override
                    public void onNext(UpdateAppInfo value) {
                        if(value.equals(null)||value.getUpdateurl().equals(null)){
                            Log.e("check","       2");
                            updateCallback.onError();
                        }else {
                            Log.e("check","       3");
                            updateCallback.onSuccess(value);
                        }
                    }
                    @Override
                    public void onError(Throwable e) {
                    }
                    @Override
                    public void onComplete() {
                    }
                });
    }
}
   여기 에는 결과 리 셋 감청 이 필요 하 다.
//            
public interface CheckAllBack{
    void onSuccess(UpdateAppInfo updateInfo);
    void onError();
}
  STEP 4: 액 티 비 티 에서 완 성 된 부분
/**
 *                  
 */
public class ApkVersionCodeUtils {
    /**
     *       apk   
     *
     * @param mContext
     * @return
     */
    public static int getVersionCode(Context mContext) {
        int versionCode = 0;
        try {
            //       ,  AndroidManifest.xml android:versionCode
            versionCode = mContext.getPackageManager().
                    getPackageInfo(mContext.getPackageName(), 0).versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionCode;
    }
    /**
     *        
     *
     * @param context    
     * @return
     */
    public static String getVerName(Context context) {
        String verName = "";
        try {
            verName = context.getPackageManager().
                    getPackageInfo(context.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return verName;
    }
}
  CheckUpdateUtils.checkUpdate("apk", "1.0.0", new CheckCallBack() {
            @Override
            public void onSuccess(UpdateAppInfo updateAppInfo) {
                String isForce = updateAppInfo.getLastForce();
                String downUrl = updateAppInfo.getUpdateurl();
                String updateinfo = updateAppInfo.getUpgradeinfo();
                String appName = updateAppInfo.getAppname();
                Log.e("aaa",appName);
                if(isForce.equals("1")&& !TextUtils.isEmpty(updateinfo)){//    
                    forceUpdate(MainActivity.this,appName,downUrl,updateinfo);
                }else{//     
                    //    
                    normalUpdate(MainActivity.this,appName,downUrl,updateinfo);
                }
            }
            @Override
            public void onError() {
                noneUpdate(MainActivity.this);
            }
        });
  private void forceUpdate(final Context context, final String appName, final String downUrl, final String updateinfo) {
        mDialog = new AlertDialog.Builder(context);
        mDialog.setTitle(appName+"    !");
        mDialog.setMessage(updateinfo);
        mDialog.setPositiveButton("    ", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (!canDownloadState()) {
                    showDownloadSetting();
                    return;
                }
                //      DownLoadApk.download(MainActivity.this,downUrl,updateinfo,appName);
     AppInnerDownLoder.downLoadApk(MainActivity.this,downUrl,appName);
            }
        }).setCancelable(false).create().show();
    }
  STEP 5: HttpUrlConnection 으로 다운로드
public class AppInnerDownLoder {
    public final static String SD_FOLDER = Environment.getExternalStorageDirectory()+ "/VersionChecker/";
    private static final String TAG = AppInnerDownLoder.class.getSimpleName();
    /**
     *        APK
     */
    @SuppressWarnings("unused")
    public static void downLoadApk(final Context mContext,final String downURL,final String appName ) {
        final ProgressDialog pd; //       
        pd = new ProgressDialog(mContext);
        pd.setCancelable(false);//        ,    
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pd.setMessage("       ,   ");
        pd.setTitle("    ");
        pd.show();
        new Thread() {
            @Override
            public void run() {
                try {
                    File file = downloadFile(downURL,appName, pd);
                    sleep(3000);
                    installApk(mContext, file);
                    //          
                    pd.dismiss();
                } catch (Exception e) {
                    pd.dismiss();
                }
            }
        }.start();
    }
    /**
     *             
     * 
     * @param path
     *                
     * @param pd
     *               
     * @return
     * @throws Exception
     */
    private static File downloadFile(String path,String appName ,ProgressDialog pd) throws Exception {
        //            sdcard            
        if (Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState())) {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            //         
            pd.setMax(conn.getContentLength());
            InputStream is = conn.getInputStream();
            String fileName = SD_FOLDER
                     + appName+".apk";
            File file = new File(fileName);
            //          
            if (!file.getParentFile().exists())
                file.getParentFile().mkdirs();
            FileOutputStream fos = new FileOutputStream(file);
            BufferedInputStream bis = new BufferedInputStream(is);
            byte[] buffer = new byte[1024];
            int len;
            int total = 0;
            while ((len = bis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
                total += len;
                //        
                pd.setProgress(total);
            }
            fos.close();
            bis.close();
            is.close();
            return file;
        } else {
            throw new IOException("    SD ");
        }
    }
    /**
     *   apk
     */
    private static void installApk(Context mContext, File file) {
        Uri fileUri = Uri.fromFile(file);
        Intent it = new Intent();
        it.setAction(Intent.ACTION_VIEW);
        it.setDataAndType(fileUri, "application/vnd.android.package-archive");
        it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//        
        mContext.startActivity(it);
    }
    /**
     *         (versionName)
     * 
     * @return         
     */
    private static double getLocalVersion(Context context) {
        PackageManager manager = context.getPackageManager();
        PackageInfo info = null;
        try {
            info = manager.getPackageInfo(context.getPackageName(), 0);
        } catch (NameNotFoundException e) {
            Log.e(TAG, "          ,  :" + e.getMessage());
            return 0.0;
        }
        return Double.valueOf(info.versionName);
    }
    /** 
     * byte(  )      kb(   ) mb(   ) 
     *  
     * @param bytes 
     * @return 
     */  
    public static String bytes2kb(long bytes) {  
        BigDecimal filesize = new BigDecimal(bytes);  
        BigDecimal megabyte = new BigDecimal(1024 * 1024);  
        float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP)  
                .floatValue();  
        if (returnValue > 1)  
            return (returnValue + "MB");  
        BigDecimal kilobyte = new BigDecimal(1024);  
        returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP)  
                .floatValue();  
        return (returnValue + "KB");  
    }  
}
  STEP 6: 앱 설치 완료 여부
public class ApkInstallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)){
              long downloadApkId =intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
              installApk(context, downloadApkId);
        }
    }
    /**
     *   apk
     */
    private void installApk(Context context,long downloadApkId) {
        //     ID
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        long downId =sp.getLong(DownloadManager.EXTRA_DOWNLOAD_ID,-1L);
        if(downloadApkId == downId){
            DownloadManager downManager= (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            Uri downloadFileUri = downManager.getUriForDownloadedFile(downloadApkId);
            if (downloadFileUri != null) {
            Intent install= new Intent(Intent.ACTION_VIEW);
            install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
            install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(install);
            }else{
                Toast.makeText(context, "    ", Toast.LENGTH_SHORT).show();
            }
        }
    }
}
  DownloadManager 다운로드 가 완료 되면 라디오 android. intent. action. DOWNLOAD 를 보 냅 니 다.COMPLETE 에서 라디오 수신 자 를 새로 만 들 면 다음 과 같이 설정 할 수 있 습 니 다.
            
                
              
         
  총결산
본 고 는 안 드 로 이 드 가 어떻게 간단하게 업데이트 효 과 를 실현 하 는 지 를 소개 했다. 주로 다음 과 같은 박문 을 참고 했다. 안 드 로 이 드 개발 실전 의 app 버 전 업데이트 가 더욱 상세 하 다. 제 가 언급 하지 않 은 부분 은 원 보 를 참조 하 시기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.