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에 따라 라이센스가 부여됩니다.