feat:框架测试正常

This commit is contained in:
lateautumn4lin 2020-09-13 02:13:02 +08:00
parent e46e6bacf8
commit 17304cf0f0
27 changed files with 663 additions and 191 deletions

View File

@ -20,36 +20,52 @@
> 公共类
- commons
> 统一日志类
- Logger
> 入口类
- entry
> Hook第一层入口包括免重启等功能
- BaseEntry
> Hook逻辑入口由第一层入口加载包含具体的Hook逻辑
- RealEntry
> 事件处理类
- handlers
> 基础处理类
- BaseHandler
> 测试类
- KuaishouHandler
> 初始化管理类
- initialization
> 基础初始化类
- BaseInit
> 注册类管理与Sekiro服务端通信
- Register
> 工具类
- utils
> 类查询助手
- ClassesReaderAssistant
> 通信助手
- CommunicationAssistant
> 算法助手
- AlgorithmAssistant
> 配置文件助手
- PropertiesAssistant
- Config
## Install

View File

@ -1 +0,0 @@
Headwolf

View File

@ -1,116 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -11,6 +11,7 @@
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/mmkv-static-1.1.2" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@ -20,15 +20,26 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/INDEX.LIST'
exclude 'META-INF/io.netty.versions.properties'
}
}
repositories {
jcenter()
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.virjar:sekiro-api:1.0.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.12'
implementation project(':mmkv-static-1.1.2')
compileOnly 'de.robv.android.xposed:api:82'
compileOnly 'de.robv.android.xposed:api:82:sources'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

View File

@ -3,6 +3,7 @@
package="com.lateautumn4lin.headwolf">
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@ -16,6 +17,20 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 是否是xposed模块xposed根据这个来判断是否是模块 -->
<meta-data
android:name="xposedmodule"
android:value="true" />
<!-- 模块描述显示在xposed模块列表那里第二行 -->
<meta-data
android:name="xposeddescription"
android:value="基于Xposed和Sekiro搭建的敏捷开发的脚手架" />
<!-- 最低xposed版本号(lib文件名可知) -->
<meta-data
android:name="xposedminversion"
android:value="30" />
</application>
</manifest>

View File

@ -1,6 +1,4 @@
remote_server=192.144.152.23
wechat_remote_server=182.92.212.44
group_kuaishou_name=ks_group2
group_taobao_name=tb_group2
group_douyin_name=dy_group2
group_wechat_name=wc_group2
package_name=com.lateautumn4lin.headwolf
package_kuaishou=com.smile.gifmaker
package_pdd=com.xunmeng.pinduoduo

View File

@ -1 +1 @@
com.lateautumn4lin.sign.entry.HookLoader
com.lateautumn4lin.headwolf.entry.BaseEntry

View File

@ -7,5 +7,137 @@ package com.lateautumn4lin.headwolf;
* @date 2020/9/10 13:40
*/
import com.lateautumn4lin.headwolf.commons.Logger;
import com.lateautumn4lin.headwolf.handlers.KuaishouHandler;
import com.lateautumn4lin.headwolf.utils.PropertiesAssistant;
import com.virjar.sekiro.api.SekiroRequestHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import static java.util.Arrays.asList;
/**
* The type Config.
*/
public class Config {
private static Properties propertiesAssistant = PropertiesAssistant.getProperties();
private static List<SekiroRequestHandler> handlers = asList(
(SekiroRequestHandler) new KuaishouHandler()
);
private static HashMap<String, SekiroRequestHandler> handlers_map = GenerateHandlersMap();
private static HashMap<String, SekiroRequestHandler> GenerateHandlersMap() {
HashMap<String, SekiroRequestHandler> map = new HashMap<String, SekiroRequestHandler>();
for (SekiroRequestHandler obj : handlers) {
map.put(obj.getClass().getName(), obj);
}
return map;
}
private static String client_id = null;
/**
* The Groups.
*/
static private HashMap<String, String> groups = GetAllPackageGroups();
/**
* Get package name string.
*
* @return the string
*/
public static String GetPackageName() {
Properties propertiesAssistant = PropertiesAssistant.getProperties();
return propertiesAssistant.getProperty("package_name");
}
/**
* Gets remote server.
*
* @return the remote server
*/
public static String getRemoteServer() {
return propertiesAssistant.getProperty("remote_server");
}
/**
* Gets client id.
*
* @return the client id
*/
public static String getClientId() {
if (client_id == null) {
String s = UUID.randomUUID().toString();
Config.client_id = s.substring(0, 8) + s.substring(9, 13) + s.substring(14, 18) + s.substring(19, 23) + s.substring(24);
}
return client_id;
}
/**
* Get all package hash map.
*
* @return the hash map
*/
public static HashMap<String, String> GetAllPackageGroups() {
Properties propertiesAssistant = PropertiesAssistant.getProperties();
HashMap<String, String> all_package_groups = new HashMap<String, String>();
try {
for (String name : propertiesAssistant.stringPropertyNames()) {
if (name.contains("package_") ^ name.contains("name")) {
all_package_groups.put(propertiesAssistant.getProperty(name), name);
}
}
} catch (Exception e) {
Logger.loge(e.toString());
}
return all_package_groups;
}
/**
* Gets group.
*
* @param type_name the type name
* @return the group
*/
public static String GetGroup(String type_name) {
return groups.get(type_name);
}
/**
* Get hook packages string.
*
* @return the string
*/
public static List<String> GetHookPackages() {
Properties propertiesAssistant = PropertiesAssistant.getProperties();
List<String> inner_hook_packages = new ArrayList<String>();
try {
for (String name : propertiesAssistant.stringPropertyNames()) {
if (name.contains("package_") ^ name.contains("name")) {
inner_hook_packages.add(propertiesAssistant.getProperty(name));
}
}
} catch (Exception e) {
Logger.loge(e.toString());
}
return inner_hook_packages;
}
/**
* Get hanler instance list.
*
* @param class_name the class name
* @return the list
*/
public static SekiroRequestHandler GetHanlerInstance(String class_name) {
return handlers_map.get(class_name);
}
}

View File

@ -4,11 +4,29 @@ import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.lateautumn4lin.headwolf.commons.Logger;
import com.tencent.mmkv.MMKV;
/**
* The type Main activity.
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Logger.logi("StartUp MainActivity");
// try {
// String rootDir = MMKV.initialize("/data/user/0/com.lateautumn4lin.headwolf/files/mmkv");
// MMKV kv = MMKV.mmkvWithID("test", MMKV.MULTI_PROCESS_MODE);
// Logger.logi("mmkv root: " + rootDir);
// kv.encode("string", "Hello from mmkv");
// String str = kv.decodeString("string");
// Logger.logi("Get MMKV:" + str);
// } catch (Exception e) {
// Logger.loge(e.toString());
// }
}
}

View File

@ -0,0 +1,29 @@
package com.lateautumn4lin.headwolf;
/*
* MyApplication
*
* @author lateautumn4lin
* @github https://github.com/lateautumn4lin
* @date 2020/9/12 3:12
*/
import android.app.Application;
import android.content.Context;
import com.lateautumn4lin.headwolf.commons.Logger;
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
Logger.logi(String.format("StartUp MyApplication And Get Context %s", context));
}
public static Context getContext() {
return context;
}
}

