編輯:關於Android編程
這裡說的不是熱修復怎麼實現修bug的原理,這裡說的是怎麼使用AndFix。如果你想了解更多的andFix實現原理,你可以參考下面的文章:

```AndFix的引入是: compile 'com.alipay.euler:andfix:0.3.1@aar' ```
導入AndFix的so庫文件以及極光推送的so庫文件;
極光推送集成參考文檔:http://docs.jpush.io/client/android_sdk/
注意:導入AndFix的so文件時,可以先閱讀這下個:https://github.com/zhonghanwen/AndFix-Ndk-Build-ADT

配置友盟在線參數的參數以及推光推送自定義的內容
友盟在線參數

極光推送自定義消息(自定義消息有長度限制,所以補丁的下載url寫成拼接形式:站點+下載資源名稱)

定義相對應的Bean

在啟動的自定義Application類進行初始化工作(AndFix、極光的初始化)

在程序的入口類進行友盟補丁的檢測:
private void getUmengParamAndFix() {
//獲取友盟在線參數對應key的values
String pathInfo = OnlineConfigAgent.getInstance().getConfigParams(this, UMENG_ONLINE_PARAM);
if (!TextUtils.isEmpty(pathInfo)){
PatchBean onLineBean = GsonUtils.getInstance().parseIfNull(PatchBean.class , pathInfo);
try {
//進行判斷當前版本是否有補丁需要下載更新
RepairBugUtil.getInstance().comparePath(this, onLineBean);
} catch (Exception e) {
e.printStackTrace();
}
}
}
再加上推送推送的自定義內容的處理:(當推送消息過來的時候應用處於運行狀態的時候,程序會處理消息進行下載補丁包)
private WeakHandler mHandler = new WeakHandler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == MSG_WHAT_DOWNLOAD){
String message = (String) msg.obj;
if (TextUtils.isEmpty(message)) return false;
try {
PatchBean bean = GsonUtils.getInstance().parse(PatchBean.class, message);
RepairBugUtil.getInstance().comparePath(MainActivity.this, bean);
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
});
//for receive customer msg from jpush server
private MessageReceiver mMessageReceiver;
public static final String MESSAGE_RECEIVED_ACTION = "com.zhw.andfix.MESSAGE_RECEIVED_ACTION";
public static final String KEY_MESSAGE = "message";
public void registerMessageReceiver() {
mMessageReceiver = new MessageReceiver();
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(MESSAGE_RECEIVED_ACTION);
registerReceiver(mMessageReceiver, filter);
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) {
String message = intent.getStringExtra(KEY_MESSAGE);
Message msg = new Message();
msg.what = MSG_WHAT_DOWNLOAD;
msg.obj = message;
mHandler.sendMessage(msg);
}
}
}
補丁包的生成
下載AndFix的補丁生成工具:here
apkpatch -m -o



