更新android应用到最新版本
更新應用的最新版本是每個上線apk都必須有的功能。
那么這個功能要怎樣實現呢?
一、首先我們理一下具體的思路:
1、最好采用異步請求的方式與服務器交互。即創建一個類,繼承AsyncTask類。
2、判斷當前的(即客戶端)apk版本是否小于服務器端的apk版本,如果小于,則向服務器端發送請求下載最新版本的apk。
3、下載最新的apk后,必須在客戶端創建一個路徑用來存放下載好的apk文件。所以在這一步之前,需在客戶端創建一個路徑。
4、下載apk得花費一點時間,為了更好的用戶體驗,我們最好寫一個進度框或一個動畫顯示正在下載的進度或者提示用戶apk正在更新。
5、通過更新apk接口,取得服務器返回的json或xml數據,包括最新的版本信息、下載apk的url、MD5、文件大小。解析json或xml數據,并將數據保存到一個bean文件中。
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(downloadPath 112 .lastIndexOf("/") + 1))); 113 114 File mFile = new File(params[0] 115 + downloadPath.substring(downloadPath 116 .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 @Override 154 protected void onProgressUpdate(Integer... values) { 155 156 super.onProgressUpdate(values); 157 } 158 159 // onPostExecute方法用于在執行完后臺任務后更新UI,顯示結果 160 @Override 161 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(MyMount 173 .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方法用于在取消執行中的任務時更改UI 189 @Override 190 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 @Override 205 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) {//返回數據為nullif(YContants.DEBUG) YLogUtil.printLog("codeUpdateJsonArray為空");return null;}if(YContants.DEBUG) YLogUtil.printLog(jsonObject);CodeUpdate codeUpdate=null;try {if (jsonObject.getInt("State")!=1) {//程序驗證不通過,則返回nullreturn 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:對于這個成員變量不能保存它的私有拷貝,而應直接與共享成員變量交互。用于多線程訪問,看作程度較輕的 synchronizedprivate 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);}/*** 當數據庫版本改變的時候調用*/@Overridepublic 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";
?
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);}} }
?
轉載于:https://www.cnblogs.com/wangchaozhangshu/p/5546002.html
總結
以上是生活随笔為你收集整理的更新android应用到最新版本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CPU性能测试
- 下一篇: 深入理解Openstack自动化部署