9.4 编写tweak

本节的目标是把长按小视频播放窗口的菜单选项给替换成“Save to Disk”和“Copy URL”,并实现相应动作。有了9.3节的原型作为铺垫,这一节就没什么太多可解释的了,咱们直接动手吧。

9.4.1 用Theos新建tweak工程“iOSREWCVideoDownloader”

新建iOSREWCVideoDownloaders工程的命令如下:


hangcom-mba:Documents sam$ /opt/theos/bin/nic.pl 
NIC 2.0 - New Instance Creator
------------------------------
  [1.] iphone/application
  [2.] iphone/cydget
  [3.] iphone/framework
  [4.] iphone/library
  [5.] iphone/notification_center_widget
  [6.] iphone/preference_bundle
  [7.] iphone/sbsettingstoggle
  [8.] iphone/tool
  [9.] iphone/tweak
  [10.] iphone/xpc_service
Choose a Template (required): 9
Project Name (required): iOSREWCVideoDownloader
Package Name [com.yourcompany.iosrewcvideodownloader]: com.iosre.iosrewcvideodownloader
Author/Maintainer Name [sam]: sam
[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.tencent.xin
[iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]: MicroMessenger
Instantiating iphone/tweak in iosrewcvideodownloader/...
 Done.

9.4.2 构造iOSREWCVideoDownloader.h

编辑后的iOSREWCVideoDownloader.h内容如下:


@interface WCContentItem : NSObject
@property (retain, nonatomic) NSMutableArray *mediaList;
@end
@interface WCDataItem : NSObject
@property (retain, nonatomic) WCContentItem *contentObj;
@end
@interface WCUrl : NSObject
@property (retain, nonatomic) NSString *url;
@end
@interface WCMediaItem : NSObject
@property (retain, nonatomic) WCUrl *dataUrl;
- (id)pathForSightData;
@end
@interface WCContentItemViewTemplateNewSight : UIView
- (WCMediaItem *)iOSREMediaItemFromSight;
- (void)iOSREOnSaveToDisk;
- (void)iOSREOnCopyURL;
@end
@interface MMServiceCenter : NSObject
+ (id)defaultCenter;
- (id)getService:(Class)arg1;
@end
@interface WCFacade : NSObject
- (WCDataItem *)getTimelineDataItemOfIndex:(int)arg1;
@end
@interface WCTimeLineViewController : NSObject
- (int)calcDataItemIndex:(int)arg1;
@end
@interface MMTableViewCell : UITableViewCell
@end
@interface MMTableView : UITableView
@end

这个头文件的所有内容均摘自类对应的头文件,构造它的目的仅仅是通过编译,避免出现任何报错信息和警告。

9.4.3 编辑Tweak.xm

编辑后的Tweak.xm内容如下:


#import "iOSREWCVideoDownloader.h"
static MMTableViewCell *iOSRECell;
static MMTableView *iOSREView;
static WCTimeLineViewController *iOSREController;
%hook WCContentItemViewTemplateNewSight
%new
- (WCMediaItem *)iOSREMediaItemFromSight
{
      id responder = self;
      while (![responder isKindOfClass:NSClassFromString(@"WCTimeLineViewController")])
      {
            if ([responder isKindOfClass:NSClassFromString(@"MMTableViewCell")]) iOSRECell = responder;
            else if ([responder isKindOfClass:NSClassFromString(@"MMTableView")]) iOSREView = responder;
            responder = [responder nextResponder];
      }
      iOSREController = responder;
      if (!iOSRECell || !iOSREView || !iOSREController)
      {
            NSLog(@"iOSRE: Failed to get video object.");
            return nil;
      }
      NSIndexPath *indexPath = [iOSREView indexPathForCell:iOSRECell];
      int itemIndex = [iOSREController calcDataItemIndex:[indexPath section]];
      WCFacade *facade = [(MMServiceCenter *)[%c(MMServiceCenter) defaultCenter] getService:[%c(WCFacade) class]];
      WCDataItem *dataItem = [facade getTimelineDataItemOfIndex:itemIndex];
      WCContentItem *contentItem = dataItem.contentObj;
      WCMediaItem *mediaItem = [contentItem.mediaList count] != 0 ? (contentItem.mediaList)[0] : nil;
      return mediaItem;
}
%new
- (void)iOSREOnSaveToDisk
{
      NSString *localPath = [[self iOSREMediaItemFromSight] pathForSightData];
      UISaveVideoAtPathToSavedPhotosAlbum(localPath, nil, nil, nil);
}
%new
- (void)iOSREOnCopyURL
{
      UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
      pasteboard.string = [self iOSREMediaItemFromSight].dataUrl.url;
}
static int iOSRECounter;
- (void)onLongTouch
{
      iOSRECounter++;
      if (iOSRECounter % 2 == 0) return;
      [self becomeFirstResponder];
      UIMenuItem *saveToDiskMenuItem = [[UIMenuItem alloc] initWithTitle:@"Save to Disk" action:@selector(iOSREOnSaveToDisk)];
      UIMenuItem *copyURLMenuItem = [[UIMenuItem alloc] initWithTitle:@"Copy URL" action:@selector(iOSREOnCopyURL)];
      UIMenuController *menuController = [UIMenuController sharedMenuController];
      [menuController setMenuItems:@[saveToDiskMenuItem, copyURLMenuItem]];
      [menuController setTargetRect:CGRectZero inView:self];
      [menuController setMenuVisible:YES animated:YES];
      [saveToDiskMenuItem release];
      [copyURLMenuItem release];
}
%end

9.4.4 编辑Makefile及control

编辑后的Makefile内容如下:


THEOS_DEVICE_IP = iOSIP
TARGET = iphone:latest:8.0
ARCHS = armv7 arm64
include theos/makefiles/common.mk
TWEAK_NAME = iOSREWCVideoDownloader
iOSREWCVideoDownloader_FILES = Tweak.xm
iOSREWCVideoDownloader_FRAMEWORKS = UIKit
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
      install.exec "killall -9 MicroMessenger"

编辑后的control内容如下:


Package: com.iosre.iosrewcvideodownloader
Name: iOSREWCVideoDownloader
Depends: mobilesubstrate, firmware (>= 8.0)
Version: 1.0
Architecture: iphoneos-arm
Description: Play with Sight!
Maintainer: sam
Author: sam
Section: Tweaks
Homepage: http://bbs.iosre.com

9.4.5 测试

将写好的tweak编译打包安装到iOS后,打开微信,长按小视频播放窗口,就会弹出自定义菜单,如图9-29所示。

图9-29 自定义菜单

点击“Save to Disk”,这个小视频会被保存到相册中,如图9-30所示。

点击“Copy URL”,然后到OPlayer Lite(或任意支持在线视频播放的App)中打开这个网址,如图9-31所示。

图9-30 把小视频保存到相册

图9-31 在OPlayer Lite中播放在线mp4

所有功能均可正常工作,本章任务达成!