• 安卓热修复之AndFIX


    我致力于最新的前沿安卓技术分析和使用教学,不打算将很多很深的东西,因为有多少人愿意沉下你的心境去学习难点?我一般只会简单提及.文字错漏在所难免还希望同学们喜欢

    热修复介绍

    热修复是什么? 如果你一个项目已经上线,出现了严重缺陷,那么你第一反应是推送新版本.那么问题来.老子刚下你的APP 你就叫我重新下载?啥东西!卸了.从而导致用户流量的减退.而热修复就是推送一个补丁文件到客户端(很小),用户打开应用时自动安装.是不是很棒?

    AndFix 热修复原理

    已经翻译的源码分析

    阿里github官网(英文)

    推荐自行看官网
    如果时间上允许我会帮大家翻译完整版的

    AndFix注意的地方

    1. 不支持添加字段 方法 资源 布局修改 类
    2. 虽然不支持添加字段 但是你可以在方法内添加 局部变量(后面解释)

    错误:
    1. 如果添加了在生成补丁包会有如下错误(大家先看看不需要先知道怎么生成,后面阐述)
    这里写图片描述

    成功:
    仔细看 上面的文字会有什么add modifie(添加修改) com.xxx(你修改的文件)
    这里写图片描述

    AndFix使用

    1. 首先添加依赖

      dependencies {
              compile 'com.alipay.euler:andfix:0.5.0@aar'
      }
      
    2. 初始化 一般在application的实现类
      我们首先创建一个类继承之 application 然后在oncreat方法初始化,
      我先介绍几个API:

      此API返回你的应用版本名()
      java
      String appversion; appversion=getPackageManager().getPackageInfo(getPackageName(),0).ersionName;

      这里写图片描述

      再来看个依赖包的类PatchManager

       public PatchManager patchManager ;

      此类有如下几个方法

      参数为上下文 一般都在application中

      patchManager = new PatchManager(this);
          初始化 这里传入的是版本名 可以用上面介绍的一个api填入 也可以直接写死
      
       patchManager.init("1.0");
       patchManager.init(versionName);

      初始化加载补丁 (你直接当写死就行一般默认在new出来并初始版本后调用.这里还是不真正的加载方法)

        patchManager.loadPatch();

      打入补丁 参数为字符串 打入后生效 路径你随意写 文件名也是一样
      addPatch(你的补丁路径)
      //移除补丁路径
      patchManager.removeAllPatch();

      String path = Environment.getExternalStorageDirectory().getAbsoluteFile() + File.separator + "out.apatch";
      
              File file = new File(path);
              if (file.exists()){
                  Log.e("fmy","文件存在");
                  try {
                      patchManager.addPatch(path);
                      patchManager.removeAllPatch();
                      Log.e("fmy","热修复成功");
                  } catch (IOException e) {
                      Log.e("fmy","热修复失败:"+e.getMessage());
                  }
              }else{
                  Log.e("fmy","文件不存在");
              }

      完整代码:

      package com.example.administrator.myapplication;
      
      import android.app.Application;
      import android.os.Environment;
      import android.util.Log;
      
      import com.alipay.euler.andfix.patch.PatchManager;
      
      import java.io.File;
      import java.io.IOException;
      
      /**
       * Created by Administrator on 2016/11/9.
       */
      
      public class MainAppliacation extends Application {
      
      
          public PatchManager patchManager ;
          private String path;
      
          @Override
          public void onCreate() {
              super.onCreate();
      
              patchManager = new PatchManager(this);
              patchManager.init("1.0");
              patchManager.loadPatch();
      
              path = Environment.getExternalStorageDirectory().getAbsoluteFile() + File.separator + "out.apatch";
      
              File file = new File(path);
              if (file.exists()){
                  Log.e("fmy","文件存在");
                  try {
                      patchManager.addPatch(path);
                      patchManager.removeAllPatch();
                      Log.e("fmy","热修复成功");
                  } catch (IOException e) {
                      Log.e("fmy","热修复失败:"+e.getMessage());
                  }
              }else{
                  Log.e("fmy","文件不存在");
              }
      
      
          }
      }
      
    3. 添加权限和把我们自定义application关联上
      权限:

       <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
          <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

      //关联我们自定义application类

       <application
              android:name=".MainAppliacation"
              ....

      完整清单文件:

      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.administrator.myapplication">
      
          <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
          <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
      
          <application
              android:name=".MainAppliacation"
              android:allowBackup="true"
              android:icon="@mipmap/ic_launcher"
              android:label="@string/app_name"
              android:supportsRtl="true"
              android:theme="@style/AppTheme">
              <activity android:name=".MainActivity">
                  <intent-filter>
                      <action android:name="android.intent.action.MAIN" />
      
                      <category android:name="android.intent.category.LAUNCHER" />
                  </intent-filter>
              </activity>
          </application>
      
      </manifest>
    4. 生成新旧版本的两个已经签名的APK(签名需一样)
      假设我们原本的apk 两个类 一个是activity 类 和一个我们自定义的application类(上面已经说了)

      我们看看activity 文件

      package com.example.administrator.myapplication;
      
      import android.support.v7.app.AppCompatActivity;
      import android.os.Bundle;
      import android.view.View;
      import android.widget.Toast;
      
      public class MainActivity extends AppCompatActivity {
      
          String name ="你好";
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
          }
      
          //一个按钮的点击事件
          public void onClick(View view) {
      
              Toast.makeText(this, name, Toast.LENGTH_SHORT).show();
          }
      }

      看下布局文件吧

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout 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"
          android:paddingBottom="@dimen/activity_vertical_margin"
          android:paddingLeft="@dimen/activity_horizontal_margin"
          android:paddingRight="@dimen/activity_horizontal_margin"
          android:paddingTop="@dimen/activity_vertical_margin"
          tools:context="com.example.administrator.myapplication.MainActivity">
      
          <Button
              android:onClick="onClick"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="看看热修复是否成功" />
      </RelativeLayout>
      

      大概的效果图
      这里写图片描述
      打包签名此apk 并取名为old.apk(这里是为了后面好讲此命名)

      修改一下activity文件
      修改了name的数值

      package com.example.administrator.myapplication;
      
      import android.support.v7.app.AppCompatActivity;
      import android.os.Bundle;
      import android.view.View;
      import android.widget.Toast;
      
      public class MainActivity extends AppCompatActivity {
      
          String name ="修复了!!!!";
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
          }
      
          //一个按钮的点击事件
          public void onClick(View view) {
      
              Toast.makeText(this, name, Toast.LENGTH_SHORT).show();
          }
      
      
      }
      

      打包签名此apk 并取名为new.apk(这里是为了后面好讲此命名)

    5. 下载生成补丁工具
      阿里github官网(英文)

      在github下载源码不用我教吧?把阿里整个master下载到本地 并解压
      ![这里写图片描述](http://img.blog.csdn.net/20161109113056564)
      

      打开上述目录的tools目录 解压工具包到你喜欢的位置

      这里写图片描述

      现在我打开我解压的后的目录
      这里写图片描述

    6. 将我们生成的new.apk 和old.apk 还有签名文件一并放入此文件夹
      这里写图片描述

    7. 生成补丁
      在此目录下按下Shit键+鼠标右键 选择 可以看到一个选项为”在此处打开一个命令窗口” —>>不好截图 一点截图就关掉了所以 I’m so sorry

      在跳出命令窗口输入如下命令

      命令 : apkpatch.bat -f new.apk -t old.apk -o output1 -k debug.keystore -p android -a androiddebugkey -e android
      
      -f <new.apk> :新版本
      -t <old.apk> : 旧版本
      -o <output> : 输出目录
      -k <keystore>: 打包所用的keystore
      -p <password>: keystore的密码
      -a <alias>: keystore 用户别名
      -e <alias password>: keystore 用户别名密码

      提示在 dos 窗口按下tab 输入此文件夹下的某个文件名首字母或者一段可以提示哦
      这里写图片描述

    -o o 我这里的用法是 在此目录下创建一个o文件夹然后将生产的东西放入此文件夹

    我们打开看看我们的o文件夹有什么
    这里写图片描述

    可以看到有一个叫
    “new-4d459be7271c372742862b1a885b176a.apatch”的文件
    这个就是我们需要的 其他文件用处我以后会补充的 如加固的一些问题

    我们把此文件改名 “out.apatch”

    现在呢我们演示一下吧:
    首先安装old.apk 到手机中 我们运行看看
    这里写图片描述

    我们把文件out.apath导入到此模拟器的sd卡根目录 在关闭程序(记得清后台!!!!!) 不然你不会重新调用application的oncreat

    这里写图片描述

    What ?为什么没有变成我们后面改成的字符串?其实是我故意写下的一个坑 我的目的很简单 如果让同学一帆风顺的写下来你永远不会影响深刻对AndFIX哪些部分可以热修复 如前文 布局文件等

    这里之所以 不出来 是因为他把重新再name的类中赋值当成重新生成了一个字段(前面说过新字段不可以热修复),所以解锁方法如下

    package com.example.administrator.myapplication;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity {
    
        String name ="你好";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        //一个按钮的点击事件
        public void onClick(View view) {
            name ="修复了";
    
            Toast.makeText(this, name, Toast.LENGTH_SHORT).show();
        }
    
    
    }
    

    然后重新生成一个new.apk 在次和签名文件生成一个新的补丁效果就出来了.这里我就不重复无聊的步骤了,我现在导入正确的补丁
    这里写图片描述
    (^__^) 我很无聊吧?

    后期我还会教大家一个最新的热修复

    阿里百川计划 …

  • 相关阅读:
    JQuery onload、ready概念介绍及使用方法
    jquery获取第几个元素的方法总结
    CSS中隐藏内容的3种方法及属性值
    jQuery获取页面及个元素高度、宽度【转】
    数据仓库原理<2>:数据仓库系统的体系结构
    数据仓库原理<1>:数据库与数据仓库
    题注在论文图表编号中的使用
    初见Python<7>:Python操作mysql
    初见Python<5>:条件、循环和其他语句
    初见Python<4>:字典
  • 原文地址:https://www.cnblogs.com/muyuge/p/6152107.html
Copyright © 2020-2023  润新知