当前位置:网站首页>First!! Is lancet hungry? Official documents
First!! Is lancet hungry? Official documents
2022-07-03 15:53:00 【Code is not difficult to write】
Lancet
Lancet It's a lightweight Android AOP frame .
- Compilation speed is fast , And supports incremental compilation .
- concise API, A few lines Java Code completion injection requirements .
- No extra code to insert apk.
- Support for SDK, Can be in SDK Write injection code to modify dependencies SDK Of App.
Start using
install
At the root build.gradle add to :
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'me.ele:lancet-plugin:1.0.6'
}
Be careful : Lancet 1.0.5 And above versions only support gradle 3.3.2 And above .
stay app The directory ’build.gradle’ add to :
apply plugin: 'me.ele.lancet'
dependencies {
provided 'me.ele:lancet-base:1.0.6'
}
Example
Lancet Use annotations to specify the rules and location of code weaving .
First look at the basics API Use :
@Proxy("i")
@TargetClass("android.util.Log")
public static int anyName(String tag, String msg){
msg = msg + "lancet";
return (int) Origin.call();
}
Here are a few key points :
@TargetClassSpecifies the target class to be woven into the codeandroid.util.Log.@ProxySpecifies the target method to be woven into the codei.- The weaving method is
Proxy( Will be introduced later ). Origin.call()On behalf ofLog.i()This goal method .
So this example Hook The function of the method is All that appears in the code Log.i(tag,msg) Replace code with Log.i(tag,msg + "lancet")
Code weaving method
@Proxy
public @interface Proxy {
String value();
}
@Proxy New methods will be used Replace The original target method existing in the code .
For example, there are 10 A place called Dog.bark(), After proxy this method , be-all 10 The code in one place will become _Lancet.xxxx.bark(). In this new method, you will execute Hook Method .@Proxy Usually used for system API The hijacking of . Because although we can't inject code into the library provided by the system , But we can hijack all calling systems API The place of .
@NameRegex
@NameRegex Scope used to limit scope operations . Only used for Proxy In the pattern , For example, you just want to delegate all the target operations under a package name . Or when you are acting for all network requests , I don't want to represent my request . Use NameRegex Yes TargetClass , ImplementedInterface Screened out class Make another match .
@Insert
public @interface Insert {
String value();
boolean mayCreateSuper() default false;
}
@Insert Insert the new code before and after the original code of the target method .@Insert Often used to operate App And library Class , And through This Operate the private properties and methods of the target class ( The following will introduce ).@Insert When the target method does not exist , You can also use mayCreateSuper Parameter to create the target method .
For example, the following code is injected into each Activity Of onStop Life cycle
@TargetClass(value = "android.support.v7.app.AppCompatActivity", scope = Scope.LEAF)
@Insert(value = "onStop", mayCreateSuper = true)
protected void onStop(){
System.out.println("hello world");
Origin.callVoid();
}
Scope It will be introduced later , The goal here is AppCompatActivity All final subclasses of .
If a class MyActivity extends AppcompatActivity No rewriting onStop Automatically created onStop Method , and Origin Here represents super.onStop(), Finally, this effect :
protected void onStop() {
System.out.println("hello world");
super.onStop();
}
Note:public/protected/private The modifier will completely copy Hook Method modifier .
Match the target class
public @interface TargetClass {
String value();
Scope scope() default Scope.SELF;
}
public @interface ImplementedInterface {
String[] value();
Scope scope() default Scope.SELF;
}
public enum Scope {
SELF,
DIRECT,
ALL,
LEAF
}
Many situations , We won't match just one class , There will be injection of all subclasses of a certain type , Or all classes that implement an interface . So pass TargetClass , ImplementedInterface 2 A note and Scope Match the target class .
@TargetClass
Find... Through class .
@TargetClassOfvalueIs the full name of a class .- Scope.SELF Represents only matching
valueSpecified target class . - Scope.DIRECT On behalf of the match
valueSpecifies the direct subclass of the class . - Scope.All On behalf of the match
valueAll subclasses of the specified class . - Scope.LEAF On behalf of the match
valueSpecifies the final subclass of the class . as everyone knows java It's single inheritance , So the inheritance relationship is a tree structure , Therefore, this represents all leaf nodes of the inheritance tree with the specified class as vertex .
@ImplementedInterface
Search through the interface . The situation is slightly more complicated than finding through classes .
@ImplementedInterfaceOfvalueYou can fill in the full names of multiple interfaces .- Scope.SELF : Represents a class that directly implements all specified interfaces .
- Scope.DIRECT : Represents the direct implementation of all specified interfaces , And the class of the sub interface of the specified interface .
- Scope.ALL: representative
Scope.DIRECTAll specified classes and all their subclasses . - Scope.LEAF: representative
Scope.ALLAll leaf nodes in the specified forest structure .
Here's the picture :
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-GDKe4ObV-1656654396985)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed56b649f7354f248146f7ccc472b8f0~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
When we use @ImplementedInterface(value = "I", scope = ...) when , The target classes are as follows :
- Scope.SELF -> A
- Scope.DIRECT -> A C
- Scope.ALL -> A B C D
- Scope.LEAF -> B D
Match target method
Although in Proxy , Insert In, we specify the method name , But the identification method must be more detailed information . We will use Hook Method modifier , Parameter types to match methods .
So be sure to keep Hook Methodical public/protected/privatestatic The information is consistent with the target method , Parameter type , The return type is consistent with the target method .
Return type can be used Object Instead of .
Method names are unlimited . Exception declarations are not limited to .
But sometimes we don't have permission to declare the target class . Now what? ?
@ClassOf
have access to ClassOf Annotation instead of direct to the class import.
Here's an example :
public class A {
protected int execute(B b){
return b.call();
}
private class B {
int call() {
return 0;
}
}
}
@TargetClass("com.dieyidezui.demo.A")
@Insert("execute")
public int hookExecute(@ClassOf("com.dieyidezui.demo.A$B") Object o) {
System.out.println(o);
return (int) Origin.call();
}
ClassOf Of value Be sure to follow **(package_name.)(outer_class_name$)inner_class_name([]...)** The template of .
such as :
- java.lang.Object
- java.lang.Integer[][]
- A[]
- A$B
API
We can go through Origin And This Some interaction with the target class .
Origin
Origin Used to call the original target method . Can be called multiple times .Origin.call() Used to call a method with a return value .Origin.callVoid() Used to call a method that has no return value .
in addition , If you have a need to catch exceptions . have access to Origin.call/callThrowOne/callThrowTwo/callThrowThree()Origin.callVoid/callVoidThrowOne/callVoidThrowTwo/callVoidThrowThree()
For example:
@TargetClass("java.io.InputStream")
@Proxy("read")
public int read(byte[] bytes) throws IOException {
try {
return (int) Origin.<IOException>callThrowOne();
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
This
Only used for Insert Way of non static method Hook in .( temporary )
get()
Returns the instantiated object to which the target method is called .
putField & getField
You can directly access all properties of the target class , Whether it's protected or private.
in addition , If this property does not exist , We will also automatically create this property . Exciting!
Automatic packing and unpacking must also support .
Some known defects :
ProxyOut of commissionThis- You cannot access the properties of your parent class . When you try to access a parent property , We will still create new properties .
For example:
package me.ele;
public class Main {
private int a = 1;
public void nothing(){
}
public int getA(){
return a;
}
}
@TargetClass("me.ele.Main")
@Insert("nothing")
public void testThis() {
Log.e("debug", This.get().getClass().getName());
This.putField(3, "a");
Origin.callVoid();
}
Tips
- The inner class should be named
package.outer_class$inner_class - SDK Developers don't need
applyplug-in unit , It only needsprovided me.ele:lancet-base:x.y.z - Although we support incremental compilation . But when we use
Scope.LEAF、Scope.ALLThe class covered has changed Or modify Hook Class time , This compilation will become full compilation .
License
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Last
In the field of Technology , There's no course you can take once and for all , Only by continuous improvement can we not be eliminated by the times .
If you feel that you are inefficient in your studies , Lack of proper guidance , Sure Comment button 1 Or private letter , Free collection Android Related learning materials , And have the opportunity to join the Daniel exchange group to have an in-depth understanding of the industry trend 、 Refined specialty Skill , get Large factory push The opportunity to !!
边栏推荐
- 关于网页中的文本选择以及统计选中文本长度
- Wechat payment -jsapi: code implementation (payment asynchronous callback, Chinese parameter solution)
- [combinatorics] combinatorial identities (recursive combinatorial identities | sum of variable terms | simple combinatorial identities and | sum of variable terms | staggered sums of combinatorial ide
- "Remake Apple product UI with Android" (2) -- silky Appstore card transition animation
- MB10M-ASEMI整流桥MB10M
- leetcode_ Power of Four
- Nifi from introduction to practice (nanny level tutorial) - flow
- Using optimistic lock and pessimistic lock in MySQL to realize distributed lock
- Break through 1million, sword finger 2million!
- Semi supervised learning
猜你喜欢
随机推荐
阿飞的期望
从 flask 服务端代码自动生成客户端代码 -- flask-native-stubs 库介绍
Microservices - load balancing ribbon
Summary of JVM knowledge points
UnityShader——MaterialCapture材质捕捉效果 (翡翠斧头)
首发!!lancet饿了么官方文档
QT common sentence notes
Redis high availability and persistence
《微服务设计》读书笔记(上)
Win32 create window and button (lightweight)
Wechat payment -jsapi: code implementation (payment asynchronous callback, Chinese parameter solution)
Jvm-09 byte code introduction
Persisting in output requires continuous learning
Microservice API gateway zuul
Visual host system design and development (Halcon WinForm)
Go语言自学系列 | golang中的if else语句
Salary 3000, monthly income 40000 by "video editing": people who can make money never rely on hard work!
几种常见IO模型的原理
"Remake Apple product UI with Android" (2) -- silky Appstore card transition animation
win32创建窗口及按钮(轻量级)







