Androidプログラムの自動更新機能モジュールの実現方法【完全なdemoソースのダウンロード付き】
本明細書の例は、Androidプログラムの機能モジュールの自動更新の実現方法を説明する。皆さんに参考にしてあげます。具体的には以下の通りです。
プログラムが起動された時、サーバー上に対応バージョンの更新があるかどうかを確認します。更新があれば、更新するかをユーザに提示します。
プログラムの起動時に、まず更新モジュールを呼び出して、サーバに保存されているバージョン番号と現在のプログラムのバージョン番号を検出します。現在のバージョン番号より大きい場合は、更新ダイアログがポップアップされます。ユーザが更新を選択すると、現在の更新状態が表示され、現在のプログラムを置き換えます。
プログラムのバージョン更新検出:
更新ファイルをダウンロードするなどの実装:
Android関連の内容についてもっと興味がある読者は、当駅のテーマを調べてもいいです。「AndroidビューViewテクニックのまとめ」、「Androidプログラミングのactivity操作技術のまとめ」、「Android操作SQLiteデータベース技術まとめ」、「Android操作json形式データ技術のまとめ」、「Androidデータベース操作技術のまとめ」、「Androidファイルの操作テクニックのまとめ」、「Androidプログラミング開発のSDカード操作方法のまとめ」、「Android開発入門と上級教程」、「Android資源操作技術のまとめ」、「Androidコントロールの使い方のまとめ」
ここで述べたように、皆さんのAndroidプログラムの設計に役に立ちます。
プログラムが起動された時、サーバー上に対応バージョンの更新があるかどうかを確認します。更新があれば、更新するかをユーザに提示します。
プログラムの起動時に、まず更新モジュールを呼び出して、サーバに保存されているバージョン番号と現在のプログラムのバージョン番号を検出します。現在のバージョン番号より大きい場合は、更新ダイアログがポップアップされます。ユーザが更新を選択すると、現在の更新状態が表示され、現在のプログラムを置き換えます。
プログラムのバージョン更新検出:
private UpdateManager updateMan;
private ProgressDialog updateProgressDialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//
//
//
updateMan = new UpdateManager(Update_TestActivity.this, appUpdateCb);
updateMan.checkUpdate();
}
検出バージョン番号とコールバックの更新を実行します。更新ファイルをダウンロードするなどの実装:
package update.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.JSONArray;
import org.json.JSONObject;
import com.trinet.util.NetHelper;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class UpdateManager {
private String curVersion;
private String newVersion;
private int curVersionCode;
private int newVersionCode;
private String updateInfo;
private UpdateCallback callback;
private Context ctx;
private int progress;
private Boolean hasNewVersion;
private Boolean canceled;
// APK
public static final String UPDATE_DOWNURL = "http://www.baidu.com/update/update_test.apk";
// APK
public static final String UPDATE_CHECKURL = "http://www.baidu.com/update/update_verson.txt";
public static final String UPDATE_APKNAME = "update_test.apk";
//public static final String UPDATE_VERJSON = "ver.txt";
public static final String UPDATE_SAVENAME = "updateapk.apk";
private static final int UPDATE_CHECKCOMPLETED = 1;
private static final int UPDATE_DOWNLOADING = 2;
private static final int UPDATE_DOWNLOAD_ERROR = 3;
private static final int UPDATE_DOWNLOAD_COMPLETED = 4;
private static final int UPDATE_DOWNLOAD_CANCELED = 5;
// apk
private String savefolder = "/mnt/innerDisk/";
//private String savefolder = "/sdcard/";
//public static final String SAVE_FOLDER =Storage. // "/mnt/innerDisk";
public UpdateManager(Context context, UpdateCallback updateCallback) {
ctx = context;
callback = updateCallback;
//savefolder = context.getFilesDir();
canceled = false;
getCurVersion();
}
public String getNewVersionName()
{
return newVersion;
}
public String getUpdateInfo()
{
return updateInfo;
}
private void getCurVersion() {
try {
PackageInfo pInfo = ctx.getPackageManager().getPackageInfo(
ctx.getPackageName(), 0);
curVersion = pInfo.versionName;
curVersionCode = pInfo.versionCode;
} catch (NameNotFoundException e) {
Log.e("update", e.getMessage());
curVersion = "1.1.1000";
curVersionCode = 111000;
}
}
public void checkUpdate() {
hasNewVersion = false;
new Thread(){
// ***************************************************************
/**
* @by wainiwann
*
*/
@Override
public void run() {
Log.i("@@@@@", ">>>>>>>>>>>>>>>>>>>>>>>>>>>getServerVerCode() ");
try {
String verjson = NetHelper.httpStringGet(UPDATE_CHECKURL);
Log.i("@@@@", verjson
+ "**************************************************");
JSONArray array = new JSONArray(verjson);
if (array.length() > 0) {
JSONObject obj = array.getJSONObject(0);
try {
newVersionCode = Integer.parseInt(obj.getString("verCode"));
newVersion = obj.getString("verName");
updateInfo = "";
Log.i("newVerCode", newVersionCode
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
Log.i("newVerName", newVersion
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
if (newVersionCode > curVersionCode) {
hasNewVersion = true;
}
} catch (Exception e) {
newVersionCode = -1;
newVersion = "";
updateInfo = "";
}
}
} catch (Exception e) {
Log.e("update", e.getMessage());
}
updateHandler.sendEmptyMessage(UPDATE_CHECKCOMPLETED);
};
// ***************************************************************
}.start();
}
public void update() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(new File(savefolder, UPDATE_SAVENAME)),
"application/vnd.android.package-archive");
ctx.startActivity(intent);
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void downloadPackage()
{
new Thread() {
@Override
public void run() {
try {
URL url = new URL(UPDATE_DOWNURL);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
File ApkFile = new File(savefolder,UPDATE_SAVENAME);
if(ApkFile.exists())
{
ApkFile.delete();
}
FileOutputStream fos = new FileOutputStream(ApkFile);
int count = 0;
byte buf[] = new byte[512];
do{
int numread = is.read(buf);
count += numread;
progress =(int)(((float)count / length) * 100);
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOADING));
if(numread <= 0){
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_COMPLETED);
break;
}
fos.write(buf,0,numread);
}while(!canceled);
if(canceled)
{
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_CANCELED);
}
fos.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
} catch(IOException e){
e.printStackTrace();
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
}
}
}.start();
}
public void cancelDownload()
{
canceled = true;
}
Handler updateHandler = new Handler()
{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_CHECKCOMPLETED:
callback.checkUpdateCompleted(hasNewVersion, newVersion);
break;
case UPDATE_DOWNLOADING:
callback.downloadProgressChanged(progress);
break;
case UPDATE_DOWNLOAD_ERROR:
callback.downloadCompleted(false, msg.obj.toString());
break;
case UPDATE_DOWNLOAD_COMPLETED:
callback.downloadCompleted(true, "");
break;
case UPDATE_DOWNLOAD_CANCELED:
callback.downloadCanceled();
default:
break;
}
}
};
public interface UpdateCallback {
public void checkUpdateCompleted(Boolean hasUpdate,
CharSequence updateInfo);
public void downloadProgressChanged(int progress);
public void downloadCanceled();
public void downloadCompleted(Boolean sucess, CharSequence errorMsg);
}
}
サーバモジュールの接続が必要です。
package com.trinet.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
public class NetHelper {
public static String httpStringGet(String url) throws Exception {
return httpStringGet(url, "utf-8");
}
/**
*
*
* @param url
* @return
*/
public static Drawable loadImage(String url) {
try {
return Drawable.createFromStream(
(InputStream) new URL(url).getContent(), "test");
} catch (MalformedURLException e) {
Log.e("exception", e.getMessage());
} catch (IOException e) {
Log.e("exception", e.getMessage());
}
return null;
}
public static String httpStringGet(String url, String enc) throws Exception {
// This method for HttpConnection
String page = "";
BufferedReader bufferedReader = null;
try {
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "android");
HttpParams httpParams = client.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
HttpGet request = new HttpGet();
request.setHeader("Content-Type", "text/plain; charset=utf-8");
request.setURI(new URI(url));
HttpResponse response = client.execute(request);
bufferedReader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent(), enc));
StringBuffer stringBuffer = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line + NL);
}
bufferedReader.close();
page = stringBuffer.toString();
Log.i("page", page);
System.out.println(page + "page");
return page;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
Log.d("BBB", e.toString());
}
}
}
}
public static boolean checkNetWorkStatus(Context context) {
boolean result;
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netinfo = cm.getActiveNetworkInfo();
if (netinfo != null && netinfo.isConnected()) {
result = true;
Log.i("NetStatus", "The net was connected");
} else {
result = false;
Log.i("NetStatus", "The net was bad!");
}
return result;
}
}
ヒントダイアログ:
package com.trinet.util;
import java.lang.reflect.Field;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.view.View;
public class DialogHelper {
public static void Alert(Context ctx, CharSequence title, CharSequence message,
CharSequence okText, OnClickListener oklistener) {
AlertDialog.Builder builder = createDialog(ctx, title, message);
builder.setPositiveButton(okText, oklistener);
builder.create().show();
}
public static void Alert(Context ctx, int titleId, int messageId,
int okTextId, OnClickListener oklistener) {
Alert(ctx, ctx.getText(titleId), ctx.getText(messageId), ctx.getText(okTextId), oklistener);
}
public static void Confirm(Context ctx, CharSequence title, CharSequence message,
CharSequence okText, OnClickListener oklistener, CharSequence cancelText,
OnClickListener cancellistener) {
AlertDialog.Builder builder = createDialog(ctx, title, message);
builder.setPositiveButton(okText, oklistener);
builder.setNegativeButton(cancelText, cancellistener);
builder.create().show();
}
public static void Confirm(Context ctx, int titleId, int messageId,
int okTextId, OnClickListener oklistener, int cancelTextId,
OnClickListener cancellistener) {
Confirm(ctx, ctx.getText(titleId), ctx.getText(messageId), ctx.getText(okTextId), oklistener, ctx.getText(cancelTextId), cancellistener);
}
private static AlertDialog.Builder createDialog(Context ctx, CharSequence title,
CharSequence message) {
AlertDialog.Builder builder = new Builder(ctx);
builder.setMessage(message);
if(title!=null)
{
builder.setTitle(title);
}
return builder;
}
@SuppressWarnings("unused")
private static AlertDialog.Builder createDialog(Context ctx,int titleId, int messageId) {
AlertDialog.Builder builder = new Builder(ctx);
builder.setMessage(messageId);
builder.setTitle(titleId);
return builder;
}
public static void ViewDialog(Context ctx, CharSequence title, View view,
CharSequence okText, OnClickListener oklistener, CharSequence cancelText,
OnClickListener cancellistener) {
}
public static void ViewDialog(Context ctx, int titleId, View view,
int okTextId, OnClickListener oklistener, int cancelTextId,
OnClickListener cancellistener) {
ViewDialog(ctx, ctx.getText(titleId), view, ctx.getText(okTextId), oklistener, ctx.getText(cancelTextId), cancellistener);
}
//
public static void SetDialogShowing(DialogInterface dialog, boolean showing)
{
try {
Field field = dialog.getClass().getSuperclass().getDeclaredField("mShowing");
field.setAccessible(true);
field.set(dialog, showing);
} catch (Exception e) {
e.printStackTrace();
}
}
}
また更新すると、コールバック関数を実行します。
//
UpdateManager.UpdateCallback appUpdateCb = new UpdateManager.UpdateCallback()
{
public void downloadProgressChanged(int progress) {
if (updateProgressDialog != null
&& updateProgressDialog.isShowing()) {
updateProgressDialog.setProgress(progress);
}
}
public void downloadCompleted(Boolean sucess, CharSequence errorMsg) {
if (updateProgressDialog != null
&& updateProgressDialog.isShowing()) {
updateProgressDialog.dismiss();
}
if (sucess) {
updateMan.update();
} else {
DialogHelper.Confirm(Update_TestActivity.this,
R.string.dialog_error_title,
R.string.dialog_downfailed_msg,
R.string.dialog_downfailed_btnnext,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
updateMan.downloadPackage();
}
}, R.string.dialog_downfailed_btnnext, null);
}
}
public void downloadCanceled()
{
// TODO Auto-generated method stub
}
public void checkUpdateCompleted(Boolean hasUpdate,
CharSequence updateInfo) {
if (hasUpdate) {
DialogHelper.Confirm(Update_TestActivity.this,
getText(R.string.dialog_update_title),
getText(R.string.dialog_update_msg).toString()
+updateInfo+
getText(R.string.dialog_update_msg2).toString(),
getText(R.string.dialog_update_btnupdate),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
updateProgressDialog = new ProgressDialog(
Update_TestActivity.this);
updateProgressDialog
.setMessage(getText(R.string.dialog_downloading_msg));
updateProgressDialog.setIndeterminate(false);
updateProgressDialog
.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
updateProgressDialog.setMax(100);
updateProgressDialog.setProgress(0);
updateProgressDialog.show();
updateMan.downloadPackage();
}
},getText( R.string.dialog_update_btnnext), null);
}
}
};
プログラムにパーミッションを追加することを覚えています。
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
完全なインスタンスコードはここをクリックしてダウンロードです。Android関連の内容についてもっと興味がある読者は、当駅のテーマを調べてもいいです。「AndroidビューViewテクニックのまとめ」、「Androidプログラミングのactivity操作技術のまとめ」、「Android操作SQLiteデータベース技術まとめ」、「Android操作json形式データ技術のまとめ」、「Androidデータベース操作技術のまとめ」、「Androidファイルの操作テクニックのまとめ」、「Androidプログラミング開発のSDカード操作方法のまとめ」、「Android開発入門と上級教程」、「Android資源操作技術のまとめ」、「Androidコントロールの使い方のまとめ」
ここで述べたように、皆さんのAndroidプログラムの設計に役に立ちます。