你的位置:首页 > 操作系统

[操作系统]android更新应用到最新版本


更新应用的最新版本是每个上线apk都必须有的功能。

那么这个功能要怎样实现呢?

一、首先我们理一下具体的思路:

  1、最好采用异步请求的方式与服务器交互。即创建一个类,继承AsyncTask类。

  2、判断当前的(即客户端)apk版本是否小于服务器端的apk版本,如果小于,则向服务器端发送请求下载最新版本的apk。

  3、下载最新的apk后,必须在客户端创建一个路径用来存放下载好的apk文件。所以在这一步之前,需在客户端创建一个路径。

  4、下载apk得花费一点时间,为了更好的用户体验,我们最好写一个进度框或一个动画显示正在下载的进度或者提示用户apk正在更新。

  5、通过更新apk接口,取得服务器返回的json或

  6、通过HttpClient取得服务器返回的安装包数据,保存到输入流中。

  7、将安装包数据保存为一个.tmp文件。如:安装包名为news,则保存的文件名为news.tmp。

  8、当安装包数据全部读取完成后,再将.tmp文件改名为以安装包名相同的文件,即news。

  9、将文件news进行解压,即可得到.apk文件。

 

二、具体实现代码:

SettingActivity.java :
 1 public class SettingActivity extends Activity { 2   private UpdateApkTask updateApkTask;// 更新apk线程 3   private ProgressDialog progressDialog;// 删除文件及数据库的load界面 4    5   @Override 6   protected void onCreate(Bundle savedInstanceState) { 7     super.onCreate(savedInstanceState); 8  9     setContentView(R.layout.activity_setting); 10  11     initUI(); 12     restorationDialog(); 13      14   } 15  16   protected void initUI() { 17     updateApk(); 18   } 19  20 /** 21    * 初始化progressDialog 22   */ 23   private void restorationDialog() { 24  25     progressDialog = new ProgressDialog(this); 26     progressDialog.setMessage(getString(R.string.restore_pDialog_title)); 27     progressDialog.setTitle(getString(R.string.hint)); 28     progressDialog.setCancelable(false);// 不可撤销 29  30   } 31  32   private updateApk(){ 33     stopUpdateApkTask(); 34    updateApkTask = new UpdateApkTask(); 35     FileUtils2.createFile(MyMount 36      .getImageStorageDir(SettingActivity.this)); 37  38    updateApkTask.execute(new String[] { MyMount 39      .getImageStorageDir(SettingActivity.this) }); 40   } 41  42 /** 43    * 更新程序版本线程 44    * 45   */ 46   private class UpdateApkTask extends AsyncTask<String, Integer, Boolean> { 47  48     private boolean tag = false; 49     public UpdateApkTask() { 50       progressDialog.show(); 51       progressDialog.setMessage(getString(R.string.apk_pDialog_title)); 52     } 53  54     // onPreExecute方法用于在执行后台任务前做一些UI操作 55     @Override 56     protected void onPreExecute() { 57  58       super.onPreExecute(); 59  60     } 61  62     // doInBackground方法内部执行后台任务,不可在此方法内修改UI 63     @Override 64     protected Boolean doInBackground(String... params) { 65       CodeUpdate mCodeUpdate = NetworkDataUpdate.getInstance( 66           SettingActivity.this).GetCodeUpdate(); 67       if (mCodeUpdate != null && mCodeUpdate.getUpdatePackName() != null) { 68  69         // 如果用户当前的apk版本号小于服务器中的apk版本号,则下载最新版本的apk 70         if (Float.parseFloat(VersionUtil.getVersionCode(SettingActivity.this)) < Float 71             .parseFloat(mCodeUpdate.getVersion())) { 72           tag = true; 73           String downloadPath = mCodeUpdate.getUpdatePackName();// 获取URL
              //如果url加了密,比如是这种形式:"http://<Dns>:<Port>/api/json/reply/",则要进行解密操作
74 downloadPath = downloadPath.replace("<Dns>",KeltiIntenface.ipStr).replace("<Port>",KeltiIntenface.postStr);// 替换URL的ip及post 75 76 InputStream is = null; 77 FileOutputStream fos = null; 78 File tmpFile = null; 79 80 try { 81 HttpClient httpClient = new DefaultHttpClient(); 82 HttpGet httpGet = new HttpGet(downloadPath); 83 HttpResponse httpResponse = httpClient.execute(httpGet); 84 HttpEntity entity = httpResponse.getEntity(); 85 is = entity.getContent(); 86 87 if (httpResponse.getStatusLine().getStatusCode() != 200) { 88 89 return false; 90 } 91 // 新建文件,下载文件 92 tmpFile = new File(params[0] 93 + downloadPath.substring(downloadPath 94 .lastIndexOf("/") + 1) + ".tmp"); 95 96 if (is != null) { 97 fos = new FileOutputStream(tmpFile); 98 byte[] buf = new byte[1024 * 1024 * 4]; 99 int ch = -1;100 while ((ch = is.read(buf)) != -1) {101 fos.write(buf, 0, ch);102 }103 }104 105 fos.flush();106 if (fos != null) {107 fos.close();108 }109 if (is != null) {110 tmpFile.renameTo(new File(params[0]111 + downloadPath.substring(downloadPath112 .lastIndexOf("/") + 1)));113 114 File mFile = new File(params[0]115 + downloadPath.substring(downloadPath116 .lastIndexOf("/") + 1));117                 //解压下载完成后的文件,将mFile文件解压到params[0]目录,且解压完成后,将压缩包删除,以节省客户端的存储空间118 if (DecompressionZip.upZipFile(mFile, params[0]) == 0) {119 120 YLogUtil.printSpidLog("mFile="+mFile.toString());121 mFile.delete();122 return true;123 }124 125 }126 } catch (ConnectException connectException) {127 128 if (tmpFile != null && tmpFile.exists()) {129 YLogUtil.printSpidLog("tmpFile="+tmpFile.toString());130 tmpFile.delete();131 }132 connectException.printStackTrace();133 134 } catch (SocketTimeoutException socketTimeoutException) {135 136 if (tmpFile != null && tmpFile.exists()) {137 YLogUtil.printSpidLog("tmpFile="+tmpFile.toString());138 tmpFile.delete();139 }140 socketTimeoutException.printStackTrace();141 142 } catch (Exception e) {143 e.printStackTrace();144 145 }146 }147 148 }149 return false;150 }151 152 // onProgressUpdate方法用于更新进度信息153 @Override154 protected void onProgressUpdate(Integer... values) {155 156 super.onProgressUpdate(values);157 }158 159 // onPostExecute方法用于在执行完后台任务后更新UI,显示结果160 @Override161 protected void onPostExecute(Boolean result) {162 163 super.onPostExecute(result);164 165 progressDialog.dismiss();166 if (result) {167 168 ToastUtils.showToast(SettingActivity.this,169 getString(R.string.toast_download_succeed), false);170 FileUtils2.openFile(171 SettingActivity.this,172 new File(MyMount173 .getImageStorageDir(SettingActivity.this)174 + YContants.apkPath));175 } else {176 // 如果用户当前的apk版本号等于服务器中的apk版本号,则告诉用户已经是最新版本177 if (!tag) {178 ToastUtils.showToast(SettingActivity.this, getString(R.string.latestVersion), true);179 180 }else {181 ToastUtils.showToast(SettingActivity.this,182 getString(R.string.toast_download_fail), false);183 }184 }185 186 }187 188 // onCancelled方法用于在取消执行中的任务时更改UI189 @Override190 protected void onCancelled() {191 192 super.onCancelled();193 progressDialog.dismiss();194 }195 196 }197 198 private void stopUpdateApkTask() {199 if (updateApkTask != null && !updateApkTask.isCancelled()) {200 updateApkTask.cancel(true);201 }202 }203 204 @Override205 protected void onDestroy() {206 207 stopUpdateApkTask();208 super.onDestroy();209 }210 211 }

 

FileUtils2.java:

public class FileUtils2 {  /**   * 创建文件夹   *   * @param pathString   *      文件夹路径   */  public static boolean createFile(String pathString) {    if (pathString == null || pathString.equals("")        || pathString.equals("null") || !pathString.contains("/")) {      return false;    } else {      File file = new File(pathString.substring(0,          pathString.lastIndexOf("/") + 1));      if (!file.exists()) {        try {          // 按照指定的路径创建文件夹          file.mkdirs();        } catch (Exception e) {          e.printStackTrace();          return false;        }      }      return fileCanReadWrite(file);    }  }  /**   * 判断文件夹/文件是否可读写   *   * @param file   *      文件路径   * @return   */  public static boolean fileCanReadWrite(File file) {    if (file.canWrite() && file.canRead()) {      return true;    } else {      return false;    }  }

/**   * 安装程序   *   * @param context  上下文   * @param file  apk的保存路径   */  public static void openFile(Context context, File file) {    try {      Intent mIntent = new Intent();      mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);      mIntent.setAction(android.content.Intent.ACTION_VIEW);      mIntent.setDataAndType(Uri.fromFile(file),          "application/vnd.android.package-archive");      context.startActivity(mIntent);    } catch (Exception e) {      e.printStackTrace();      ToastUtils.showToast(          context,          context.getResources().getString(              R.string.toast_openApk_error), false);    }  }

 

}

 

ToastUtils.java:

public class ToastUtils {    public static void showToast(Context context, String msg, Boolean isTimeLong){     int time = Toast.LENGTH_SHORT;     if(isTimeLong){       time = Toast.LENGTH_LONG;     }          Toast toast = Toast.makeText(context, null, time);     LinearLayout layout = (LinearLayout)toast.getView();         layout.setBackgroundResource(R.drawable.toast_bg);    layout.setOrientation(LinearLayout.VISIBLE);     layout.setGravity(Gravity.CENTER);     TextView tv = new TextView(context);     tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));       tv.setGravity(Gravity.CENTER);     tv.setTextColor(Color.parseColor("#000000"));     tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30);     tv.setPadding(0, 0, 0, 0);     tv.setText(msg);     layout.addView(tv);     toast.show();   } }

 

MyMount.java:

public class MyMount {/**   * 获取图片,视频,html存储路径   *   * @return   */  @SuppressLint("DefaultLocale")  public static String getImageStorageDir(Context context) {    String pathStr = "";    File storageDirFile = new File("/mnt/");    if (storageDirFile.isDirectory()) {      String[] dirList = storageDirFile.list();      if (dirList != null) {        for (int i = 0; i < dirList.length; i++) {          String dirString = (dirList[i]).toLowerCase();          if (dirString.equals("sdcard")) {            if (ifValid("/mnt/" + dirList[i] + "/")) {              pathStr = dirList[i];            }          }        }      }    }    if (pathStr.equals("")) {      return getFileDir(context) + "/spid/";    }    File mFile=new File("/mnt/" + pathStr + "/spid/");    if (!mFile.exists()) {      mFile.mkdirs();    }    return "/mnt/" + pathStr + "/spid/";  }}

 

CodeUpdate.java:

public class CodeUpdate {  private String ModuleId;  private String Version;  private String UpdatePackName;  private String MD5;  private String FileSize;  public String getModuleId() {    return ModuleId;  }  public void setModuleId(String moduleId) {    ModuleId = moduleId;  }  public String getVersion() {    return Version;  }  public void setVersion(String version) {    Version = version;  }  public String getUpdatePackName() {    return UpdatePackName;  }  public void setUpdatePackName(String updatePackName) {    UpdatePackName = updatePackName;  }  public String getMD5() {    return MD5;  }  public void setMD5(String mD5) {    MD5 = mD5;  }  public String getFileSize() {    return FileSize;  }  public void setFileSize(String fileSize) {    FileSize = fileSize;  }}

 

NetworkDataUpdate.java:

/** * 获取网络Json数据并解析,插入本地数据库 * */public class NetworkDataUpdate{    private static NetworkDataUpdate instance;    private Context context;  //接口参数  private String []propertyName={"datetime","clientID"};    private ImageLoader imageLoader;  private Des mDes=new Des();    public NetworkDataUpdate(Context context){    this.context=context;        imageLoader=ImageLoader.getInstance(context, MyMount.getImageStorageDir(context));  }    public static NetworkDataUpdate getInstance(Context context){    if (instance==null) {      instance=new NetworkDataUpdate(context);    }    return instance;  }  /**   * 更新apk接口   * @return   */  public CodeUpdate GetCodeUpdate(){    String mac="";    try {      mac=mDes.createEncrypt(UniqueIdentifier.getInstance(context).getMac());    } catch (UnsupportedEncodingException e1) {      e1.printStackTrace();    }    String []propertyValue=new String[]{mac};    String []propertyName=new String[]{"clientID"};    //通过GetCodeUpdate接口,发送请求,从服务器端接收返回的json数据    JSONObject jsonObject=UrlData2Json.getJSONObject(YContants.namespace, KeltiIntenface.FunctionName.GetCodeUpdate, KeltiIntenface.url, propertyName, propertyValue, null);            if (jsonObject==null) {//返回数据为null      if(YContants.DEBUG) YLogUtil.printLog("codeUpdateJsonArray为空");      return null;    }        if(YContants.DEBUG) YLogUtil.printLog(jsonObject);    CodeUpdate codeUpdate=null;        try {            if (jsonObject.getInt("State")!=1) {//程序验证不通过,则返回null        return null;      }      JSONObject childJsonObject=jsonObject.getJSONObject("Data");            codeUpdate=new CodeUpdate();      codeUpdate.setModuleId(childJsonObject.getString("ModuleId"));      codeUpdate.setVersion(childJsonObject.getString("Version"));      codeUpdate.setUpdatePackName(childJsonObject.getString("UpdatePackName"));      codeUpdate.setMD5(childJsonObject.getString("MD5"));      codeUpdate.setFileSize(childJsonObject.getString("FileSize"));          } catch (JSONException e) {      e.printStackTrace();    }        if (codeUpdate.getModuleId()!=null&&!codeUpdate.getModuleId().equals("")) {      DataAddDB.addApk(context,"1", codeUpdate);    }            return codeUpdate;      }}

 

DataAddDB.java:

public class DataAddDB {/**   * 向Apk表插入数据   * @param context   * @param downloadList   */  public static void addApk(Context context,String appID,CodeUpdate codeUpdate){        HashMap<String, Object> mHashMap=DButil2.getInstance(context).queryTableApk(appID);        boolean isExist=false;//用于标记表id是否重复    if (appID.equals(mHashMap.get(DBContants.TableApkUpdate.ID)+"")) {              isExist=true;    }          ContentValues values=new ContentValues();    values.put(DBContants.TableApkUpdate.ID, appID+"");    values.put(DBContants.TableApkUpdate.VERSION, codeUpdate.getVersion());    values.put(DBContants.TableApkUpdate.UpdatePackName, codeUpdate.getUpdatePackName());    values.put(DBContants.TableApkUpdate.MD5, codeUpdate.getMD5());    values.put(DBContants.TableApkUpdate.FileSize, codeUpdate.getFileSize());          if (!isExist) {            DButil2.getInstance(context).addTableApkUpdate(values);    }    else {      DButil2.getInstance(context).updateTableApk(values, appID+"");    }        }  }

 

DButils2.java:

public class DButil2 extends DBUtil1{  //volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。用于多线程访问,看作程度较轻的 synchronized  private volatile static DButil2 instance;     private DButil2(Context context){    super(context);      }     public static DButil2 getInstance(Context context){    ifReadCount=0;    if(instance==null){           synchronized(DButil2.class){               if(instance==null){                   instance=new DButil2(context);                 }           }       }     return instance;     }//*****************************************************apk更新************************************************  public HashMap<String, Object>queryTableApk(String appID){    Cursor cursor = db.rawQuery("select * from apkUpdate where Id=?",new String[]{appID+""});        return queryTableApk(cursor);  }}

 

DButil1.java:

public class DBUtil1 extends RootDBUtil {  private volatile static DBUtil1 instance;    protected DBUtil1(Context context) {    super(context);      }    public static DBUtil1 getInstance(Context context){    if(instance==null){             synchronized(DBUtil1.class){               if(instance==null){                   instance=new DBUtil1(context);                 }           }       }    return instance;  }/**   * 查询apk表   * @param cursor   * @return   */  public HashMap<String, Object>queryTableApk(Cursor cursor){    HashMap<String, Object>mHashMap=new HashMap<String, Object>();    try {      while (cursor.moveToNext()) {        mHashMap.put(DBContants.TableApkUpdate.ID, cursor.getString(0));        mHashMap.put(DBContants.TableApkUpdate.VERSION, cursor.getString(1));        mHashMap.put(DBContants.TableApkUpdate.UpdatePackName, cursor.getString(2));        mHashMap.put(DBContants.TableApkUpdate.MD5, cursor.getString(3));        mHashMap.put(DBContants.TableApkUpdate.FileSize, cursor.getString(4));              }          } catch (Exception e) {      e.printStackTrace();    }finally{      if (!cursor.isClosed()) {        cursor.close();      }    }    return mHashMap;  }}

 

RootDBUtil.java:

public class RootDBUtil {  private volatile static RootDBUtil instance;  SQLiteDatabase db;  protected RootDBUtil(Context context) {        db = new DBHelper(context).getWritableDatabase();              }    public static RootDBUtil getInstance(Context context) {    if(instance==null){             synchronized(RootDBUtil.class){               if(instance==null){                   instance=new RootDBUtil(context);                 }           }       }    return instance;  }//******************************************************apk更新*******************************************************  public synchronized void addTableApkUpdate(ContentValues values){    try {      db.insert(DBContants.TableApkUpdate.TABLE_NAME, null, values);    } catch (Exception e) {      e.printStackTrace();    }    }    public synchronized void updateTableApk(ContentValues values,String id){    try {      db.update(DBContants.TableApkUpdate.TABLE_NAME, values, DBContants.TableApkUpdate.ID + " = ? ", new String[] { id });    } catch (Exception e) {      e.printStackTrace();    }  }}

 

DBHelper.java:

public class DBHelper extends SQLiteOpenHelper {  /**   * 数据库版本   */  private static final int VERSION = 1;  /**   * 数据库名称   */  public static final String NAME = "spidclient.db";  private Context context;  /**   *   * @param name   *       数据库文件名   * @param factory   *      游标工厂   * @param version   *      数据库版本,最小值为1   */  public DBHelper(Context context) {    super(context, NAME, null, VERSION);    this.context=context;  }  /**   * 第一次创建数据库的时候调用   */  public void onCreate(SQLiteDatabase db) {    /**     *     * create table t_contact(id integer primary key autoincrement, name     * text, photo integer, phone text, address text, email text, pin_yin     * text);     *     */                createUpdateApk(db);          }  /**   * 当数据库版本改变的时候调用   */  @Override  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {    // TODO Auto-generated method stub      }  /**   * 更新apk   * @param db   */  private void createUpdateApk(SQLiteDatabase db){    StringBuilder sb = new StringBuilder(" create table ").append(DBContants.TableApkUpdate.TABLE_NAME).append("(")//                .append(DBContants.TableApkUpdate.ID).append(" Integer primary key autoincrement,")//        .append(DBContants.TableApkUpdate.VERSION).append(" Integer, ")//        .append(DBContants.TableApkUpdate.UpdatePackName).append(" text, ")//        .append(DBContants.TableApkUpdate.MD5).append(" text, ")//        .append(DBContants.TableApkUpdate.FileSize).append(" text); ");    //执行创表语句    db.execSQL(sb.toString());    }}

 

DBContants.java:

public class DBContants {  //apk更新表  public static class TableApkUpdate{    public static final String TABLE_NAME="apkUpdate";    public static final String ID="Id";    public static final String VERSION="Version";    public static final String UpdatePackName="UpdatePackName";    public static final String MD5="MD5";    public static final String FileSize="FileSize";    }}

 

KeltiIntenface.java:

public class KeltiIntenface {  public static String ipStr="newkelti.ip24.com.cn";  public static String postStr="860";

    //程序更新接口
    public static String url="http://"+ipStr+":"+postStr+"/WebService/Pad_DataUpdate.asmx";

  public static class FunctionName{     //更新apk    public static String GetCodeUpdate="GetCodeUpdate_v01";//"GetCodeUpdate";  }}

 

YContants.java:

public class YContants {    // 命名空间  public static String namespace = "http://tempuri.org/";}

 

Des.java:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import android.annotation.SuppressLint;
import android.util.Base64;
import java.io.IOException;
import java.io.UnsupportedEncodingException;



/** * 解密 */public class Des {

 private Cipher c; // 密码器

  private byte[] cipherByte;
  private SecretKey deskey; // 密钥

  private String keyString = "A3F2569DESJEIWBCJOTY45DYQWF68H1Y"; // 获得密钥的参数

  /**   * 加密   * @param data   * @return   * @throws UnsupportedEncodingException   */  public String createEncrypt(String data)      throws UnsupportedEncodingException {    if (data.equals("")) {      return "";    }    try {      byte[] buffData = data.getBytes("UTF8");      byte[] dKey = deBase64(keyString);      deskey = new javax.crypto.spec.SecretKeySpec(dKey, Algorithm);      try {        c = Cipher.getInstance(Algorithm);      } catch (Exception e) {        e.printStackTrace();      }      c.init(Cipher.ENCRYPT_MODE, deskey);      cipherByte = c.doFinal(buffData);    } catch (java.security.InvalidKeyException ex) {      ex.printStackTrace();    } catch (javax.crypto.BadPaddingException ex) {      ex.printStackTrace();    } catch (javax.crypto.IllegalBlockSizeException ex) {      ex.printStackTrace();    } catch (IOException e) {      e.printStackTrace();    }    return Base64.encodeToString(cipherByte, Base64.DEFAULT);  }}

 

UrlData2Json.java:

/** * 获取接口Json数据 * */public class UrlData2Json {  /**   * 返回一个JSONObject对象   *   * 说明:参数名数组和参数值数组要一一对应   *   * @param namespace 命名空间   * @param methoName 方法名   * @param url 接口地址   * @param propertyName 参数名数组   * @param propertyValue 参数值数组   * @param networkExceptionListener 监听器   * @return   */  public static JSONObject getJSONObject(String namespace, String methoName,      String url, String []propertyName,      Object[] propertyValue,YNetworkExceptionListener networkExceptionListener) {        try {      SoapObject soapObject = new SoapObject(namespace, methoName);      SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(          SoapEnvelope.VER11);      if (propertyName!=null&&propertyValue!=null) {        for (int i = 0; i < propertyName.length; i++) {          // 带参数的方法调用,若调用无参数的,则无需此句          soapObject.addProperty(propertyName[i],propertyValue[i]);// 添加参数        }      }            envelope.dotNet = true;      envelope.setOutputSoapObject(soapObject);      HttpTransportSE httpTranstation = new HttpTransportSE(url,YContants.CONNECTION_TIME);      httpTranstation.call(namespace + methoName, envelope);             Object result = envelope.getResponse();            if (null==result) {        return new JSONObject();      }      String str = (String) result.toString();// 获得请求的字符串      JSONObject jObject = new JSONObject(str);            return jObject;          }     catch(ConnectException connectException){      if (networkExceptionListener!=null) {        networkExceptionListener.networkException();              }      connectException.printStackTrace();      if(YContants.DEBUG) YLogUtil.printLog("connectException");    }    catch (SocketTimeoutException socketTimeoutException) {      if (networkExceptionListener!=null) {        networkExceptionListener.connectionTimeOut();              }      socketTimeoutException.printStackTrace();      if(YContants.DEBUG) YLogUtil.printLog("socketTimeoutException");    }    catch (JSONException e) {          if (networkExceptionListener!=null) {        networkExceptionListener.JSONException();              }      e.printStackTrace();      if(YContants.DEBUG) YLogUtil.printLog("JSONException");    }        catch (Exception e) {      if (networkExceptionListener!=null) {        networkExceptionListener.otherException();      }      e.printStackTrace();      if(YContants.DEBUG) YLogUtil.printLog("Exception");          }        return null;  }}

 

VersionUtil.java:

import android.content.Context;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;public class VersionUtil {  public static String getVersionCode(Context context) {    String version = "1.0";    try {      // 获取packagemanager的实例      PackageManager packageManager = context.getPackageManager();      // getPackageName()是你当前类的包名,0代表是获取版本信息      PackageInfo packInfo;      packInfo = packageManager.getPackageInfo(context.getPackageName(),          0);      version = packInfo.versionName;    } catch (NameNotFoundException e) {      e.printStackTrace();    }    return version;  }}

 

DecompressionZip.java:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;


/** * 解压ZIP文件 * */public class DecompressionZip {/** * 解压功能 * 将zipFile文件解压到folderPath目录 * * @param zipFile 压缩文件 * @param folderPath 存储路径 * @return * @throws ZipException * @throws IOException */ @SuppressWarnings("rawtypes") public static int upZipFile(File zipFile, String folderPath) throws ZipException, IOException { ZipFile zfile = new ZipFile(zipFile); Enumeration zList = zfile.entries();//压缩文件的条目 ZipEntry ze = null; byte[] buf = new byte[1024]; while (zList.hasMoreElements()) { ze = (ZipEntry) zList.nextElement(); if (ze.isDirectory()) {//判断是否为一个目录 String dirstr = folderPath + ze.getName(); dirstr = new String(dirstr.getBytes("8859_1"), "GB2312"); File f = new File(dirstr); f.mkdir(); continue; } OutputStream os = new BufferedOutputStream(new FileOutputStream( getRealFileName(folderPath, ze.getName()))); InputStream is = new BufferedInputStream(zfile.getInputStream(ze)); int readLen = 0; while ((readLen = is.read(buf, 0, 1024)) != -1) { os.write(buf, 0, readLen); } is.close(); os.close(); } zfile.close(); return 0; }}

 

YLogUtil.java:

/** * 打印log * */public class YLogUtil {
private static final boolean LOG_DEBUG = true;//log输出的开关public static <T> void printSpidLog(T log) { if(LOG_DEBUG){ String logText=""; try { String lineFormat = "类名:%s---方法名:%s---第%d行"; StackTraceElement traceElement = Thread.currentThread().getStackTrace()[3]; logText = String.format(lineFormat, traceElement.getFileName(), traceElement.getMethodName(), traceElement.getLineNumber()); } catch (Exception e) { e.printStackTrace(); logText="找不到出错位置"; } Log.i("spid",logText+"---信息:"+log); } }}