View File

@ -7,5 +7,64 @@ package com.lateautumn4lin.headwolf.commons;
* @date 2020/9/10 13:54
*/
import android.util.Log;
/**
* The type Logger.
*/
public class Logger {
private Logger() {
}
/**
* The constant TAG.
*/
public static final String TAG = "headwolf";
/**
* Logi.
*
* @param msg the msg
*/
public static void logi(String msg) {
Log.i(TAG, msg);
}
/**
* Loge.
*
* @param msg the msg
*/
public static void loge(String msg) {
Log.e(TAG, msg);
}
/**
* Logw.
*
* @param msg the msg
*/
public static void logw(String msg) {
Log.w(TAG, msg);
}
/**
* Logd.
*
* @param msg the msg
*/
public static void logd(String msg) {
Log.d(TAG, msg);
}
/**
* Logv.
*
* @param msg the msg
*/
public static void logv(String msg) {
Log.v(TAG, msg);
}
}

View File

@ -7,5 +7,111 @@ package com.lateautumn4lin.headwolf.entry;
* @date 2020/9/10 13:45
*/
public class BaseEntry {
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import com.lateautumn4lin.headwolf.Config;
import com.lateautumn4lin.headwolf.commons.Logger;
import java.io.File;
import java.lang.reflect.Method;
import java.util.List;
import dalvik.system.PathClassLoader;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
* The type Base entry. 第一层Hook入口
*/
public class BaseEntry implements IXposedHookLoadPackage {
private String modulePackage = null;
private static List<String> hookPackages = null;
private final String handleHookClass = RealEntry.class.getName();
private final String handleHookMethod = "handleLoadPackage";
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
try {
// 延迟初始化静态变量
if (modulePackage == null) {
modulePackage = Config.GetPackageName();
}
if (hookPackages == null) {
hookPackages = Config.GetHookPackages();
}
// 包含配置文件中配置的包名则进入真正Hook逻辑
if (hookPackages.contains(loadPackageParam.packageName)) {
try {
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
Logger.logi(String.format("Get Needed Hook Package:%s", loadPackageParam.packageName));
Context context = (Context) param.args[0];
loadPackageParam.classLoader = context.getClassLoader();
invokeHandleHookMethod(context, modulePackage, handleHookClass, handleHookMethod, loadPackageParam);
}
});
} catch (Exception e) {
Logger.loge(String.format("Invoke Hook Method Error, Package:%s", loadPackageParam.packageName));
}
}
} catch (Exception e) {
Logger.loge(e.toString());
}
}
/**
* Invoke handle hook method.
*
* @param context the context
* @param modulePackageName the module package name
* @param handleHookClass the handle hook class
* @param handleHookMethod the handle hook method
* @param loadPackageParam the load package param
* @throws Throwable the throwable
*/
private void invokeHandleHookMethod(Context context, String modulePackageName, String handleHookClass, String handleHookMethod, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
try {
File apkFile = findApkFile(context, modulePackageName);
if (apkFile == null) {
throw new RuntimeException("Find Apk File Error");
}
Logger.logi(String.format("Get Apk File:%s", apkFile.toString()));
PathClassLoader pathClassLoader = new PathClassLoader(apkFile.getAbsolutePath(), XposedBridge.BOOTCLASSLOADER);
Class<?> cls = Class.forName(handleHookClass, true, pathClassLoader);
Logger.logi(String.format("Get ClassLoader:%s", apkFile.toString()));
Object instance = cls.newInstance();
Method method = cls.getDeclaredMethod(handleHookMethod, XC_LoadPackage.LoadPackageParam.class);
Logger.logi(String.format("Get Needed Hook Method:%s", apkFile.toString()));
method.invoke(instance, loadPackageParam);
} catch (Exception e) {
Logger.loge(e.toString());
}
}
/**
* Find apk file file. 获取需要Hook Apk文件地址
*
* @param context the context
* @param modulePackageName the module package name
* @return the file
*/
private File findApkFile(Context context, String modulePackageName) {
if (context == null) {
throw new RuntimeException("Can't Get Context");
}
try {
Context moudleContext = context.createPackageContext(modulePackageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
String apkPath = moudleContext.getPackageCodePath();
return new File(apkPath);
} catch (PackageManager.NameNotFoundException e) {
Logger.loge(String.format("Find File ErrorPackage:%s", modulePackageName));
return null;
}
}
}

