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);
}


}



转载于:https://www.cnblogs.com/xiaoxiaing/p/11598877.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
区块链技术可以为数字藏品发展提供许多潜在的好处,包括以下几点: 1. 去中心化的交易平台:区块链技术可以为数字藏品提供去中心化的交易平台,使得交易变得更加透明和公正。由于区块链的分布式账本特性,所有交易都将被记录在区块链上,使得交易信息难以被篡改或删除。这可以消除中介机构的作用,降低交易成本,并且加强数字藏品市场的安全性。 2. 身份验证和防伪:区块链技术还可以用于数字藏品的身份验证和防伪。每个数字藏品都可以被分配一个唯一的数字身份,该身份可以在区块链上进行验证,以确保其真实性和完整性。这种技术可以防止数字藏品的伪造或复制,并增加数字藏品的信任度。 3. 所有权证明:区块链技术还可以用于数字藏品的所有权证明。数字藏品可以被分配到一个区块链地址上,使得其所有权可以被记录在区块链上。这可以减少拥有者之间的争议,并增加数字藏品的流通性。 4. 智能合约:区块链技术还可以支持智能合约,这是一种自动执行合约的技术。智能合约可以与数字藏品绑定在一起,并在特定的条件下自动执行。例如,当数字藏品被出售时,智能合约可以自动转移所有权并将交易款项支付给卖方。 总的来说,区块链技术可以为数字藏品市场带来更大的透明度、可信度和安全性,并且可以减少交易成本、增加流动性。因此,随着区块链技术的不断发展,数字藏品市场的前景也会变得更加光明。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值