andfix热修复

news/2024/7/8 6:54:35

andfix的基本介绍

https://github.com/alibaba/AndFix

AndFix优劣
1.原理简单,集成简单,使用简单,即使生效
2.只能修复方法及别的bug,极大的限制了使用场景

AndFix执行流程及核心原理

 1.添加依赖:compile 'com.alipay.euler:andfix:0.5.0@aar'
 2.为什么有的应用需要在project中的build中添加classpath?
    APP中的build无论apply还是android中的其他要么是类要么是方法,而这些方法或者类是来自project中classpath中的插件里面的,所以如果只是提供Java代码则只需要添加依赖即可,如果需要添加自定义grade脚本则需要添加classpath

使用AndFix完成线上bug修复

1.封装一个类管理andfix所有的api

public class AndFixPathManager {
private PatchManager mPatchManager=null;
private static AndFixPathManager mInstance = null;

public static AndFixPathManager getInstance() {
    if (mInstance == null) {
        synchronized (AndFixPathManager.class) {
            if (mInstance == null) {
                mInstance = new AndFixPathManager();
            }
        }
    }
    return mInstance;
}

//初始化AndFix方法
public void initPatch(Context context) {
    mPatchManager = new PatchManager(context);
    mPatchManager.init(Utils.getVersionName(context));
    mPatchManager.loadPatch();
}
//加载我们的patch文件
public void addPatch(String path){
    try {
        if(mPatchManager!=null) {
            mPatchManager.addPatch(path);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

2,Utils获取当前版本名和测试输出空指针
public class Utils {
public static String getVersionName(Context context){
    String versionName="1.0.0";
    PackageManager packageManager = context.getPackageManager();
    try {
        PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
        return packageInfo.versionName;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return versionName;

}

public static void printLog() {
    String error="";
    Log.e("TAG",error);
}
}
新建MyApplication初始化andfix
      AndFixPathManager.getInstance().initPatch(this);

准备一个错误apk

1.布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.yijia.andfix.MainActivity"
android:orientation="vertical">

<Button
    android:id="@+id/kill_view"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center"
    android:text="产生bug"
    android:onClick="createBug"
    android:textSize="23sp"/>

<Button
    android:id="@+id/clean_view"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center"
    android:onClick="fixBug"
    android:text="解决bug"
    android:textSize="23sp"/>
</LinearLayout>

2.printLog方法

public static void printLog() {
    String error=null;
    Log.e("TAG",error);
}

apatch文件生成

1.去官网下载一个tool(apkpatch-1.0.3)

2.打开apkpatch然后将oldapk和newapk,jks并新建一个输出文件的文件夹outputs


3.使用命令:apkpatch查看命令;使用这个命令生成apkpatch -f new.apk -t old.apk -o outputs/ -k release.jks -p 111111 -a release -e 111111,此时会生成apatch


4.可以创建一个命令脚本:新建一个create_patch.sh 里面输入:sh apkpatch -f new.apk -t old.apk -o outputs/ -k release.jks -p 111111 -a release -e 111111

5.andfix使用 将.apatch下载下来并加载好

public class AndFixService extends Service {
private static final String TAG = AndFixService.class.getSimpleName();
private static final String FILE_END = ".apatch";
private static final int UPDATE_PATCH = 0x02;
private static final int DOWNLOAD_PATCH = 0x01;

private String mPatchFileDir;
private String mPatchFile;
private Handler mHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case UPDATE_PATCH:
                checkPatchUpdate();
                break;
            case DOWNLOAD_PATCH:
                downloadPatch();
                break;
        }
    }
};

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}


@Override
public void onCreate() {
    super.onCreate();
    init();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

// mHandler.sendEmptyMessage(UPDATEPATCH); mHandler.sendEmptyMessage(DOWNLOADPATCH); return STARTNOTSTICKY; }

//完成文件目录的构造
private void init() {

    mPatchFileDir = getExternalCacheDir().getAbsolutePath() + "/apatch/";
    File patchDir = new File(mPatchFileDir);

    try {
        if (patchDir == null || !patchDir.exists()) {
            patchDir.mkdir();
        }
    } catch (Exception e) {
        e.printStackTrace();
        stopSelf();
    }
}

private BasePatch mBasePatchInfo;

//检查服务器是否有patch文件
private void checkPatchUpdate() {
    RequestCenter.requestPatchUpdateInfo(new DisposeDataListener() {
        @Override
        public void onSuccess(Object responseObj) {
            mBasePatchInfo = (BasePatch) responseObj;
            if (!TextUtils.isEmpty(mBasePatchInfo.data.downloadUrl)) {
                //下载patch文件
                mHandler.sendEmptyMessage(DOWNLOAD_PATCH);
            } else {
                stopSelf();
            }
        }

        @Override
        public void onFailure(Object reasonObj) {
            stopSelf();
        }
    });
}

//完成patch文件的下载
private void downloadPatch() {
    //初始化patch文件下载路径
    mPatchFile = mPatchFileDir.concat(String.valueOf(System.currentTimeMillis())).
            concat(FILE_END);

    RequestCenter.downloadFile("http://www.ahhuabang.com/data/appfile/yijia.apatch", mPatchFile,
            new DisposeDownloadListener() {
                @Override
                public void onProgress(int progrss) {
                    Log.d(TAG, "current progedss: " + progrss);
                }

                @Override
                public void onSuccess(Object responseObj) {
                    //将我们下载好的patch文件添加到我们的andfix中
                    AndFixPathManager.getInstance().addPatch(mPatchFile);
                }

                @Override
                public void onFailure(Object reasonObj) {
                    stopSelf();
                }
            });
}
}

解释一下:RequestCenter.requestPatchUpdateInfo简单post请求,测试的时候可以忽略掉检查步骤,直接下载,封装方法代码太长了,后期会重新封装一个简单方法


主程序代码

public class MainActivity extends AppCompatActivity {
//后缀
private static final String FILE_END = ".apatch";
//下载文件的路径
private String mPatchDir;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 /*   mPatchDir = getExternalCacheDir().getAbsolutePath() + "/apatch/";
    File file = new File(mPatchDir);
    if (file == null || !file.exists()) {
        file.mkdir();
    }*/
    startPatchService();
}

private void startPatchService() {
    Intent intent=new Intent(this, AndFixService.class);
    startService(intent);
}

public void createBug(View view) {
    Utils.printLog();
    Toast.makeText(MainActivity.this,"点击了",Toast.LENGTH_LONG).show();
}

public void fixBug(View view) {
    AndFixPathManager.getInstance().addPatch(getPatchName());
}

private String getPatchName() {

    return mPatchDir.concat("yijia").concat(FILE_END);
}
}

http://www.niftyadmin.cn/n/3649023.html

相关文章

debian10 dns_如何在Debian 10上使用OctoDNS部署和管理DNS

debian10 dnsThe author selected the Electronic Frontier Foundation to receive a donation as part of the Write for DOnations program. 作者选择了电子前沿基金会来接受捐款&#xff0c;这是Write for DOnations计划的一部分。 介绍 (Introduction) OctoDNS is an infr…

《管理的实践》读书笔记(2)

彼得-德鲁克&#xff1a;“我也是第一位认清&#xff0c;或至少是首先指出&#xff0c;有效的管理必须通过目标管理与自我控制的人。”朝晖&#xff1a;“在软件的世界中&#xff0c;一个系统的实现是由多个子系统&#xff0c;到模块&#xff0c;到功能函数等不同的级别而组成的…

GradientDrawable代替Drawable 和 StateListDrawable代替selector工具类

工具类代码&#xff1a; public class DrawUtils {//GradientDrawable代替Drawablepublic static Drawable getDrawable(int rgb, float radius) {GradientDrawable gradientDrawable new GradientDrawable();//gradientDrawable.setColor(rgb);//设置填充颜色gradientDrawabl…

使用ngUpgrade将AngularJS服务迁移到Angular

In our last guide, we covered how to install everything we need to get started with upgrading from AngularJS to Angular. We also covered how to rewrite and downgrade components. 在上一指南中 &#xff0c;我们介绍了如何安装从AngularJS升级到Angular所需的一切。…

数据绑定技术DataBinding

数据绑定技术使用一 第一步添加配置 项目下的build.gradle下的android中defaultConfig下方添加代码: dataBinding{enabled true }第二步添加数据常量并设置set和get方法,因为偷懒就不写了 public class User { private String name; private String nickName; private Strin…

如何在Ubuntu 18.04上使用OpenLiteSpeed安装WordPress

介绍 (Introduction) WordPress is an open-source content management system (CMS). The most popular CMS in the world, WordPress allows you to set up blogs and websites on top of a MySQL database backend, using PHP to execute scripts and process dynamic conte…

纪念日:服务构件环境(SCE)挑起企业级架构的栋梁,下一代的应用开发模式日渐清晰

回忆几个镜头&#xff1a;在21世纪初的时候&#xff0c;有三家代表性的公司都在思考着简化Java那繁复的开发&#xff0c;去创造下一代更为简单高效的开发模式。回顾起来他们的发展轨迹各自不太相同。普元软件(Primeton)于2001年4月1日成立&#xff0c;志在探索下一代基于互联网…

Android 可拖拽的GridView效果实现, 长按可拖拽和item实时交换位置

在Android开发中&#xff0c;我们常常用到ListView和GridView&#xff0c;而有的时候系统的ListView&#xff0c;GridView并不能满足我们的需求&#xff0c;所以我们需要自己定义一个ListView或者GridView,我的上一篇文章中就是自定义的一个左右滑动删除item的例子&#xff0c;…