View File

@ -7,5 +7,45 @@ package com.lateautumn4lin.headwolf.entry;
* @date 2020/9/10 13:45
*/
public class RealEntry {
import android.content.Context;
import com.lateautumn4lin.headwolf.commons.Logger;
import com.lateautumn4lin.headwolf.initialization.Register;
import com.lateautumn4lin.headwolf.utils.ClassesReaderAssistant;
import com.virjar.sekiro.api.SekiroRequestHandler;
import java.util.HashMap;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
* The type Real entry.
*/
public class RealEntry implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
try {
Logger.logi(String.format("Begin Real Hook Logic About:%s", loadPackageParam.packageName));
// step1:获取context
Context context = (Context) XposedHelpers.callMethod(
XposedHelpers.callStaticMethod(
XposedHelpers.findClass(
"android.app.ActivityThread",
loadPackageParam.classLoader
),
"currentActivityThread"
),
"getSystemContext"
);
// step2:获取包名对应的需要注册的handler以及home_class
Class HomeClass = loadPackageParam.classLoader.loadClass("com.yxcorp.gifshow.HomeActivity");
HashMap<String, SekiroRequestHandler> associate_handlers = ClassesReaderAssistant.reader(context, loadPackageParam.packageName);
// step3:由注册类进行handler注册
Register.GroupRegister(loadPackageParam, HomeClass, associate_handlers);
} catch (Exception e) {
Logger.loge(e.toString());
}
}
}

