1. 创建一个theos项目
nic.pl
选15,设置包名,和作者
创建好的项目
2. 熟悉语法
Objective-C语法
https://www.runoob.com/w3cnote/objective-c-tutorial.html
Logos语法
https://iphonedev.wiki/index.php/Logos
代码编写
将Tweak.x改成Tweak.xm
Makefile文件里也要改
// Tweak.xm
/ 引入头文件
#import <Foundation/Foundation.h>
/**
* group指令,不会自己执行分组内的代码,需要使用%init进行指定
*/
// 分组1
%group test1
%hook JDYUserContextManager
// 需要hook的方法,和原生的Objc语法一样
+ (id)sharedInstance{
// 打印日志,需要引入头文件 Foundation/Foundation.h
NSLog(@"jinru");
return %orig; // 调用方法的原始实现
}
%end
%end
// 分组2
%group test2
%hook JDYUserContextManager
+ (id)sharedInstance{
NSLog(@"jinru2");
return %orig; // 调用方法的原始实现
}
%end
%end
// 生成匿名构造函数,入口
%ctor{
NSString *appname = @"taobao";
if([appname isEqual:@"taobao"]){
// 指定需要运行的执行的分组代码,%init有两种用法,这里只展示一种
%init(test1);
}else{
%init(test2);
}
}
上面的分组2是没有执行到的,主要是为了体现出分组的用法
因为上面的类是千牛的,所有我们需要把
taobao.plist
内的包名新增一个,或者直接替换成千牛的包名
// taobao.plist
{ Filter = { Bundles = ( "com.apple.springboard","com.taobao.sellerplatform" ); }; }
或者
{ Filter = { Bundles = ( "com.taobao.sellerplatform" ); }; }
这两种写法有什么区别呢,上面hook了两个APP,下面的hook了一个APP
3. 编译运行
运行前先修改下Makefile文件,在最顶部加上以下代码
// Makefile
export THEOS_DEVICE_IP=127.0.0.1 // 设备IP
export THEOS_DEVICE_PORT=2222 // 设备端口号
ARCHS = arm64 // 处理器类型
使用爱思助手连接SSH,也可以使用命令连接,具体命令可以网上找找
编译运行
make
make package
make install
安装好以后打开新的命令行窗口查看日志
输入命令,没有安装需要先安装一下,idevicesyslog
idevicesyslog -m taobao.dylib // taobao为创建项目时的名称
可以看到有个不同的APP都进了
修改一下,让手机进入桌面10S后自动打开千牛APP
// 引入头文件
#import <Foundation/Foundation.h>
/**
* group指令,不会自己执行分组内的代码,需要使用%init进行指定
*/
// 千牛APP
%group qianniu
%hook JDYUserContextManager
// 需要hook的方法,和原生的Objc语法一样
+ (id)sharedInstance{
// 打印日志,需要引入头文件 Foundation/Foundation.h
NSLog(@"jinru");
return %orig; // 调用方法的原始实现
}
%end
%end
// 生成匿名构造函数,入口
%ctor{
// 获取当前APP的BundleId
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];//获取app版本信息
NSString *bundleID = [infoDictionary objectForKey:@"CFBundleIdentifier"];
// 如果是千牛APP就进入千牛的分组
if([bundleID isEqualToString:@"com.taobao.sellerplatform"]){
NSLog(@"jinru:qianniu");
// 指定需要运行的执行的分组代码,%init有两种用法,这里只展示一种
%init(qianniu);
}else{
// 苹果桌面
/*
唤起千牛APP,这里开一个线程,进入之后10S打开千牛APP
*/
[NSThread detachNewThreadWithBlock:^{
@try{
[NSThread sleepForTimeInterval:10];
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
NSObject *workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
[workspace performSelector:@selector(openApplicationWithBundleID:) withObject:@"com.taobao.sellerplatform"];
}@catch (NSException *e){
NSLog(@"%@",e);
}
}];
NSLog(@"jinru:zuomian");
}
}
编译运行并打开桌面,10S后会自动打开千牛APP
目前是两个APP的代码全部放在一个文件中,接下来拆分一下
新建Springboard.h
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Springboard : NSObject {
}
// 初始化
-(instancetype)init;
// 打开APP
-(void)openApplicationWithBundleID:(NSString*)bundleID;
@end
新建Springboard.m
#import "Springboard.h"
@implementation Springboard {
}
// 初始化
-(instancetype)init{
self = [super init];
return self;
}
// 打开APP
-(void)openApplicationWithBundleID:(NSString*)bundleID{
[NSThread detachNewThreadWithBlock:^{
@try{
[NSThread sleepForTimeInterval:10];
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
NSObject *workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
[workspace performSelector:@selector(openApplicationWithBundleID:) withObject:bundleID];
}@catch (NSException *e){
NSLog(@"%@",e);
}
}];
}
@end
修改Tweak.xm
// 引入头文件
#import <Foundation/Foundation.h>
#import "Springboard.h"
/**
* group指令,不会自己执行分组内的代码,需要使用%init进行指定
*/
// 千牛APP
%group qianniu
%hook JDYUserContextManager
// 需要hook的方法,和原生的Objc语法一样
+ (id)sharedInstance{
// 打印日志,需要引入头文件 Foundation/Foundation.h
NSLog(@"jinru");
return %orig; // 调用方法的原始实现
}
%end
%end
// 生成匿名构造函数,入口
%ctor{
// 获取当前APP的BundleId
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];//获取app版本信息
NSString *bundleID = [infoDictionary objectForKey:@"CFBundleIdentifier"];
// 如果是千牛APP就进入千牛的分组
if([bundleID isEqualToString:@"com.taobao.sellerplatform"]){
NSLog(@"jinru:qianniu");
// 指定需要运行的执行的分组代码,%init有两种用法,这里只展示一种
%init(qianniu);
}else{
// 苹果桌面
/*
唤起千牛APP,这里开一个线程,进入之后10S打开千牛APP
*/
Springboard *springboard = [Springboard new];
[springboard openApplicationWithBundleID:@"com.taobao.sellerplatform"];
NSLog(@"jinru:zuomian");
}
}
修改Makefile
export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=2222
ARCHS = arm64
TARGET := iphone:clang:latest:7.0
INSTALL_TARGET_PROCESSES = SpringBoard
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = taobao
# 引入xm文件
taobao_FILES = Tweak.xm
taobao_CFLAGS = -fobjc-arc
#导入系统的frameworks
taobao_FRAMEWORKS = Foundation AdSupport MobileCoreServices CoreLocation
#头文件
taobao_OBJCFLAGS += -I./
#源文件,通配符的方式引入
taobao_FILES += $(wildcard ./*.m)
include $(THEOS_MAKE_PATH)/tweak.mk
修改完成之后的结构
需要注意的几个配置
#导入系统的frameworks
taobao_FRAMEWORKS = Foundation AdSupport MobileCoreServices CoreLocation
#头文件 表示引入当前文件夹内的所有头文件
taobao_OBJCFLAGS += -I./
#源文件,通配符的方式引入,引入当前文件夹内的所有后缀为.m的源文件
taobao_FILES += $(wildcard ./*.m)