feat:框架测试正常
This commit is contained in:
parent
e46e6bacf8
commit
17304cf0f0
16
README.md
16
README.md
@ -20,36 +20,52 @@
|
|||||||
|
|
||||||
> 公共类
|
> 公共类
|
||||||
- commons
|
- commons
|
||||||
|
|
||||||
> 统一日志类
|
> 统一日志类
|
||||||
- Logger
|
- Logger
|
||||||
|
|
||||||
> 入口类
|
> 入口类
|
||||||
- entry
|
- entry
|
||||||
|
|
||||||
> Hook第一层入口(包括免重启等功能)
|
> Hook第一层入口(包括免重启等功能)
|
||||||
- BaseEntry
|
- BaseEntry
|
||||||
|
|
||||||
> Hook逻辑入口,由第一层入口加载,包含具体的Hook逻辑
|
> Hook逻辑入口,由第一层入口加载,包含具体的Hook逻辑
|
||||||
- RealEntry
|
- RealEntry
|
||||||
|
|
||||||
> 事件处理类
|
> 事件处理类
|
||||||
- handlers
|
- handlers
|
||||||
|
|
||||||
> 基础处理类
|
> 基础处理类
|
||||||
- BaseHandler
|
- BaseHandler
|
||||||
|
|
||||||
> 测试类
|
> 测试类
|
||||||
- KuaishouHandler
|
- KuaishouHandler
|
||||||
|
|
||||||
> 初始化管理类
|
> 初始化管理类
|
||||||
- initialization
|
- initialization
|
||||||
|
|
||||||
> 基础初始化类
|
> 基础初始化类
|
||||||
- BaseInit
|
- BaseInit
|
||||||
|
|
||||||
> 注册类,管理与Sekiro服务端通信
|
> 注册类,管理与Sekiro服务端通信
|
||||||
- Register
|
- Register
|
||||||
|
|
||||||
> 工具类
|
> 工具类
|
||||||
- utils
|
- utils
|
||||||
|
|
||||||
> 类查询助手
|
> 类查询助手
|
||||||
- ClassesReaderAssistant
|
- ClassesReaderAssistant
|
||||||
|
|
||||||
> 通信助手
|
> 通信助手
|
||||||
- CommunicationAssistant
|
- CommunicationAssistant
|
||||||
|
|
||||||
> 算法助手
|
> 算法助手
|
||||||
- AlgorithmAssistant
|
- AlgorithmAssistant
|
||||||
|
|
||||||
> 配置文件助手
|
> 配置文件助手
|
||||||
- PropertiesAssistant
|
- PropertiesAssistant
|
||||||
|
|
||||||
- Config
|
- Config
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
Headwolf
|
|
||||||
@ -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>
|
|
||||||
@ -11,6 +11,7 @@
|
|||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
|
<option value="$PROJECT_DIR$/mmkv-static-1.1.2" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
|||||||
@ -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>
|
|
||||||
@ -20,15 +20,26 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
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 {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
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.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
testImplementation 'junit:junit:4.12'
|
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.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
package="com.lateautumn4lin.headwolf">
|
package="com.lateautumn4lin.headwolf">
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".MyApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
@ -16,6 +17,20 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</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>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@ -1,6 +1,4 @@
|
|||||||
remote_server=192.144.152.23
|
remote_server=192.144.152.23
|
||||||
wechat_remote_server=182.92.212.44
|
package_name=com.lateautumn4lin.headwolf
|
||||||
group_kuaishou_name=ks_group2
|
package_kuaishou=com.smile.gifmaker
|
||||||
group_taobao_name=tb_group2
|
package_pdd=com.xunmeng.pinduoduo
|
||||||
group_douyin_name=dy_group2
|
|
||||||
group_wechat_name=wc_group2
|
|
||||||
@ -1 +1 @@
|
|||||||
com.lateautumn4lin.sign.entry.HookLoader
|
com.lateautumn4lin.headwolf.entry.BaseEntry
|
||||||
@ -7,5 +7,137 @@ package com.lateautumn4lin.headwolf;
|
|||||||
* @date 2020/9/10 13:40
|
* @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 {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,11 +4,29 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.lateautumn4lin.headwolf.commons.Logger;
|
||||||
|
import com.tencent.mmkv.MMKV;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Main activity.
|
||||||
|
*/
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
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());
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,5 +7,64 @@ package com.lateautumn4lin.headwolf.commons;
|
|||||||
* @date 2020/9/10 13:54
|
* @date 2020/9/10 13:54
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Logger.
|
||||||
|
*/
|
||||||
public class 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,111 @@ package com.lateautumn4lin.headwolf.entry;
|
|||||||
* @date 2020/9/10 13:45
|
* @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 Error,Package:%s", modulePackageName));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,45 @@ package com.lateautumn4lin.headwolf.entry;
|
|||||||
* @date 2020/9/10 13:45
|
* @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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,24 @@ package com.lateautumn4lin.headwolf.handlers;
|
|||||||
* @date 2020/9/10 13:44
|
* @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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,5 +7,43 @@ package com.lateautumn4lin.headwolf.handlers;
|
|||||||
* @date 2020/9/10 15:39
|
* @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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,8 @@ package com.lateautumn4lin.headwolf.initialization;
|
|||||||
* @date 2020/9/10 13:49
|
* @date 2020/9/10 13:49
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Base init.
|
||||||
|
*/
|
||||||
public class BaseInit {
|
public class BaseInit {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,5 +7,65 @@ package com.lateautumn4lin.headwolf.initialization;
|
|||||||
* @date 2020/9/10 13:49
|
* @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 {
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,38 +11,38 @@ package com.lateautumn4lin.headwolf.utils;
|
|||||||
import android.content.Context;
|
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.File;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import dalvik.system.DexFile;
|
import dalvik.system.DexFile;
|
||||||
|
import dalvik.system.PathClassLoader;
|
||||||
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类读取器<br/>
|
* The type Classes reader assistant.
|
||||||
* 读取某个包下所有类<br/>
|
|
||||||
*/
|
*/
|
||||||
public final class ClassesReaderAssistant {
|
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 包路径
|
* @param packageCodePath the package code path
|
||||||
* @return Set<DexFile> set
|
* @return the set
|
||||||
*/
|
*/
|
||||||
public static Set<DexFile> applicationDexFile(String packageCodePath) {
|
public static Set<DexFile> applicationDexFile(String packageCodePath) {
|
||||||
Set<DexFile> dexFiles = new HashSet<>();
|
Set<DexFile> dexFiles = new HashSet<>();
|
||||||
@ -64,11 +64,12 @@ public final class ClassesReaderAssistant {
|
|||||||
return dexFiles;
|
return dexFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建DexFile文件
|
* Create dex file dex file.
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path the path
|
||||||
* @return DexFile dex file
|
* @return the dex file
|
||||||
*/
|
*/
|
||||||
public static DexFile createDexFile(String path) {
|
public static DexFile createDexFile(String path) {
|
||||||
try {
|
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 context the context
|
||||||
* @param packageCodePath 上下文
|
* @param associateName the associate name
|
||||||
* @return List<Class> list
|
* @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) {
|
public static List<Class<?>> reader(String packageName, String packageCodePath) {
|
||||||
List<Class<?>> classes = new ArrayList<>();
|
List<Class<?>> classes = new ArrayList<>();
|
||||||
Set<DexFile> dexFiles = applicationDexFile(packageCodePath);
|
Set<DexFile> dexFiles = applicationDexFile(packageCodePath);
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
for (DexFile dexFile : dexFiles) {
|
for (DexFile dexFile : dexFiles) {
|
||||||
if (dexFile == null) continue;
|
Logger.logi(dexFile.toString());
|
||||||
Enumeration<String> entries = dexFile.entries();
|
try {
|
||||||
while (entries.hasMoreElements()) {
|
PathClassLoader pathClassLoader = new PathClassLoader(new File(packageCodePath).getAbsolutePath(), XposedBridge.BOOTCLASSLOADER);
|
||||||
try {
|
if (dexFile == null) continue;
|
||||||
String currentClassPath = entries.nextElement();
|
Enumeration<String> entries = dexFile.entries();
|
||||||
if (currentClassPath == null || currentClassPath.isEmpty() || currentClassPath.indexOf(packageName) != 0)
|
while (entries.hasMoreElements()) {
|
||||||
continue;
|
try {
|
||||||
Class<?> entryClass = Class.forName(currentClassPath, true, classLoader);
|
String currentClassPath = entries.nextElement();
|
||||||
if (entryClass == null) continue;
|
if (currentClassPath == null || currentClassPath.isEmpty() || currentClassPath.indexOf(packageName) != 0)
|
||||||
classes.add(entryClass);
|
continue;
|
||||||
} catch (Exception e) {
|
Class<?> entryClass = Class.forName(currentClassPath, true, pathClassLoader);
|
||||||
e.printStackTrace();
|
if (entryClass == null) continue;
|
||||||
|
classes.add(entryClass);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.loge(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return classes;
|
return classes;
|
||||||
|
|||||||
@ -7,5 +7,8 @@ package com.lateautumn4lin.headwolf.utils;
|
|||||||
* @date 2020/9/10 13:54
|
* @date 2020/9/10 13:54
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Communication assistant.
|
||||||
|
*/
|
||||||
public class CommunicationAssistant {
|
public class CommunicationAssistant {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,23 @@
|
|||||||
package com.lateautumn4lin.headwolf.utils;
|
package com.lateautumn4lin.headwolf.utils;
|
||||||
|
|
||||||
|
import com.lateautumn4lin.headwolf.commons.Logger;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class ProperTies {
|
/**
|
||||||
|
* The type Properties assistant.
|
||||||
|
*/
|
||||||
|
public class PropertiesAssistant {
|
||||||
|
/**
|
||||||
|
* Gets properties.
|
||||||
|
*
|
||||||
|
* @return the properties
|
||||||
|
*/
|
||||||
public static Properties getProperties() {
|
public static Properties getProperties() {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
InputStream in = ProperTies.class.getResourceAsStream("/assets/config");
|
|
||||||
try {
|
try {
|
||||||
|
InputStream in = PropertiesAssistant.class.getResourceAsStream("/assets/config");
|
||||||
props.load(in);
|
props.load(in);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.loge(e.toString());
|
Logger.loge(e.toString());
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Hello World!"
|
android:text="来Github提Issue、提Pr!"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Headwolf</string>
|
<string name="app_name">Headwolf框架</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@ -3,9 +3,10 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.6.1'
|
classpath 'com.android.tools.build:gradle:3.6.1'
|
||||||
@ -20,6 +21,9 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
mavenCentral()
|
||||||
|
maven { url "https://jitpack.io" }
|
||||||
|
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
headwolf/mmkv-static-1.1.2/build.gradle
Normal file
2
headwolf/mmkv-static-1.1.2/build.gradle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
configurations.maybeCreate("default")
|
||||||
|
artifacts.add("default", file('mmkv-static-1.1.2.aar'))
|
||||||
@ -1,2 +1,2 @@
|
|||||||
rootProject.name='Headwolf'
|
rootProject.name='Headwolf'
|
||||||
include ':app'
|
include ':app', ':mmkv-static-1.1.2'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user