View File

@ -7,5 +7,24 @@ package com.lateautumn4lin.headwolf.handlers;
* @date 2020/9/10 13:44
*/
public class BaseHandler {
/**
* The type Base handler.
*/
public abstract class BaseHandler {
/**
* Gets belong.
*
* @return the belong
*/
public abstract String getBelong();
/**
* Gets action.
*
* @return the action
*/
public abstract String getAction();
}

View File

@ -7,5 +7,43 @@ package com.lateautumn4lin.headwolf.handlers;
* @date 2020/9/10 15:39
*/
public class KuaishouHandler {
import com.google.gson.Gson;
import com.virjar.sekiro.api.SekiroRequest;
import com.virjar.sekiro.api.SekiroRequestHandler;
import com.virjar.sekiro.api.SekiroResponse;
import java.util.HashMap;
import java.util.Map;
/**
* The type Kuaishou handler.
*/
public class KuaishouHandler implements SekiroRequestHandler {
/**
* Gets belong.
*
* @return the belong
*/
public String getBelong() {
return "com.smile.gifmaker";
}
/**
* Gets action.
*
* @return the action
*/
public String getAction() {
return "sign";
}
@Override
public void handleRequest(SekiroRequest sekiroRequest, SekiroResponse sekiroResponse) {
Gson gson = new Gson();
Map<String, String> object = new HashMap<String, String>();
String name = sekiroRequest.getString("name");
object.put("name", name);
sekiroResponse.send(gson.toJson(object));
}
}

View File

@ -7,5 +7,8 @@ package com.lateautumn4lin.headwolf.initialization;
* @date 2020/9/10 13:49
*/
/**
* The type Base init.
*/
public class BaseInit {
}

View File

@ -7,5 +7,65 @@ package com.lateautumn4lin.headwolf.initialization;
* @date 2020/9/10 13:49
*/
import android.os.Bundle;
import com.lateautumn4lin.headwolf.Config;
import com.lateautumn4lin.headwolf.commons.Logger;
import com.virjar.sekiro.api.SekiroClient;
import com.virjar.sekiro.api.SekiroRequestHandler;
import java.util.HashMap;
import java.util.Map;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
* The type Register.
*/
public class Register {
/**
* Base register boolean.
*
* @param loadPackageParam the load package param
* @param home_class the home class
* @param associate_handlers the associate handlers
* @return the boolean
*/
public static Boolean GroupRegister(final XC_LoadPackage.LoadPackageParam loadPackageParam, Class home_class, final HashMap<String, SekiroRequestHandler> associate_handlers) {
final String group_name = Config.GetGroup(loadPackageParam.packageName);
try {
XposedHelpers.findAndHookMethod(home_class, "onCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Logger.logi(String.format("Group Register:%s Begin ClientId:%s", group_name, Config.getClientId()));
final SekiroClient sekiroClient = SekiroClient.start(
Config.getRemoteServer(),
Config.getClientId(),
group_name
);
try {
for (Map.Entry<String, SekiroRequestHandler> entry : associate_handlers.entrySet()) {
try {
SekiroRequestHandler handler = entry.getValue();
sekiroClient.registerHandler(entry.getKey(), handler);
Logger.logi(String.format("Group Register Group:%s Action:%s Handler:%s Success ClientId:%s", group_name, entry.getKey(), handler, Config.getClientId()));
} catch (Exception e) {
Logger.loge(e.toString());
}
}
} catch (Exception e) {
Logger.loge(e.toString());
}
super.afterHookedMethod(param);
}
});
} catch (Exception e) {
Logger.loge(String.format("Group Register Error ClientId:%s", Config.getClientId()));
return false;
}
return true;
}
}

