zoukankan      html  css  js  c++  java
  • Android为TV端助力之QQ空间热更新技术

    直接上代码

     

     

     

    package com.enjoy.patch;

    import android.content.Context;
    import android.os.Build;
    import android.util.Log;

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;


    public class EnjoyFix {

    private static final String TAG = "EnjoyFix";

    private static File initHack(Context context) {

    File hackDir = context.getDir("hack", Context.MODE_PRIVATE);
    File hackFile = new File(hackDir, "hack.jar");
    if (!hackFile.exists()) {
    BufferedInputStream is = null;
    BufferedOutputStream os = null;
    try {
    is = new BufferedInputStream(context.getAssets().open("hack" +
    ".jar"));
    os = new BufferedOutputStream(new FileOutputStream(hackFile));
    byte[] buffer = new byte[4096];
    int len;
    while ((len = is.read(buffer)) != -1) {
    os.write(buffer, 0, len);
    }
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (is != null){
    try {
    is.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if (os != null){
    try {
    os.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    return hackFile;

    }

    public static void installPatch(Context context, File patch) {
    File hackFile = initHack(context);
    ClassLoader classLoader = context.getClassLoader();
    List<File> files = new ArrayList<>();
    if (patch.exists()) {
    files.add(patch);
    }
    files.add(hackFile);
    File dexOptDir = context.getCacheDir();
    try {
    Log.i("TAG","Build.VERSION.SDK_INT"+Build.VERSION.SDK_INT);
    //23 6.0及以上
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    V23.install(classLoader, files, dexOptDir);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    V19.install(classLoader, files, dexOptDir); //4.4以上
    } else { // >= 14
    V14.install(classLoader, files, dexOptDir);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }


    private static final class V23 {

    private static void install(ClassLoader loader, List<File> additionalClassPathEntries,
    File optimizedDirectory)
    throws IllegalArgumentException, IllegalAccessException,
    NoSuchFieldException, InvocationTargetException, NoSuchMethodException,
    IOException {
    //找到 pathList
    Field pathListField = SharedReflectUtils.findField(loader, "pathList");
    Object dexPathList = pathListField.get(loader);

    ArrayList<IOException> suppressedExceptions = new ArrayList<>();
    // 从 pathList找到 makePathElements 方法并执行
    // 得到补丁创建的 Element[]
    Object[] objects = makePathElements(dexPathList,
    new ArrayList<>(additionalClassPathEntries), optimizedDirectory,
    suppressedExceptions);

    //将原本的 dexElements 与 makePathElements生成的数组合并
    SharedReflectUtils.expandFieldArray(dexPathList, "dexElements", objects);
    if (suppressedExceptions.size() > 0) {
    for (IOException e : suppressedExceptions) {
    Log.w(TAG, "Exception in makePathElement", e);
    throw e;
    }

    }
    }

    /**
    * 把dex转化为Element数组
    */
    private static Object[] makePathElements(
    Object dexPathList, ArrayList<File> files, File optimizedDirectory,
    ArrayList<IOException> suppressedExceptions)
    throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    //通过阅读android6、7、8、9源码,都存在makePathElements方法
    Method makePathElements = SharedReflectUtils.findMethod(dexPathList, "makePathElements",
    List.class, File.class,
    List.class);
    return (Object[]) makePathElements.invoke(dexPathList, files, optimizedDirectory,
    suppressedExceptions);
    }
    }

    private static final class V19 {

    private static void install(ClassLoader loader, List<File> additionalClassPathEntries,
    File optimizedDirectory)
    throws IllegalArgumentException, IllegalAccessException,
    NoSuchFieldException, InvocationTargetException, NoSuchMethodException,
    IOException {
    Field pathListField = SharedReflectUtils.findField(loader, "pathList");
    Object dexPathList = pathListField.get(loader);
    ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
    SharedReflectUtils.expandFieldArray(dexPathList, "dexElements",
    makeDexElements(dexPathList,
    new ArrayList<File>(additionalClassPathEntries), optimizedDirectory,
    suppressedExceptions));
    if (suppressedExceptions.size() > 0) {
    for (IOException e : suppressedExceptions) {
    Log.w(TAG, "Exception in makeDexElement", e);
    throw e;
    }
    }
    }

    private static Object[] makeDexElements(
    Object dexPathList, ArrayList<File> files, File optimizedDirectory,
    ArrayList<IOException> suppressedExceptions)
    throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    Method makeDexElements = SharedReflectUtils.findMethod(dexPathList, "makeDexElements",
    ArrayList.class, File.class,
    ArrayList.class);


    return (Object[]) makeDexElements.invoke(dexPathList, files, optimizedDirectory,
    suppressedExceptions);
    }
    }

    /**
    * 14, 15, 16, 17, 18.
    */
    private static final class V14 {


    private static void install(ClassLoader loader, List<File> additionalClassPathEntries,
    File optimizedDirectory)
    throws IllegalArgumentException, IllegalAccessException,
    NoSuchFieldException, InvocationTargetException, NoSuchMethodException {

    Field pathListField = SharedReflectUtils.findField(loader, "pathList");
    Object dexPathList = pathListField.get(loader);

    SharedReflectUtils.expandFieldArray(dexPathList, "dexElements",
    makeDexElements(dexPathList,
    new ArrayList<File>(additionalClassPathEntries), optimizedDirectory));
    }

    private static Object[] makeDexElements(
    Object dexPathList, ArrayList<File> files, File optimizedDirectory)
    throws IllegalAccessException, InvocationTargetException,
    NoSuchMethodException {
    Method makeDexElements =
    SharedReflectUtils.findMethod(dexPathList, "makeDexElements", ArrayList.class,
    File.class);
    return (Object[]) makeDexElements.invoke(dexPathList, files, optimizedDirectory);
    }
    }

    }
    ---------------------------------------------------------------------------------------------------------------------------------
    package com.enjoy.patch;

    import java.lang.reflect.Array;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.Arrays;

    /**
    * 反射工具类
    */
    public class SharedReflectUtils {


    /**
    * 从 instance 到其父类 找 name 属性
    *
    * @param instance
    * @param name
    * @return
    * @throws NoSuchFieldException
    */
    public static Field findField(Object instance, String name) throws NoSuchFieldException {
    for (Class<?> clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
    try {
    //查找当前类的 属性(不包括父类)
    Field field = clazz.getDeclaredField(name);

    if (!field.isAccessible()) {
    field.setAccessible(true);
    }
    return field;
    } catch (NoSuchFieldException e) {
    // ignore and search next
    }
    }
    throw new NoSuchFieldException("Field " + name + " not found in " + instance.getClass());
    }

    /**
    * 从 instance 到其父类 找 name 方法
    *
    * @param instance
    * @param name
    * @return
    * @throws NoSuchFieldException
    */
    public static Method findMethod(Object instance, String name, Class<?>... parameterTypes)
    throws NoSuchMethodException {
    for (Class<?> clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
    try {
    Method method = clazz.getDeclaredMethod(name, parameterTypes);

    if (!method.isAccessible()) {
    method.setAccessible(true);
    }

    return method;
    } catch (NoSuchMethodException e) {
    // ignore and search next
    }
    }
    throw new NoSuchMethodException("Method "
    + name
    + " with parameters "
    + Arrays.asList(parameterTypes)
    + " not found in " + instance.getClass());
    }


    /**
    * @param instance
    * @param fieldName
    * @param fixs 补丁的Element数组
    * @throws NoSuchFieldException
    * @throws IllegalArgumentException
    * @throws IllegalAccessException
    */
    public static void expandFieldArray(Object instance, String fieldName, Object[] fixs)
    throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    //拿到 classloader中的dexelements 数组
    Field jlrField = findField(instance, fieldName);
    //old Element[]
    Object[] old = (Object[]) jlrField.get(instance);


    //合并后的数组
    Object[] newElements = (Object[]) Array.newInstance(old.getClass().getComponentType(),
    old.length + fixs.length);

    // 先拷贝新数组
    System.arraycopy(fixs, 0, newElements, 0, fixs.length);
    System.arraycopy(old, 0, newElements, fixs.length, old.length);

    //修改 classLoader中 pathList的 dexelements
    jlrField.set(instance, newElements);
    }


    }



  • 相关阅读:
    DOM——《JavaScript高级程序设计》笔记
    (转)用js无法获取style样式的问题解析与解决方法
    【2】可视化格式模型、背景、链接、表格表单——《精通CSS‘》
    安装sql server 2008 R2,提示错误:此计算机上安装了 Microsoft Visual Studio 2008 的早期版本。请在安装 SQL Server 2008 前将 Microsoft Visual Studio 2008 升级到 SP1。
    C#读取Word表格中的数据 (转)
    C#在Word文档指定位置处理表格
    c#操作word书签
    c# 操作word的
    函数参数压栈顺序2
    可变长参数
  • 原文地址:https://www.cnblogs.com/xiaoxiaing/p/11598877.html
Copyright © 2011-2022 走看看