自己測試一下成不成啦~
通過ThinDownloadManager下載補丁包,下載成功後使用AndFix加載補丁包的方法:
public void downloadAndLoad(Context context, final PatchBean bean, String downloadUrl) {
if (mLocalPreferencesHelper == null) {
mLocalPreferencesHelper = new LocalPreferencesHelper(context, SPConst.SP_NAME);
}
Uri downloadUri = Uri.parse(downloadUrl);
Uri destinationUri = Uri.parse(Environment.getExternalStorageDirectory()
.getAbsolutePath() + bean.url);
DownloadRequest downloadRequest = new DownloadRequest(downloadUri)
.setDestinationURI(destinationUri)
.setPriority(DownloadRequest.Priority.HIGH)
.setDownloadListener(new DownloadStatusListener() {
@Override
public void onDownloadComplete(int id) {
// add patch at runtime
try {
// .apatch file path
String patchFileString = Environment.getExternalStorageDirectory()
.getAbsolutePath() + bean.url;
BaseApplication.mPatchManager.addPatch(patchFileString);
Log.d(TAG, "apatch:" + patchFileString + " added.");
//復制且加載補丁成功後,刪除下載的補丁
File f = new File(patchFileString);
if (f.exists()) {
boolean result = new File(patchFileString).delete();
if (!result)
Log.e(TAG, patchFileString + " delete fail");
}
// mLocalPreferencesHelper.saveOrUpdate(SPConst.IsHavePathDownLoad, false);
} catch (IOException e) {
Log.e(TAG, "", e);
} catch (Throwable throwable) {
}
}
@Override
public void onDownloadFailed(int id, int errorCode, String errorMessage) {
//下載失敗的時候,標注標記位,等下次重新打開應用的時候重新下載
// mLocalPreferencesHelper.saveOrUpdate(SPConst.IsHavePathDownLoad, true);
Log.e(TAG, "onDownloadFailed");
}
@Override
public void onProgress(int id, long totalBytes, int progress) {
Log.e(TAG, "progress:" + progress);
}
});
mDownloadManager = new ThinDownloadManager(THREAD_COUNT);
mDownloadManager.add(downloadRequest);
}
判斷是否有補丁包需要下載的方法:
public void comparePath(Context context, PatchBean RemoteBean) throws Exception {
String pathInfo = mLocalPreferencesHelper.getString(SPConst.PATH_INFO);
final PatchBean localBean = GsonUtils.getInstance().parseIfNull(PatchBean.class, pathInfo);
//遠程的應用版本跟當前應用的版本比較
if (BaseApplication.VERSION_NAME.equals(RemoteBean.app_v)) {
//遠程的應用版本跟本地保存的應用版本一樣,但補丁不一樣,則需要下載重新
/**
*第一種情況:當本地記錄的Bean為空的時候(剛安裝的時候可能為空)並且遠程的Bean的path_v不為空的時候需要下載補丁。
* 第二種情況:當本地記錄的path_v和遠程Bean的path_v不一樣的時候需要下載補丁。
*/
if (localBean == null && !TextUtils.isEmpty(RemoteBean.path_v)
|| localBean.app_v.equals(RemoteBean.app_v) &&
!localBean.path_v.equals(RemoteBean.path_v)) {
downloadAndLoad(context, RemoteBean,
SPConst.URL_PREFIX + RemoteBean.url);
String json = GsonUtils.getInstance().parse(RemoteBean);
mLocalPreferencesHelper.saveOrUpdate(SPConst.PATH_INFO, json);
} /*else {
mLocalPreferencesHelper.saveOrUpdate(SPConst.IsHavePathDownLoad, false);
}*/
}
}
倍數提高工作效率的Android Studio奇技
這是從Philippe Breault的系列文章《Android Studio Tips Of the Day》中提取出來的自認為精華的部分。這些技巧在實際應用中能夠非常
Android開發之日期、時間選擇器(DatePicker和TimePicker)的功能和用法
日期、時間選擇器(DatePicker和TimePicker)的功能和用法 DatePicker和TimePicker是兩個比較常用的控件,它們都從FrameLa
Service使用全解析
什麼是ServiceService是Android 的四大組件之一,主要處理一些耗時的後台操作邏輯,或者輪詢操作等需要長期在後台運行的任務。甚至在程序退出之後,可以讓Se
Android初識之簡易計算器
之前自己的編程完全是在PC上進行的,而且主要是在算法和數據結構上。由於某些需要加之認識到Android的重要性,且大學走到現在基本上沒什麼課了,空閒時間很多,於是就開始學
Android項目編譯的時候出現:Caused by: java.lang.ClassNotFoundException: com.example.aaa.MainActivity
錯誤類型: 04-28 06:10:15.508: E/Andro
AndRoid源碼分析----------Handler消息機制(1)Handler獲取Message對象及Message的復用
在研究源碼之前,我們對Handler的了解一般是這樣的概念:在主線程中,