View File

@ -11,38 +11,38 @@ package com.lateautumn4lin.headwolf.utils;
import android.content.Context;
import com.lateautumn4lin.headwolf.Config;
import com.lateautumn4lin.headwolf.commons.Logger;
import com.virjar.sekiro.api.SekiroRequestHandler;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
import de.robv.android.xposed.XposedBridge;
/**
* 类读取器<br/>
* 读取某个包下所有类<br/>
* The type Classes reader assistant.
*/
public final class ClassesReaderAssistant {
/**
* 获取应用程序下的所有Dex文件
*
* @param context 上下文
* @return Set<DexFile> set
*/
public static Set<DexFile> applicationDexFile(Context context) {
return applicationDexFile(context.getPackageCodePath());
}
/**
* 获取应用程序下的所有Dex文件
* Application dex file set.
*
* @param packageCodePath 包路径
* @return Set<DexFile> set
* @param packageCodePath the package code path
* @return the set
*/
public static Set<DexFile> applicationDexFile(String packageCodePath) {
Set<DexFile> dexFiles = new HashSet<>();
@ -64,11 +64,12 @@ public final class ClassesReaderAssistant {
return dexFiles;
}
/**
* 创建DexFile文件
* Create dex file dex file.
*
* @param path 路径
* @return DexFile dex file
* @param path the path
* @return the dex file
*/
public static DexFile createDexFile(String path) {
try {
@ -78,42 +79,78 @@ public final class ClassesReaderAssistant {
}
}
/**
* 读取类路径下的所有类
*
* @param packageName 包名
* @param context 包路径
* @return List<Class> list
*/
public static List<Class<?>> reader(String packageName, Context context) {
return reader(packageName, context.getPackageCodePath());
}
/**
* 读取类路径下的所有类
* Reader hash map.
*
* @param packageName 包名
* @param packageCodePath 上下文
* @return List<Class> list
* @param context the context
* @param associateName the associate name
* @return the hash map
*/
public static HashMap<String, SekiroRequestHandler> reader(Context context, String associateName) {
String packageName = String.format("%s.handlers", Config.GetPackageName());
HashMap<String, SekiroRequestHandler> associate_handlers = new HashMap<String, SekiroRequestHandler>();
try {
Context moudleContext = context.createPackageContext(Config.GetPackageName(), Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
List<Class<?>> associate_classes = reader(packageName, moudleContext.getPackageCodePath());
for (Class<?> cls : associate_classes)
try {
Logger.logi(String.format("%s,get", cls.getName()));
if (cls.getName().equals(String.format("%s.BaseHandler", packageName))) {
continue;
}
Constructor constructor = cls.getConstructor();
Object instance = constructor.newInstance();
Method getBelong = cls.getDeclaredMethod("getBelong");
Object belong_name = getBelong.invoke(instance);
Logger.logi(String.format("%s Compare %s", belong_name, associateName));
if (((String) belong_name).equals(associateName)) {
Method getAction = cls.getDeclaredMethod("getAction");
Object action = getAction.invoke(instance);
associate_handlers.put((String) action, Config.GetHanlerInstance(cls.getName()));
}
} catch (NoSuchMethodException e) {
Logger.loge(String.format("Can't Find Method:getBelong For %s", packageName));
} catch (Exception e) {
Logger.loge(e.toString());
}
} catch (Exception e) {
Logger.loge(e.toString());
}
return associate_handlers;
}
/**
* Reader list.
*
* @param packageName the package name
* @param packageCodePath the package code path
* @return the list
*/
public static List<Class<?>> reader(String packageName, String packageCodePath) {
List<Class<?>> classes = new ArrayList<>();
Set<DexFile> dexFiles = applicationDexFile(packageCodePath);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
for (DexFile dexFile : dexFiles) {
if (dexFile == null) continue;
Enumeration<String> entries = dexFile.entries();
while (entries.hasMoreElements()) {
try {
String currentClassPath = entries.nextElement();
if (currentClassPath == null || currentClassPath.isEmpty() || currentClassPath.indexOf(packageName) != 0)
continue;
Class<?> entryClass = Class.forName(currentClassPath, true, classLoader);
if (entryClass == null) continue;
classes.add(entryClass);
} catch (Exception e) {
e.printStackTrace();
Logger.logi(dexFile.toString());
try {
PathClassLoader pathClassLoader = new PathClassLoader(new File(packageCodePath).getAbsolutePath(), XposedBridge.BOOTCLASSLOADER);
if (dexFile == null) continue;
Enumeration<String> entries = dexFile.entries();
while (entries.hasMoreElements()) {
try {
String currentClassPath = entries.nextElement();
if (currentClassPath == null || currentClassPath.isEmpty() || currentClassPath.indexOf(packageName) != 0)
continue;
Class<?> entryClass = Class.forName(currentClassPath, true, pathClassLoader);
if (entryClass == null) continue;
classes.add(entryClass);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
Logger.loge(e.toString());
}
}
return classes;

View File

@ -7,5 +7,8 @@ package com.lateautumn4lin.headwolf.utils;
* @date 2020/9/10 13:54
*/
/**
* The type Communication assistant.
*/
public class CommunicationAssistant {
}

View File

@ -1,13 +1,23 @@
package com.lateautumn4lin.headwolf.utils;
import com.lateautumn4lin.headwolf.commons.Logger;
import java.io.InputStream;
import java.util.Properties;
public class ProperTies {
/**
* The type Properties assistant.
*/
public class PropertiesAssistant {
/**
* Gets properties.
*
* @return the properties
*/
public static Properties getProperties() {
Properties props = new Properties();
InputStream in = ProperTies.class.getResourceAsStream("/assets/config");
try {
InputStream in = PropertiesAssistant.class.getResourceAsStream("/assets/config");
props.load(in);
} catch (Exception e) {
Logger.loge(e.toString());

View File

@ -9,7 +9,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:text="来Github提Issue、提Pr"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

View File

@ -1,3 +1,3 @@
<resources>
<string name="app_name">Headwolf</string>
<string name="app_name">Headwolf框架</string>
</resources>

View File

@ -3,9 +3,10 @@
buildscript {
repositories {
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
@ -20,6 +21,9 @@ allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
}
}

View File

@ -0,0 +1,2 @@
configurations.maybeCreate("default")
artifacts.add("default", file('mmkv-static-1.1.2.aar'))

View File

@ -1,2 +1,2 @@
rootProject.name='Headwolf'
include ':app'
include ':app', ':mmkv-static-1.1.2'