首页
社区
课程
招聘
[原创]【Code_Review】Tweak开发:给调音量增加震动反馈
发表于: 2017-12-4 20:04 9851

[原创]【Code_Review】Tweak开发:给调音量增加震动反馈

2017-12-4 20:04
9851

最近分析一个开源越狱插件--Volbrate,这个插件是给iPhone音量键增加震动的,功能很简单。亮点在于,这个插件提供了在手机设置中做一些功能修改和设定

如图所示:
图片名称

通过搜索知道是利用了PreferenceBundle,theos第9个模板--preference_bundle_modern。只写过tweak,对PreferenceBundle不了解,所以就边分析边学怎么写PreferenceBundle。

有关tweak的编写,资料好多,就不再说了。推荐看狗神的《iOS应用逆向工程》第二版

plist

可知,其作用于springboard

简单来说,就是hook音量键,然后添加震动功能。
关键hook代码:

由代码可知,hook VolumeControl类里面的三个函数。
-(float)volume 获取音量值
-(void)increaseVolume 增加一格音量
-(void)decreaseVolume 减少一格音量

tweak中震动的实现是 调用一个private API :AudioServicesPlaySystemSoundWithVibration
Apple官方并没有这个函数的文档。搜索这个函数,出来最多就是are there apis for custom vibrations in ios。翻译部分内容:
其函数原型:
void AudioServicesPlaySystemSoundWithVibration(SystemSoundID inSystemSoundID, id arg, NSDictionary* vibratePattern)

有意思的是怎么才能写PreferenceBundle,在设置中随时修改某些参数。达到修改tweak功能的作用。比如可以做一个 是否启用hook的开关...
Preference Bundles可以作为iPhone设置中的扩展程序,开发者能编写自己想要的bundles,安装后位于手机/Library/PreferenceBundles/目录下。

Theos的PreferenceBundles模板结合了MobileSubstrate的PreferenceLoader
PreferenceLoaders是MobileSubstrate其中的一个工具,可以把tweak扩展PreferenceBundles注入到iOS的设置中

Tweak.xm不能直接调用PreferenceBundle来获取一些修改后的变量值,而是通过另一种方式,比如从某个plist文件读取,变量的plist文件位于/User/Library/Preferences目录。

PreferenceBundles作为tweak的扩展,直接就在tweak的工程目录新建PreferenceBundles工程
利用theos nic.pl来创建新建PreferenceBunldes工程

如图依次填入,工程名,BundleID,工程前缀
最后的目录结构如图:

这时候tweak的makefile会自动增加一些东西

entry.plist
确定在设置应用中的入口图标,文字等。

Info.plist
这个文件保存工程信息,不需做什么修改

Root.plist
Root.plist可以看做是PreferenceBundle的UI布局文件。其中要跟tweak交互的变量就声明在这里,比如:

entry.plist 和 Root.plist文件的所用的键值详细内容,可参考Preferences specifier plist
Info.plist和Root.plist都在Resources文件夹里。且工程所用到图片,图标文件也保存在Resources目录下。

代码文件
模板会新建两个文件,XXXRootListController.hXXXRootListController.mXXX就是之前设置的工程前缀。
XXXRootListController必须继承PSListController或者PSViewController,且必须实现- (id)specifiers方法,因为PSListController依赖_specifiers来获得metadata和group。
iphonedevwiki的示例代码:

kNameOfPreferencePlist指的就是Root.plist。
这些theos都已经替我们做好了。其他逻辑代码就写在XXXRootListController.m里,可以有多个.m文件。
如何在PreferenceBundle中设置和读取要交互的变量,具体方法可参考iphonedevwiki

在tweak的constructor(%ctor)中完成PreferenceBundle的加载,
Preferences的示例代码:

notificationCallback()获取需要的变量值。
CFNotificationCenterAddObserver()CoreFoundation/CFNotificationCenter.h中的函数,注册监听事件,设置监听相关变量改变后所做的事。

第四个参数:Darwin消息字符串,在Root.plist文件中设置相关变量的消息字符串,然后在Tweak.xm文件中要写上对于的消息字符串。key为PostNotification。当对应的变量改变时,就会发送这个消息字符串。然后监听事件就会接受到消息。
比如在Root.plist文件中:

makefile的编写跟tweak差不多

编译是跟tweak一起编译,不用做其他操作。

如何写PreferenceBundle的中文资料没找到,所以参考的都是英文资料,所以有些地方翻译的不好,大致意思应该明白。写的较为简单,算是基本了解怎么写PreferenceBundle吧。

https://stackoverflow.com/questions/12966467/are-there-apis-for-custom-vibrations-in-ios
https://github.com/derv82/Exchangent/wiki/Part-6:-Preferences,-Preferences,-a-little-Tweak,-and-Heaps-of-More-Preferences
http://sharedinstance.net/2015/02/settings-the-right-way-redux/
http://iphonedevwiki.net/index.php/PreferenceBundles
http://iphonedevwiki.net/index.php/PreferenceLoader

 
 
 
 
 
 
 
 
%hook VolumeControl

    -(void)increaseVolume {
        if(volVibrationOptions == 2) {
            [FeedbackCall vibrateDevice];
        } if(volVibrationOptions == 1 && volMax == YES){
            [FeedbackCall vibrateDevice];
        } else {
            %orig;
        }
    }

    -(void)decreaseVolume {
        if(volVibrationOptions == 2) {
            [FeedbackCall vibrateDevice];
        } if(volVibrationOptions == 1 && volMin == YES){
            [FeedbackCall vibrateDevice];
        } else {
            %orig;
        }
    }

    -(float)volume {
        x = %orig;
        if(x == 0){
            volMin = YES;
        } if(x == 1){
            volMax = YES;
        } if(x > 0 && x < 1) {
            volMin = NO;
            volMax = NO;
        }

    return %orig;
    }
%end
+ (void)vibrateDeviceForTimeLengthIntensity:(CGFloat)timeLength vibrationIntensity:(CGFloat)vibeIntensity {

    NSMutableDictionary* dict = [NSMutableDictionary dictionary];
    NSMutableArray* arr = [NSMutableArray array];

    [arr addObject:[NSNumber numberWithBool: YES]]; //vibrate for time length
    [arr addObject:[NSNumber numberWithInt: timeLength*1000]];

    [arr addObject:[NSNumber numberWithBool: NO]];
    [arr addObject:[NSNumber numberWithInt: 50]];

    [dict setObject: arr forKey:@"VibePattern"];
    [dict setObject:[NSNumber numberWithFloat: vibeIntensity] forKey:@"Intensity"];

    AudioServicesPlaySystemSoundWithVibration(kSystemSoundID_Vibrate, nil, dict);

}
收藏
免费 1
支持
分享
最新回复 (7)
雪    币: 98
活跃值: (364)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
2
黑炭威武~~
2017-12-5 11:56
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
66666,膜拜大神
2017-12-5 11:57
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
给大佬递茶
2017-12-5 12:02
0
雪    币: 199
活跃值: (99)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
小黑屋群众
2017-12-5 12:11
0
雪    币: 298
活跃值: (113)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
小黑屋加一
2017-12-5 15:54
0
雪    币: 6818
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错!!!
2017-12-5 20:36
0
雪    币: 523
活跃值: (278)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
2017-12-19 14:30
0
游客
登录 | 注册 方可回帖
返回
//