标签:created 自己 tco 格式 keep mis runnable attribute jar
首先,它是一个热修复的解决方案,可以紧急修复我们的线上bug,并且针对于第一次加载补丁的时候,它是及时生效的,并且集成起来相对简单,这是它的优点。
当然,它的局限性也是显而易见的:
public static void test(Context context) {
//旧代码
//Toast.makeText(context.getApplicationContext(), "It‘s a Bug", Toast.LENGTH_SHORT).show();
//新代码
Toast.makeText(context.getApplicationContext(), "It‘s a Bug ,but already fixed", Toast.LENGTH_SHORT).show();
}
//新增temp变量不允许!
private static String temp = "new apk...";
public static void test(Context context) {
Toast.makeText(context.getApplicationContext(), temp, Toast.LENGTH_SHORT).show();
}
//private static String str = "old apk...";
private static String str= "new apk...";//修改全局变量也是不允许的,静态变量也同样不允许
public Test() {
//temp = "old"; 修复前
temp = "new"; //这样也是不允许的,不允许修改构造函数
}
//另一方面代码块也是不允许修改的, 也会被打补丁工具直接忽略. 包括静态代码块
{
Log.d(TAG, "old block");
}
static{
Log.d(TAG, "new block");
}
public static void test(Context context) {
newMethod(context);
}
//新增方法是不可以的
public static void newMethod(Context context) {
Toast.makeText(context.getApplicationContext(), "new method", Toast.LENGTH_SHORT).show();
}
假设test方法被反射调用, 因为静态方法反射调用可以有两种方式, 所以会出现以下两种情况, 一一说明
Class cls = BaseBug.class;
Method method = cls.getDeclaredMethod("test", new Class[]{Context.class});
method.invoke(new BaseBug(), new Object[]{mContext});//这样是不被允许的
method.invoke(null, new Object[]{mContext});//这样是可以的,因为参数是null
非静态方法调用肯定是类似method.invoke(new BaseBug(), new Object[]{}); 参考上面,所以此时test方法不能被patch.
public @interface MethodInfo {
String info() default "old apk...";
}
public @interface MethodInfo {
String info() default "new apk...";//这样是不可以的,打补丁时会忽略此修改
}
//==============另一个例子
//修复前 @MethodInfo(info="old")
@MethodInfo(info="new")//修复后。 这样是可以的
public static void test(Context context {
Toast.makeText(context.getApplicationContext(), "old apk...", Toast.LENGTH_SHORT).show();
}
repositories {
maven {
url "http://repo.baichuan-android.taobao.com/content/groups/public/"
}
}
dependencies {
compile ‘com.alibaba.sdk.android.plugins:alisdk-hotfix:1.3.3‘
compile ‘com.alibaba.sdk.android.plugins.jar:alisdk-utdid:0.0.1‘
}
//注意:如果你的项目已经依赖alisdk-utdid,则不需要再进行依赖
compile (‘com.alibaba.sdk.android.plugins:alisdk-hotfix:1.3.3‘){
// exclude module:"alisdk-utdid"
transitive false
//这里exclude 这一句和transitive这一句可以二选一
}
<meta-data
android:name="com.taobao.android.hotfix.APPSECRET"
android:value="your-app-secret" />
<meta-data
android:name="com.taobao.android.hotfix.RSASECRET"
android:value="your-rsa-secret" />
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 存储读写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
package com.tango.hotfdemo;
import android.app.Application;
import com.taobao.hotfix.HotFixManager;
import com.taobao.hotfix.PatchLoadStatusListener;
import com.taobao.hotfix.util.PatchStatusCode;
/**
* Created by Administrator on 2016/12/13.
*/
public class MyApplication extends Application {
public static String appVersion;
public static String appId;
@Override
public void onCreate() {
super.onCreate();
initApp();
// initHotfix(); 为了演示,这里没有调用。而是要结合它的Debug工具使用
}
private void initApp() {
this.appId = "000000"; //替换掉自己应用的appId,这里我是瞎写的
try {
this.appVersion = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName;
} catch (Exception e) {
this.appVersion = "1.0.0";
}
}
/**
* 建议在Application.onCreate方法中执行initialize和queryNewHotPatch操作, 尽可能早的执行
* 本demo只是为了测试的方便, 所以没有调用
*/
private void initHotfix() {
HotFixManager.getInstance().initialize(this, appVersion, appId, true, new PatchLoadStatusListener() {
@Override
public void onload(int mode, int code, String info, int handlePatchVersion) {
// 补丁加载回调通知
if (code == PatchStatusCode.CODE_SUCCESS_LOAD) {
// TODO: 10/24/16 表明补丁加载成功
} else if (code == PatchStatusCode.CODE_ERROR_NEEDRESTART) {
// TODO: 10/24/16 表明新补丁生效需要重启. 业务方可自行实现逻辑, 提示用户或者强制重启, 建议: 用户可以监听进入后台事件, 然后应用自杀
} else {
// TODO: 10/25/16 其它错误信息, 查看PatchStatusCode类说明
}
}
});
HotFixManager.getInstance().queryNewHotPatch();
}
}
package com.tango.hotfdemo;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.taobao.hotfix.HotFixManager;
import com.taobao.hotfix.PatchLoadStatusListener;
public class MainActivity extends AppCompatActivity {
private Button btn_click;
private static final int REQUEST_EXTERNAL_STORAGE_PERMISSION = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initHotfix();
}
/**
* 为了测试的方便, initialize放在activity中, 但是实际上initialize应该放在Application的onCreate方法中, 需要尽可能早的做初始化.
*/
private void initHotfix() {
HotFixManager.getInstance().initialize(this.getApplication(), MyApplication.appVersion, MyApplication.appId, true, new PatchLoadStatusListener() {
@Override
public void onload(final int mode, final int code, final String info, final int handlePatchVersion) {
runOnUiThread(new Runnable() {
@Override
public void run() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Mode:").append(mode).append(" Code:").append(code).append(" Info:").append(info).append(" HandlePatchVersion:").append(handlePatchVersion);
// updateConsole(stringBuilder.toString());
}
});
}
});
if (Build.VERSION.SDK_INT >= 23) {
requestExternalStoragePermission();
}
}
/**
* 如果本地补丁放在了外部存储卡中, 6.0以上需要申请读外部存储卡权限才能够使用. 应用内部存储则不受影响
*/
private void requestExternalStoragePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_EXTERNAL_STORAGE_PERMISSION);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE_PERMISSION:
if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
}
break;
default:
}
}
private void initView() {
btn_click = (Button) findViewById(R.id.btn_click);
btn_click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"我是一个大bug",Toast.LENGTH_LONG).show();
}
});
}
}
#基线包使用,生成mapping.txt
#-printmapping mapping.txt
#生成的mapping.txt在app/buidl/outputs/mapping/release路径下,移动到/app路径下
#修复后的项目使用,保证混淆结果一致
-applymapping mapping.txt
#这里需要解释一下,当生成基准包的时候呢,打开这个配置-printmapping mapping.txt,目的是为了生成一个混淆的规则文件,然后copy到/app路径下,这样,在打补丁包的时候,再打开这个配置-applymapping mapping.txt,保证两次混淆的规则是一致的,以免不必要的冲突
#HotFix
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
native <methods>;
}
-keep class com.alipay.euler.andfix.**{
*;
}
-keep class com.taobao.hotfix.aidl.**{*;}
-keep class com.ta.utdid2.device.**{*;}
-keep class com.taobao.hotfix.HotFixManager{
public *;
}
btn_click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"I‘m a Big Bug!But I‘m already Fixed!",Toast.LENGTH_LONG).show();
}
});
java -jar BCFixPatchTools-1.3.0.jar -cmd patch -src_apk c:\Users\Administrator\Desktop\hotFix打包文件夹\old.apk -fixed_apk c:\Users\Administrator\Desktop\hotFix打包文件夹\new.apk -wp c:\Users\Administrator\Desktop\hotFix打包文件夹\BuDing -sign_file_url c:\Users\Administrator\Desktop\hotFix打包文件夹\babytree.keystore -sign_file_pass tangotango -sign_alias tangotango -sign_alias_pass tangotango
java -jar BCFixPatchTools-1.3.0.jar -cmd patch //固定格式
-src_apk 基准包的地址,也就是old.apk 这里要用绝对路径
-fixed_apk 新包的地址,同样要绝对路径
-wp 我们生成的补丁包将会放到哪个路径下 也是绝对路径(也就是我们创建的那个文件夹)
-sign_file_url 签名文件 绝对路径
-sign_file_pass
-sign_alias
-sign_alias_pass 这就不用多说了,签名文件的那些口令
标签:created 自己 tco 格式 keep mis runnable attribute jar
原文地址:http://blog.csdn.net/kinglongsky123/article/details/53613182