...
3
.idea/compiler.xml
generated
@@ -2,7 +2,8 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="1.8">
|
<bytecodeTargetLevel target="1.8">
|
||||||
<module name="YukiHookAPI.app" target="11" />
|
<module name="YukiHookAPI.app_demo" target="11" />
|
||||||
|
<module name="YukiHookAPI.module_demo" target="11" />
|
||||||
<module name="YukiHookAPI.yukihookapi-yaya" target="11" />
|
<module name="YukiHookAPI.yukihookapi-yaya" target="11" />
|
||||||
</bytecodeTargetLevel>
|
</bytecodeTargetLevel>
|
||||||
</component>
|
</component>
|
||||||
|
3
.idea/gradle.xml
generated
@@ -10,7 +10,8 @@
|
|||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app_demo" />
|
||||||
|
<option value="$PROJECT_DIR$/module_demo" />
|
||||||
<option value="$PROJECT_DIR$/yukihookapi" />
|
<option value="$PROJECT_DIR$/yukihookapi" />
|
||||||
<option value="$PROJECT_DIR$/yukihookapi-ksp-xposed" />
|
<option value="$PROJECT_DIR$/yukihookapi-ksp-xposed" />
|
||||||
</set>
|
</set>
|
||||||
|
3
.idea/misc.xml
generated
@@ -4,6 +4,9 @@
|
|||||||
<option name="filePathToZoomLevelMap">
|
<option name="filePathToZoomLevelMap">
|
||||||
<map>
|
<map>
|
||||||
<entry key="app/src/main/res/layout/activity_main.xml" value="0.4169230769230769" />
|
<entry key="app/src/main/res/layout/activity_main.xml" value="0.4169230769230769" />
|
||||||
|
<entry key="app_demo/src/main/res/layout/activity_main.xml" value="0.4375" />
|
||||||
|
<entry key="demo/src/main/res/layout/activity_main.xml" value="0.4375" />
|
||||||
|
<entry key="module_demo/src/main/res/layout/activity_main.xml" value="0.4375" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
package com.highcapable.yukihookapi
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
assertEquals("com.highcapable.yukihookapi", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
com.highcapable.yukihookapi.demo.hook.inject.MainInjecter_YukiHookXposedInit
|
|
@@ -1,52 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/7.
|
|
||||||
*/
|
|
||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package com.highcapable.yukihookapi.demo
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.content.Context
|
|
||||||
import com.highcapable.yukihookapi.YukiHookAPI
|
|
||||||
import com.highcapable.yukihookapi.demo.hook.MainHooker
|
|
||||||
import com.highcapable.yukihookapi.demo.hook.SecondHooker
|
|
||||||
|
|
||||||
class App : Application() {
|
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context?) {
|
|
||||||
////
|
|
||||||
// 装载你的 Hook 框架的代码
|
|
||||||
////
|
|
||||||
// 方式 1
|
|
||||||
YukiHookAPI.encase(base) {
|
|
||||||
// Your code here.
|
|
||||||
}
|
|
||||||
// 方式 2
|
|
||||||
YukiHookAPI.encase(base, MainHooker(), SecondHooker())
|
|
||||||
super.attachBaseContext(base)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,55 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/8.
|
|
||||||
*/
|
|
||||||
package com.highcapable.yukihookapi.demo
|
|
||||||
|
|
||||||
import androidx.annotation.Keep
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
class InjectLucky {
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
private var string = "没有"
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
constructor() {
|
|
||||||
string = "原始数据"
|
|
||||||
}
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
constructor(string: String = "原始数据复写") {
|
|
||||||
this.string = string
|
|
||||||
}
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
fun getString() = string
|
|
||||||
}
|
|
@@ -1,46 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/8.
|
|
||||||
*/
|
|
||||||
package com.highcapable.yukihookapi.demo
|
|
||||||
|
|
||||||
import androidx.annotation.Keep
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
class InjectNoParamTest {
|
|
||||||
|
|
||||||
@Keep
|
|
||||||
private var test = "没有"
|
|
||||||
|
|
||||||
init {
|
|
||||||
test = "没修改的变量"
|
|
||||||
}
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
fun getString() = test
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/3.
|
|
||||||
*/
|
|
||||||
package com.highcapable.yukihookapi.demo
|
|
||||||
|
|
||||||
import androidx.annotation.Keep
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
class InjectTestName(private val string: String) {
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
fun getString() = string
|
|
||||||
}
|
|
@@ -1,111 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/29.
|
|
||||||
*/
|
|
||||||
@file:Suppress("SameParameterValue")
|
|
||||||
|
|
||||||
package com.highcapable.yukihookapi.demo
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.Keep
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
|
||||||
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
|
||||||
|
|
||||||
@Keep
|
|
||||||
class MainActivity : AppCompatActivity() {
|
|
||||||
|
|
||||||
@Keep
|
|
||||||
private var a = "没更改的变量"
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
// for test
|
|
||||||
findViewById<Button>(R.id.main_button).setOnClickListener {
|
|
||||||
modulePrefs.apply {
|
|
||||||
putString("data", "这是存储的数据")
|
|
||||||
putBoolean("test_key", true)
|
|
||||||
putString("test_key_name", "存储数据成功,包名:$packageName")
|
|
||||||
}
|
|
||||||
Toast.makeText(this, "存储完成", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
// for test
|
|
||||||
AlertDialog.Builder(this)
|
|
||||||
.setTitle("Hook 方法返回值测试")
|
|
||||||
.setMessage(test() + "\n变量:$a\n模块数据:${xptest()}\n模块是否已激活:${YukiHookModuleStatus.isActive()}")
|
|
||||||
.setPositiveButton("下一个") { _, _ ->
|
|
||||||
AlertDialog.Builder(this)
|
|
||||||
.setTitle("Hook 方法参数测试")
|
|
||||||
.setMessage(test("这是没有更改的文字") + "\n${a(content = "这是原文")}\n模块是否已激活:${YukiHookModuleStatus.isActive()}")
|
|
||||||
.setPositiveButton("下一个") { _, _ ->
|
|
||||||
AlertDialog.Builder(this)
|
|
||||||
.setTitle("Hook 构造方法测试(stub)")
|
|
||||||
.setMessage(InjectTest("文字未更改").getString() + "\n模块是否已激活:${YukiHookModuleStatus.isActive()}")
|
|
||||||
.setPositiveButton("下一个") { _, _ ->
|
|
||||||
AlertDialog.Builder(this)
|
|
||||||
.setTitle("Hook 构造方法测试(多个)")
|
|
||||||
.setMessage(InjectLucky().getString() + "\n" + InjectLucky(string = "没更改的文字").getString() + "\n模块是否已激活:${YukiHookModuleStatus.isActive()}")
|
|
||||||
.setPositiveButton("下一个") { _, _ ->
|
|
||||||
AlertDialog.Builder(this)
|
|
||||||
.setTitle("Hook 构造方法测试(无参)")
|
|
||||||
.setMessage(InjectNoParamTest().getString() + "\n模块是否已激活:${YukiHookModuleStatus.isActive()}")
|
|
||||||
.setPositiveButton("下一个") { _, _ ->
|
|
||||||
AlertDialog.Builder(this)
|
|
||||||
.setTitle("Hook 构造方法测试(名称)")
|
|
||||||
.setMessage(InjectTestName("文字没更改").getString() + "\n模块是否已激活:${YukiHookModuleStatus.isActive()}")
|
|
||||||
.setPositiveButton("完成") { _, _ -> toast() }
|
|
||||||
.show()
|
|
||||||
}.show()
|
|
||||||
}.show()
|
|
||||||
}.show()
|
|
||||||
}.show()
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
private fun toast() = Toast.makeText(this, "我弹出来了,没有 Hook", Toast.LENGTH_SHORT).show()
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
private fun a(content1: String = "前缀", content: String) = "$content1${content}_后面加了一段文字"
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
private fun test() = "正常显示的一行文字"
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
private fun xptest() = "这里是正常的文字"
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
private fun test(string: String) = string
|
|
||||||
}
|
|
@@ -1,100 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/2.
|
|
||||||
*/
|
|
||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package com.highcapable.yukihookapi.demo.hook
|
|
||||||
|
|
||||||
import com.highcapable.yukihookapi.demo.BuildConfig
|
|
||||||
import com.highcapable.yukihookapi.demo.InjectTest
|
|
||||||
import com.highcapable.yukihookapi.demo.MainActivity
|
|
||||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
|
||||||
import com.highcapable.yukihookapi.hook.type.BundleClass
|
|
||||||
import com.highcapable.yukihookapi.hook.type.StringType
|
|
||||||
import com.highcapable.yukihookapi.hook.type.UnitType
|
|
||||||
|
|
||||||
// for test
|
|
||||||
class MainHooker : YukiBaseHooker() {
|
|
||||||
|
|
||||||
override fun onHook() =
|
|
||||||
loadApp(name = BuildConfig.APPLICATION_ID) {
|
|
||||||
MainActivity::class.java.hook {
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "onCreate"
|
|
||||||
param(BundleClass)
|
|
||||||
}
|
|
||||||
beforeHook {
|
|
||||||
field {
|
|
||||||
name = "a"
|
|
||||||
type = StringType
|
|
||||||
}.set(instance, "这段文字被修改成功了")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "toast"
|
|
||||||
returnType = UnitType
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "a"
|
|
||||||
param(StringType, StringType)
|
|
||||||
returnType = StringType
|
|
||||||
}
|
|
||||||
beforeHook {
|
|
||||||
args(index = 0).set("改了前面的")
|
|
||||||
args(index = 1).set("改了后面的")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "test"
|
|
||||||
returnType = StringType
|
|
||||||
}
|
|
||||||
replaceTo("这段文字已被 Hook 成功")
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "test"
|
|
||||||
param(StringType)
|
|
||||||
returnType = StringType
|
|
||||||
}
|
|
||||||
beforeHook { args().set("方法参数已被 Hook 成功") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InjectTest::class.java.hook {
|
|
||||||
injectMember {
|
|
||||||
constructor { param(StringType) }
|
|
||||||
beforeHook { args().set("构造方法已被 Hook 成功") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadHooker(hooker = TestChildHooker())
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,66 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/3.
|
|
||||||
*/
|
|
||||||
package com.highcapable.yukihookapi.demo.hook
|
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.widget.Toast
|
|
||||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
|
||||||
import com.highcapable.yukihookapi.hook.factory.findMethod
|
|
||||||
import com.highcapable.yukihookapi.hook.type.ActivityClass
|
|
||||||
import com.highcapable.yukihookapi.hook.type.BundleClass
|
|
||||||
|
|
||||||
// for test
|
|
||||||
class SecondHooker : YukiBaseHooker() {
|
|
||||||
|
|
||||||
override fun onHook() =
|
|
||||||
loadApp(name = "com.android.browser") {
|
|
||||||
ActivityClass.hook {
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "onCreate"
|
|
||||||
param(BundleClass)
|
|
||||||
}
|
|
||||||
afterHook {
|
|
||||||
AlertDialog.Builder(instance())
|
|
||||||
.setCancelable(false)
|
|
||||||
.setTitle("测试 Hook")
|
|
||||||
.setMessage("Hook 已成功")
|
|
||||||
.setPositiveButton("OK") { _, _ ->
|
|
||||||
Toast.makeText(instance(), "Hook Success", Toast.LENGTH_SHORT).show()
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
member = hookClass.findMethod(name = "onStart")
|
|
||||||
afterHook {
|
|
||||||
Toast.makeText(instance(), "手动 Hook", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,43 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/4.
|
|
||||||
*/
|
|
||||||
package com.highcapable.yukihookapi.demo.hook
|
|
||||||
|
|
||||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
|
||||||
import com.highcapable.yukihookapi.hook.type.StringType
|
|
||||||
|
|
||||||
// for test
|
|
||||||
class TestChildHooker : YukiBaseHooker() {
|
|
||||||
|
|
||||||
override fun onHook() =
|
|
||||||
findClass(name = "$packageName.InjectTestName").hook {
|
|
||||||
injectMember {
|
|
||||||
constructor { param(StringType) }
|
|
||||||
beforeHook { args().set("构造方法已被 Hook 成功 [2]") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,187 +0,0 @@
|
|||||||
/**
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 HighCapable
|
|
||||||
*
|
|
||||||
* This file is part of YukiHookAPI.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/2/4.
|
|
||||||
*/
|
|
||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package com.highcapable.yukihookapi.demo.hook.inject
|
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.widget.Toast
|
|
||||||
import com.highcapable.yukihookapi.YukiHookAPI
|
|
||||||
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
|
||||||
import com.highcapable.yukihookapi.demo.*
|
|
||||||
import com.highcapable.yukihookapi.hook.factory.encase
|
|
||||||
import com.highcapable.yukihookapi.hook.factory.findMethod
|
|
||||||
import com.highcapable.yukihookapi.hook.type.ActivityClass
|
|
||||||
import com.highcapable.yukihookapi.hook.type.BundleClass
|
|
||||||
import com.highcapable.yukihookapi.hook.type.StringType
|
|
||||||
import com.highcapable.yukihookapi.hook.type.UnitType
|
|
||||||
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@InjectYukiHookWithXposed
|
|
||||||
class MainInjecter : YukiHookXposedInitProxy {
|
|
||||||
|
|
||||||
override fun onHook() {
|
|
||||||
// 设置模式
|
|
||||||
YukiHookAPI.configs {
|
|
||||||
debugTag = "YukiSuki"
|
|
||||||
isDebug = true
|
|
||||||
}
|
|
||||||
// 方案 1
|
|
||||||
// encase(MainHooker(), SecondHooker())
|
|
||||||
// 方案 2
|
|
||||||
encase {
|
|
||||||
loadApp(name = BuildConfig.APPLICATION_ID) {
|
|
||||||
MainActivity::class.java.hook {
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "onCreate"
|
|
||||||
param(BundleClass)
|
|
||||||
}
|
|
||||||
beforeHook {
|
|
||||||
field {
|
|
||||||
name = "a"
|
|
||||||
type = StringType
|
|
||||||
}.set(instance, "这段文字被修改成功了")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "xptest"
|
|
||||||
returnType = StringType
|
|
||||||
}
|
|
||||||
replaceTo(prefs.getString(key = "data", default = "获取 Hook:没数据"))
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "toast"
|
|
||||||
returnType = UnitType
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "a"
|
|
||||||
param(StringType, StringType)
|
|
||||||
returnType = StringType
|
|
||||||
}
|
|
||||||
beforeHook {
|
|
||||||
args(index = 0).set("✌️改了前面的")
|
|
||||||
args(index = 1).set("✌️改了后面的")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "test"
|
|
||||||
returnType = StringType
|
|
||||||
}
|
|
||||||
replaceTo("这段文字已被 Hook 成功")
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "test"
|
|
||||||
param(StringType)
|
|
||||||
returnType = StringType
|
|
||||||
}
|
|
||||||
beforeHook { args().set("方法参数已被 Hook 成功") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InjectLucky::class.java.hook {
|
|
||||||
injectMember {
|
|
||||||
allConstructors()
|
|
||||||
afterHook {
|
|
||||||
field {
|
|
||||||
name = "string"
|
|
||||||
type = StringType
|
|
||||||
}.set(instance, "内容被改掉了")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InjectTest::class.java.hook {
|
|
||||||
injectMember {
|
|
||||||
constructor { param(StringType) }
|
|
||||||
beforeHook { args().set("构造方法已被 Hook 成功") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InjectNoParamTest::class.java.hook {
|
|
||||||
injectMember {
|
|
||||||
constructor()
|
|
||||||
afterHook {
|
|
||||||
field {
|
|
||||||
name = "test"
|
|
||||||
type = StringType
|
|
||||||
}.set(instance, "内容被改掉了")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
findClass(name = "$packageName.InjectTestName").hook {
|
|
||||||
injectMember {
|
|
||||||
constructor { param(StringType) }
|
|
||||||
beforeHook { args().set("构造方法已被 Hook 成功 [2]") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadApp(name = "com.android.browser") {
|
|
||||||
ActivityClass.hook {
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "onCreate"
|
|
||||||
param(BundleClass)
|
|
||||||
}
|
|
||||||
afterHook {
|
|
||||||
AlertDialog.Builder(instance())
|
|
||||||
.setCancelable(false)
|
|
||||||
.setTitle("测试 Hook")
|
|
||||||
.setMessage(
|
|
||||||
"Hook 已成功\n" +
|
|
||||||
"test_key:${prefs.getBoolean("test_key")}\n" +
|
|
||||||
"test_key_name:${prefs.getString("test_key_name", "默认值")}"
|
|
||||||
)
|
|
||||||
.setPositiveButton("OK") { _, _ ->
|
|
||||||
Toast.makeText(instance(), "Hook Success", Toast.LENGTH_SHORT).show()
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
member = hookClass.findMethod(name = "onStart")
|
|
||||||
afterHook {
|
|
||||||
Toast.makeText(instance(), "手动 Hook", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}.failures {
|
|
||||||
onConductFailure { _, _ -> }
|
|
||||||
onHookingFailure {}
|
|
||||||
onAllFailure {}
|
|
||||||
ignoredConductFailure()
|
|
||||||
ignoredHookingFailure()
|
|
||||||
ignoredAllFailure()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".MainActivity"
|
|
||||||
tools:ignore="HardcodedText">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:text="Hello World!" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/main_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="存储模块数据" />
|
|
||||||
</LinearLayout>
|
|
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<string name="app_name">YukiHookAPI</string>
|
|
||||||
</resources>
|
|
@@ -1,17 +0,0 @@
|
|||||||
package com.highcapable.yukihookapi
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
fun addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2)
|
|
||||||
}
|
|
||||||
}
|
|
0
app/.gitignore → app_demo/.gitignore
vendored
54
app_demo/build.gradle
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
plugins {
|
||||||
|
id 'com.android.application'
|
||||||
|
id 'org.jetbrains.kotlin.android'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
signingConfigs {
|
||||||
|
debug {
|
||||||
|
storeFile file('../keystore/public')
|
||||||
|
storePassword '123456'
|
||||||
|
keyAlias 'public'
|
||||||
|
keyPassword '123456'
|
||||||
|
v1SigningEnabled true
|
||||||
|
v2SigningEnabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileSdk 31
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.highcapable.yukihookapi.app_demo"
|
||||||
|
minSdk 22
|
||||||
|
targetSdk 31
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
|
implementation 'com.google.android.material:material:1.5.0'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
|
testImplementation 'junit:junit:4.13.2'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
|
}
|
23
app_demo/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.highcapable.yukihookapi.app_demo">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/Theme.Default">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ui.MainActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 HighCapable
|
||||||
|
*
|
||||||
|
* This file is part of YukiHookAPI.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is Created by fankes on 2022/2/9.
|
||||||
|
*/
|
||||||
|
@file:Suppress("SameParameterValue")
|
||||||
|
|
||||||
|
package com.highcapable.yukihookapi.app_demo.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.highcapable.yukihookapi.app_demo.R
|
||||||
|
import com.highcapable.yukihookapi.app_demo.utils.Main
|
||||||
|
|
||||||
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
findViewById<TextView>(R.id.app_demo_first_text).text = getFirstText()
|
||||||
|
findViewById<TextView>(R.id.app_demo_second_text).text = secondText
|
||||||
|
findViewById<TextView>(R.id.app_demo_third_text).text = Main("Feel real").getString()
|
||||||
|
findViewById<TextView>(R.id.app_demo_fourth_text).text = getRegularText("Have fun day")
|
||||||
|
findViewById<TextView>(R.id.app_demo_fifth_text).text = getDataText()
|
||||||
|
findViewById<Button>(R.id.app_demo_button).setOnClickListener { toast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val secondText = "This is a miracle"
|
||||||
|
|
||||||
|
private fun getFirstText() = "Hello World!"
|
||||||
|
|
||||||
|
private fun getRegularText(string: String) = string
|
||||||
|
|
||||||
|
private fun getDataText() = "No data found"
|
||||||
|
|
||||||
|
private fun toast() = Toast.makeText(this, "Nothing to show", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
@@ -23,17 +23,11 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*
|
*
|
||||||
* This file is Created by fankes on 2022/2/3.
|
* This file is Created by fankes on 2022/2/9.
|
||||||
*/
|
*/
|
||||||
package com.highcapable.yukihookapi.demo
|
package com.highcapable.yukihookapi.app_demo.utils
|
||||||
|
|
||||||
import androidx.annotation.Keep
|
class Main(private val string: String) {
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
class InjectTest(private val string: String) {
|
|
||||||
|
|
||||||
// for test
|
|
||||||
@Keep
|
|
||||||
fun getString() = string
|
fun getString() = string
|
||||||
}
|
}
|
56
app_demo/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="HardcodedText">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_demo_first_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="sample"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_demo_second_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="sample"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_demo_third_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="sample"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_demo_fourth_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="sample"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_demo_fifth_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="sample"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/app_demo_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Click Me!"
|
||||||
|
android:textAllCaps="false" />
|
||||||
|
</LinearLayout>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 982 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -1,6 +1,6 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.YukiHookAPI" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
<style name="Theme.Default" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimary">@color/purple_200</item>
|
<item name="colorPrimary">@color/purple_200</item>
|
||||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
3
app_demo/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">YukiHookAppDemo</string>
|
||||||
|
</resources>
|
@@ -1,6 +1,6 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.YukiHookAPI" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
<style name="Theme.Default" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimary">@color/purple_500</item>
|
<item name="colorPrimary">@color/purple_500</item>
|
||||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
1
module_demo/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/build
|
@@ -19,7 +19,7 @@ android {
|
|||||||
compileSdk 31
|
compileSdk 31
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.highcapable.yukihookapi.demo"
|
applicationId "com.highcapable.yukihookapi.module_demo"
|
||||||
minSdk 22
|
minSdk 22
|
||||||
targetSdk 31
|
targetSdk 31
|
||||||
versionCode 1
|
versionCode 1
|
||||||
@@ -55,12 +55,12 @@ dependencies {
|
|||||||
compileOnly 'de.robv.android.xposed:api:82'
|
compileOnly 'de.robv.android.xposed:api:82'
|
||||||
// Implementation API
|
// Implementation API
|
||||||
implementation project(':yukihookapi')
|
implementation project(':yukihookapi')
|
||||||
|
// Implementation Processor
|
||||||
ksp project(':yukihookapi-ksp-xposed')
|
ksp project(':yukihookapi-ksp-xposed')
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'com.google.android.material:material:1.5.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
implementation project(path: ':yukihookapi')
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
41
module_demo/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
-dontwarn
|
||||||
|
-ignorewarnings
|
||||||
|
|
||||||
|
-optimizationpasses 10
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
|
||||||
|
-dontoptimize
|
||||||
|
-verbose
|
||||||
|
-overloadaggressively
|
||||||
|
-repackageclasses i
|
||||||
|
-allowaccessmodification
|
||||||
|
|
||||||
|
-adaptclassstrings
|
||||||
|
-adaptresourcefilenames
|
||||||
|
-adaptresourcefilecontents
|
||||||
|
|
||||||
|
# -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
|
||||||
|
-renamesourcefileattribute P
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.highcapable.yukihookapi.demo">
|
package="com.highcapable.yukihookapi.module_demo">
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@@ -8,25 +8,25 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.YukiHookAPI">
|
android:theme="@style/Theme.Default">
|
||||||
|
|
||||||
<!-- 是否是xposed模块 -->
|
<!-- 设置为 Xposed 模块 -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposedmodule"
|
android:name="xposedmodule"
|
||||||
android:value="true" />
|
android:value="true" />
|
||||||
|
|
||||||
<!-- 模块描述 -->
|
<!-- 设置你的模块描述 -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposeddescription"
|
android:name="xposeddescription"
|
||||||
android:value="YukiHookAPI Xposed Module Test" />
|
android:value="YukiHookAPI Xposed Module Test" />
|
||||||
|
|
||||||
<!-- 最低xposed版本号 -->
|
<!-- 最低 Xposed 版本号 -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposedminversion"
|
android:name="xposedminversion"
|
||||||
android:value="93" />
|
android:value="93" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".ui.MainActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
1
module_demo/src/main/assets/xposed_init
Normal file
@@ -0,0 +1 @@
|
|||||||
|
com.highcapable.yukihookapi.module_demo.hook.MainHook_YukiHookXposedInit
|
@@ -0,0 +1,133 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 HighCapable
|
||||||
|
*
|
||||||
|
* This file is part of YukiHookAPI.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is Created by fankes on 2022/2/9.
|
||||||
|
*/
|
||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package com.highcapable.yukihookapi.module_demo.hook
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
|
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
||||||
|
import com.highcapable.yukihookapi.hook.type.BundleClass
|
||||||
|
import com.highcapable.yukihookapi.hook.type.StringType
|
||||||
|
import com.highcapable.yukihookapi.hook.type.UnitType
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
||||||
|
|
||||||
|
@InjectYukiHookWithXposed
|
||||||
|
class MainHook : YukiHookXposedInitProxy {
|
||||||
|
|
||||||
|
override fun onHook() {
|
||||||
|
// 配置 YuKiHookAPI
|
||||||
|
YukiHookAPI.configs {
|
||||||
|
// 全局调试用的 TAG
|
||||||
|
debugTag = "YukiHookAPI"
|
||||||
|
// 是否开启全局调试日志输出功能
|
||||||
|
isDebug = true
|
||||||
|
}
|
||||||
|
// 开始你的 Hook
|
||||||
|
YukiHookAPI.encase {
|
||||||
|
// 装载需要 Hook 的 APP
|
||||||
|
loadApp(name = "com.highcapable.yukihookapi.app_demo") {
|
||||||
|
// 得到需要 Hook 的 Class
|
||||||
|
findClass(name = "$packageName.ui.MainActivity").hook {
|
||||||
|
// 注入要 Hook 的方法
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "getFirstText"
|
||||||
|
returnType = StringType
|
||||||
|
}
|
||||||
|
// 执行替换 Hook
|
||||||
|
replaceTo(any = "Hello YukiHookAPI!")
|
||||||
|
}
|
||||||
|
// 注入要 Hook 的方法
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "onCreate"
|
||||||
|
param(BundleClass)
|
||||||
|
}
|
||||||
|
// 在方法执行之前拦截
|
||||||
|
beforeHook {
|
||||||
|
field {
|
||||||
|
name = "secondText"
|
||||||
|
type = StringType
|
||||||
|
}.set(instance, "I am hook result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 注入要 Hook 的方法
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "getRegularText"
|
||||||
|
param(StringType)
|
||||||
|
returnType = StringType
|
||||||
|
}
|
||||||
|
// 在方法执行之前拦截
|
||||||
|
beforeHook {
|
||||||
|
// 设置 0 号 param
|
||||||
|
args().set("I am hook method param")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 注入要 Hook 的方法
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "toast"
|
||||||
|
returnType = UnitType
|
||||||
|
}
|
||||||
|
// 拦截整个方法
|
||||||
|
replaceUnit {
|
||||||
|
AlertDialog.Builder(instance())
|
||||||
|
.setTitle("Hooked")
|
||||||
|
.setMessage("I am hook your toast showing")
|
||||||
|
.setPositiveButton("OK", null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 注入要 Hook 的方法
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "getDataText"
|
||||||
|
returnType = StringType
|
||||||
|
}
|
||||||
|
// 执行替换 Hook
|
||||||
|
replaceTo(prefs.getString(key = "test_data", default = "Test data is nothing"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 得到需要 Hook 的 Class
|
||||||
|
findClass(name = "$packageName.utils.Main").hook {
|
||||||
|
// 注入要 Hook 的方法
|
||||||
|
injectMember {
|
||||||
|
constructor { param(StringType) }
|
||||||
|
// 在方法执行之前拦截
|
||||||
|
beforeHook {
|
||||||
|
// 设置 0 号 param
|
||||||
|
args().set("I am hook constructor param")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 HighCapable
|
||||||
|
*
|
||||||
|
* This file is part of YukiHookAPI.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is Created by fankes on 2022/1/29.
|
||||||
|
*/
|
||||||
|
@file:Suppress("SetTextI18n")
|
||||||
|
|
||||||
|
package com.highcapable.yukihookapi.module_demo.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
||||||
|
import com.highcapable.yukihookapi.module_demo.R
|
||||||
|
|
||||||
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
findViewById<TextView>(R.id.module_demo_text).text = "Module is Active -> ${YukiHookModuleStatus.isActive()}"
|
||||||
|
findViewById<EditText>(R.id.module_demo_edit_text).also {
|
||||||
|
it.setText(modulePrefs.getString(key = "test_data"))
|
||||||
|
findViewById<Button>(R.id.module_demo_button).setOnClickListener { _ ->
|
||||||
|
if (it.text.toString().isNotEmpty()) {
|
||||||
|
modulePrefs.putString(key = "test_data", value = it.text.toString())
|
||||||
|
Toast.makeText(applicationContext, "Saved", Toast.LENGTH_SHORT).show()
|
||||||
|
} else Toast.makeText(applicationContext, "Please enter the text", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,30 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="85.84757"
|
||||||
|
android:endY="92.4963"
|
||||||
|
android:startX="42.9492"
|
||||||
|
android:startY="49.59793"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
170
module_demo/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#3DDC84"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
</vector>
|
34
module_demo/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="HardcodedText">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/module_demo_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="sample"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/module_demo_edit_text"
|
||||||
|
android:layout_width="250dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:hint="Please enter the text"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:ignore="Autofill,LabelFor,TextFields" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/module_demo_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Save Test Data"
|
||||||
|
android:textAllCaps="false" />
|
||||||
|
</LinearLayout>
|
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
BIN
module_demo/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
module_demo/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
module_demo/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 982 B |
BIN
module_demo/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
module_demo/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
module_demo/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
module_demo/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
module_demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
module_demo/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
module_demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 7.6 KiB |
16
module_demo/src/main/res/values-night/themes.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.Default" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_200</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/black</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
10
module_demo/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
|
<color name="purple_500">#FF6200EE</color>
|
||||||
|
<color name="purple_700">#FF3700B3</color>
|
||||||
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
|
<color name="teal_700">#FF018786</color>
|
||||||
|
<color name="black">#FF000000</color>
|
||||||
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
</resources>
|
3
module_demo/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">YukiHookModuleDemo</string>
|
||||||
|
</resources>
|
16
module_demo/src/main/res/values/themes.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.Default" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_500</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/white</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
@@ -1,4 +1,5 @@
|
|||||||
rootProject.name = "YukiHookAPI"
|
rootProject.name = "YukiHookAPI"
|
||||||
include ':app'
|
include ':app_demo'
|
||||||
|
include ':module_demo'
|
||||||
include ':yukihookapi'
|
include ':yukihookapi'
|
||||||
include ':yukihookapi-ksp-xposed'
|
include ':yukihookapi-ksp-xposed'
|
||||||
|
@@ -174,8 +174,8 @@ class YukiHookXposedProcessor : SymbolProcessorProvider {
|
|||||||
if (modulePackageName.isNotBlank()) logger.warn(message = "You set the customize module package name to \"$modulePackageName\",please check for yourself if it is correct")
|
if (modulePackageName.isNotBlank()) logger.warn(message = "You set the customize module package name to \"$modulePackageName\",please check for yourself if it is correct")
|
||||||
val realPackageName =
|
val realPackageName =
|
||||||
modulePackageName.ifBlank {
|
modulePackageName.ifBlank {
|
||||||
if (packageName.contains(".hook."))
|
if (packageName.contains(".hook.") || packageName.endsWith(".hook"))
|
||||||
packageName.split(".hook.")[0]
|
packageName.split(".hook")[0]
|
||||||
else error(msg = "YukiHookAPI cannot identify your App's package name,please refer to the wiki https://github.com/fankes/YukiHookAPI/wiki to fix the package name or manually configure the package name")
|
else error(msg = "YukiHookAPI cannot identify your App's package name,please refer to the wiki https://github.com/fankes/YukiHookAPI/wiki to fix the package name or manually configure the package name")
|
||||||
}
|
}
|
||||||
codeGenerator.createNewFile(
|
codeGenerator.createNewFile(
|
||||||
|