首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

带更新内容揭示的自动更新的一种实现

2012-09-25 
带更新内容提示的自动更新的一种实现思路如下:1.实现一个只有程序安装后第一次打开时才会执行的方法,这样

带更新内容提示的自动更新的一种实现

思路如下:

1.实现一个只有程序安装后第一次打开时才会执行的方法,这样方便在配置文件PreferenceManager.getDefaultSharedPreferences(Context)中保存程序的一些信息,比如apk安装时间,这个值之后会和服务器上的apk修改时间做比较来判断是否要更新,如我这个例子里的showOnFirstLaunch(),程序入口活动JumpActivity?onCreate时获取程序包信息中的versionCode版本代码号,如果与配置中保存的版本号不一致,表示安装新版后第一次打开程序,则执行之后的代代码片段,如保存当前版本号,设置新版已安装的值为true,多设了这个值的目的是,我们自动更新时虽然下载了新版本,但是没有对其安装,则打开旧版本时提示下载的更新没有被安装,给用户一个安装的选择。

?

JumpActivity.class

private void showOnFirstLaunch() {  setContentView(R.layout.splash);    try {      PackageInfo info = getPackageManager().getPackageInfo(PACKAGE_NAME, 0);      int currentVersion = info.versionCode;      prefs = PreferenceManager.getDefaultSharedPreferences(this);      int lastVersion = prefs.getInt(PreferencesActivity.KEY_HELP_VERSION_SHOWN, 0);      if (currentVersion != lastVersion) {//安装好后第一次启动      //设置版本号        prefs.edit().putInt(PreferencesActivity.KEY_HELP_VERSION_SHOWN, currentVersion).commit();         prefs.edit().putBoolean(PreferencesActivity.KEY_LATEST_VERSION_INSTALL, true).commit();        File apk = new File(apkFile);if(apk.exists())apk.delete();//显示关于对话框Intent intent = new Intent(Intent.ACTION_VIEW);                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);                intent.setClassName(this, HelpActivity.class.getName());                startActivity(intent);                finish();         }else {//不是第一次启动    //是否完成上次下载的更新的安装   if(!prefs.getBoolean(PreferencesActivity.KEY_LATEST_VERSION_INSTALL, true)){      new AlertDialog.Builder(JumpActivity.this)      .setTitle(R.string.app_update_title)      .setCancelable(false)      .setMessage(R.string.app_update_not_install)      .setPositiveButton(R.string.button_update_ok,new DialogInterface.OnClickListener() {   public void onClick(DialogInterface dialog, int which) {File apk = new File(apkFile);    if(apk.exists())install();//下载的文件存在则安装    else {//不存在则提示重新下载    Intent update = new Intent(JumpActivity.this,UpdateService.class);    startService(update);    }}      })     .setNegativeButton(R.string.button_update_no,new DialogInterface.OnClickListener() {   public void onClick(DialogInterface dialog, int which) {//如果放弃本次更新,将不再进行提示prefs.edit().putBoolean(PreferencesActivity.KEY_LATEST_VERSION_INSTALL, true).commit();Log.v(TAG, "129");launchActivity();}     })  .show();     return;       }  launchActivity();        }    } catch (PackageManager.NameNotFoundException e) {      Log.w(TAG, e);    }  }
?

?

?

private void install() {       Intent i = new Intent();   i.setAction(Intent.ACTION_VIEW);       i.setDataAndType(Uri.fromFile(new File(apkFile)),                   "application/vnd.android.package-archive");       startActivity(i);     }

?这个例子做了一个简单的跳转功能,通过Integer.parseInt(Build.VERSION.SDK) >= 5来分别启动适合不同系统版本的活动,使程序可以兼容跟多的手机。

?

private void launchActivity(){  if (Integer.parseInt(Build.VERSION.SDK) >= CameraManager.VERSION_CODES_LEVEL) {intent = new Intent(this,BJFILE.class);}else {intent = new Intent(this,EarlyBJFILE.class);}  startActivity(intent);  finish();  }
?

2.在BJFILE或EarlyBJFILE活动中重我们使用一个Service来检查首否需要更新应用,当服务器上的apk文件的最后修改时间与程序配置文件中的最后修改时间不同,则表示发现新更新。

?

UpdateService.class

?

@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);Log.v(TAG, "onStart");new Thread(){public void run(){if(checkUpdate()){//如果有更新,则显示更新界面UpdateActivity,类似一个对话框       Intent update = new Intent(UpdateService.this,UpdateActivity.class);       update.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);       update.putExtra(VERSITON, newVersion);      startActivity(update);    }else stopSelf();}}.start();}         //可能是不存在该请求对象,返回的向应头中没有设置last-modified域,则取到的值为0private long getLastModified() {try {URL url = new URL(UpdateActivity.updateURL);URLConnection con = (URLConnection) url.openConnection();Log.v(TAG, "con.getLastModified()"+con.getLastModified());return  con.getLastModified();} catch (MalformedURLException e) {e.printStackTrace();Log.v(TAG, "MalformedURLException");return  1;} catch (IOException e) {e.printStackTrace();Log.v(TAG, "IOException");return  2;}}//判断是否需要更新private boolean checkUpdate(){SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);long latest = prefs.getLong(PreferencesActivity.KEY_LATEST_VERSION, 0);newVersion = getLastModified();Log.v(TAG, "latest=" + latest);Log.v(TAG, "newVersion=" + newVersion);if(newVersion>latest)return true;else return false;}

?3.UpdateActivity的样式为

?

<style name="BackgroundOnly"><item name="android:windowBackground">@null</item><item name="android:windowContentOverlay">@null</item><item name="android:windowAnimationStyle">@null</item><item name="android:windowNoTitle">true</item><item name="android:windowNoDisplay">true</item><item name="android:windowIsFloating">true</item></style>

?源代码

import java.io.BufferedReader;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import android.app.Activity;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.DialogInterface;import android.content.Intent;import android.content.SharedPreferences;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.preference.PreferenceManager;import android.util.Log;public class UpdateActivity extends Activity{private static String TAG = "UpdateActivity";public static String updateURL = "http://www.bjnote.com/down4/bjnote.apk";//更新程序位置private static String updateContentURL="http://www.bjnote.com/down4/bjnote.txt";//更新内容private StringBuffer sb =null;private ProgressDialog download;private Handler mHandler;protected static final int GUI_STOP_NOTIFIER = 0x108;protected static final int GUI_THREADING_NOTIFIER = 0x109;protected static final int GUI_ERROR_NOTIFIER = 0x110;protected static final int GUI_IO_NOTIFIER = 0x111;protected static final int GUI_INTERRUPTED_NOTIFIER = 0x112;protected static final int GUI_PROGRESS_NOTIFIER = 0x113;//开始进度条的进度值显示protected static final int GUI_UPDATE_CONTENT_NOTIFIER = 0x114;//有更新文本private int count = 0;private long total;private DownThread downThread;private UpdateContent updateContent;private SharedPreferences prefs;private long newVersion;private String apkFile = Environment.getExternalStorageDirectory()+"/bjfile.apk";    class DownThread extends Thread{        private boolean cancel=false;    private  File file;                public void run() {                  HttpClient client = new DefaultHttpClient();                  HttpGet get = new HttpGet(updateURL);                  HttpResponse response = null;                 FileOutputStream fileOutputStream = null;                  InputStream is=null;                try {                  response = client.execute(get);                if(response.getStatusLine().getStatusCode()!=200)throw new IOException("StatusCode!=200");                    HttpEntity entity = response.getEntity();                      total = entity.getContentLength();                    mHandler.sendEmptyMessage(GUI_PROGRESS_NOTIFIER);                    is = entity.getContent();                     if (is != null) {                            file = new File(apkFile);                          fileOutputStream = new FileOutputStream(file);                                                    byte[] buf = new byte[1024];                          int ch = -1;                        while ((ch = is.read(buf)) != -1) {                        if(cancel)throw new InterruptedException();                        count+=ch;                            fileOutputStream.write(buf, 0, ch);                            mHandler.sendEmptyMessage(GUI_THREADING_NOTIFIER);                        }                         if(count==total)mHandler.sendEmptyMessage(GUI_STOP_NOTIFIER);                        fileOutputStream.flush();                        if(fileOutputStream!=null)fileOutputStream.close();                    }                 } catch (ClientProtocolException e) {                       e.printStackTrace();                    mHandler.sendEmptyMessage(GUI_ERROR_NOTIFIER);                    if(file.exists())file.delete();                         } catch (IOException e) {                if(file.exists())file.delete();                       e.printStackTrace();                      mHandler.sendEmptyMessage(GUI_IO_NOTIFIER);                } catch (InterruptedException e) {e.printStackTrace();if(file.exists())file.delete(); mHandler.sendEmptyMessage(GUI_INTERRUPTED_NOTIFIER);} finally{try {is.close();} catch (IOException e1) {e1.printStackTrace();}}            }                          private void setCancel(boolean isCancel){            cancel = isCancel;            }          }            //读取更新内容    class UpdateContent extends Thread{                public void run() {                  HttpClient client = new DefaultHttpClient();                  HttpGet get = new HttpGet(updateContentURL);                  HttpResponse response = null;                 BufferedReader bis = null;                 try {                  response = client.execute(get);                //添加更新提示                sb.append(UpdateActivity.this.getString(R.string.app_update_tip));                if(response.getStatusLine().getStatusCode()!=200){                throw new IOException("StatusCode!=200");                }                    HttpEntity entity = response.getEntity();                    //XXX 可能需要改成其他的编码,Apple默认是gb2312                    bis = new BufferedReader(new InputStreamReader(entity.getContent(),"gb2312"));                    String s=null;                    if (bis != null) {                      s=bis.readLine();                        while (s!=null) {                        sb.append("\n"+s);                        s=bis.readLine();                        }                         mHandler.sendEmptyMessage(GUI_UPDATE_CONTENT_NOTIFIER);                        bis.close();                    }                 } catch (ClientProtocolException e) {                       e.printStackTrace();                    stopService();                        } catch (IOException e) {                    e.printStackTrace();                      stopService();                }            }                      }    @Overridepublic void onCreate(Bundle bundle) {super.onCreate(bundle);Log.v(TAG, "onCreate");mHandler = new Handler() {public void handleMessage(Message msg) {switch(msg.what) {case GUI_THREADING_NOTIFIER:download.setProgress(count);break;case GUI_STOP_NOTIFIER: download.dismiss(); prefs.edit().putLong(PreferencesActivity.KEY_LATEST_VERSION, newVersion).commit(); //表示已下载但还未安装 prefs.edit().putBoolean(PreferencesActivity.KEY_LATEST_VERSION_INSTALL, false).commit();new AlertDialog.Builder(UpdateActivity.this)  .setCancelable(false)  .setTitle(R.string.app_update_title)  .setMessage(R.string.button_update_finish)  .setPositiveButton(R.string.button_ok,new DialogInterface.OnClickListener() {     public void onClick(DialogInterface dialog, int which) {  install();  }       })  .setNegativeButton(R.string.button_exit, new DialogInterface.OnClickListener() {  public void onClick(DialogInterface dialog, int which) {  stopService();  }   })  .show();break;case GUI_IO_NOTIFIER:case GUI_ERROR_NOTIFIER:if(download!=null)download.dismiss();new AlertDialog.Builder(UpdateActivity.this)  .setCancelable(false)  .setMessage(R.string.app_update_error)  .setPositiveButton(R.string.button_exit,new DialogInterface.OnClickListener() {     public void onClick(DialogInterface dialog, int which) {  stopService();  }       })  .show();break;case GUI_INTERRUPTED_NOTIFIER:download.dismiss();new AlertDialog.Builder(UpdateActivity.this)  .setCancelable(false)  .setMessage(R.string.app_update_cancel)  .setPositiveButton(R.string.button_exit,new DialogInterface.OnClickListener() {     public void onClick(DialogInterface dialog, int which) {  stopService();  //如果放弃本次更新,将不再进行提示  prefs.edit().putLong(PreferencesActivity.KEY_LATEST_VERSION, newVersion).commit();        prefs.edit().putBoolean(PreferencesActivity.KEY_LATEST_VERSION_INSTALL, true).commit();  }       })  .show();break;case GUI_PROGRESS_NOTIFIER: download.setMax((int) total); download.setProgress(0);break;case GUI_UPDATE_CONTENT_NOTIFIER:download();break;}}};newVersion = getIntent().getLongExtra(UpdateService.VERSITON, 0);prefs = PreferenceManager.getDefaultSharedPreferences(this);sb = new StringBuffer();updateContent = new UpdateContent();updateContent.start();}      private void install() {       Intent i = new Intent();        i.setAction(Intent.ACTION_VIEW);           i.setDataAndType(Uri.fromFile(new File(apkFile)),                   "application/vnd.android.package-archive");           startActivity(i);   }    private void download() {  downThread = new DownThread();  new AlertDialog.Builder(this).setTitle(R.string.app_update_title).setCancelable(false).setMessage(sb.toString()).setPositiveButton(R.string.button_update_ok,new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { download = new ProgressDialog(UpdateActivity.this); download.setMessage(getString(R.string.app_update_warn)); download.setCancelable(false); download.setIndeterminate(false); download.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);download.setButton(getString(R.string.button_cancel), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {downThread.setCancel(true);}});download.show();downThread.start();}     }) .setNegativeButton(R.string.button_update_no, new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {stopService();prefs.edit().putLong(PreferencesActivity.KEY_LATEST_VERSION, newVersion).commit();prefs.edit().putBoolean(PreferencesActivity.KEY_LATEST_VERSION_INSTALL, true).commit();} }).show();}/** * stopSelf,服务关闭自身 */private void stopService() {Intent stop = new Intent(this,UpdateService.class);stopService(stop);Log.v(TAG, "stopService");finish();Log.v(TAG, "finish activity");}@Overridepublic void onDestroy() {super.onDestroy();prefs=null;Log.v(TAG, "onDestroy");}}
2 楼 yanghuaixi 2011-01-06   我也刚刚做了一个相关的东西,有机会可以交流下 3 楼 ck19860613 2011-01-09   自己逻辑很清楚,就是表述出来不太清楚 4 楼 live17909 2011-04-17   老大,能发下源码吗?谢谢.paladin383@gmail.com

热点排行