├── .gitignore ├── Example ├── LinkMapParser.py ├── Podfile ├── Podfile.lock ├── RangersAppLog.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── OCDemo.xcscheme ├── RangersAppLog │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── BDAdapter.h │ ├── BDAdapter.m │ ├── BDBaseTableViewController.h │ ├── BDBaseTableViewController.m │ ├── BDDemoViewController.h │ ├── BDDemoViewController.m │ ├── BDFeedLoader.h │ ├── BDFeedLoader.m │ ├── BDFeedModel.h │ ├── BDFeedModel.m │ ├── BDResultViewController.h │ ├── BDResultViewController.m │ ├── Background │ │ ├── BackgroundDownload.h │ │ ├── BackgroundDownload.m │ │ ├── BackgroundTask.h │ │ └── BackgroundTask.m │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── Location │ │ ├── LocationTracker.h │ │ └── LocationTracker.m │ ├── Music │ │ ├── BDPlayer.h │ │ ├── BDPlayer.m │ │ ├── test_song.jpg │ │ └── test_song.mp3 │ ├── Push │ │ ├── LocalPush.h │ │ └── LocalPush.m │ ├── RangersAppLog.entitlements │ └── main.m ├── SwiftDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift └── sdk_size_info.json ├── LICENSE ├── ObjCExample ├── ObjCExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── ObjCExample.xcscheme ├── ObjCExample.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ObjCExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── cenci.imageset │ │ │ ├── Contents.json │ │ │ └── after Guido Reni - Portrait of Beatrice Cenci.jpg │ │ ├── 山花烂漫国画.imageset │ │ │ ├── Contents.json │ │ │ └── 山花烂漫国画.jpg │ │ ├── 果树国画.imageset │ │ │ ├── Contents.json │ │ │ └── 果树国画.jpg │ │ ├── 梅花国画.imageset │ │ │ ├── Contents.json │ │ │ └── 梅花国画.jpg │ │ ├── 猫国画.imageset │ │ │ ├── Contents.json │ │ │ └── 猫国画.jpeg │ │ ├── 竹子国画.imageset │ │ │ ├── Contents.json │ │ │ └── 竹子国画.jpg │ │ ├── 荷花国画.imageset │ │ │ ├── Contents.json │ │ │ └── 荷花国画.jpeg │ │ ├── 迎客松国画.imageset │ │ │ ├── Contents.json │ │ │ └── 迎客松国画.jpg │ │ └── 鸟国画.imageset │ │ │ ├── Contents.json │ │ │ └── 鸟国画.jpeg │ ├── BDAdapter.h │ ├── BDAdapter.m │ ├── BDColors.h │ ├── BDColors.m │ ├── BDDemoTextCell.h │ ├── BDDemoTextCell.m │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Controllers │ │ ├── BDTestIntroducerViewController.h │ │ ├── BDTestIntroducerViewController.m │ │ ├── BDTesterControllers.h │ │ ├── BDTesterIntroducerBase.h │ │ ├── BDTesterIntroducerBase.m │ │ ├── ConfigViewer │ │ │ ├── BDConfigViewerCell.h │ │ │ ├── BDConfigViewerCell.m │ │ │ ├── BDConfigViewerCell.xib │ │ │ ├── BDTesterSDKConfigViewer.h │ │ │ └── BDTesterSDKConfigViewer.m │ │ ├── FinderTester │ │ │ ├── BDFinderTesterImp.h │ │ │ └── BDFinderTesterImp.m │ │ ├── H5Tester │ │ │ ├── BDNativeH5TesterImpViewController.h │ │ │ ├── BDNativeH5TesterImpViewController.m │ │ │ └── h5_page.html │ │ ├── HookCompatibilityTester │ │ │ ├── BDAspectTesterImp.h │ │ │ ├── BDAspectTesterImp.m │ │ │ ├── BDHookCompatibilityTesterSuite.h │ │ │ ├── BDHookCompatibilityTesterSuite.m │ │ │ ├── BDReactiveObjCTesterImp.h │ │ │ └── BDReactiveObjCTesterImp.m │ │ ├── New Group │ │ │ ├── NewCaseViewController.h │ │ │ └── NewCaseViewController.m │ │ ├── PickerTester │ │ │ ├── BDTestPickerViewController.h │ │ │ └── BDTestPickerViewController.m │ │ ├── PlayerTester │ │ │ ├── BDPlayerTesterImp.h │ │ │ └── BDPlayerTesterImp.m │ │ ├── ProfileAPITester │ │ │ ├── BDProfileAPITesterImp.h │ │ │ ├── BDProfileAPITesterImp.m │ │ │ ├── BDProfileAPITester_UI.h │ │ │ ├── BDProfileAPITester_UI.m │ │ │ └── BDProfileAPITester_UI.xib │ │ ├── UICompatibilityTester │ │ │ ├── BDUICompatibilityTesterSuite.h │ │ │ ├── BDUICompatibilityTesterSuite.m │ │ │ ├── IGListTester │ │ │ │ ├── BDChinesePaintingSectionController.h │ │ │ │ ├── BDChinesePaintingSectionController.m │ │ │ │ ├── BDIGListKitTesterImp.h │ │ │ │ ├── BDIGListKitTesterImp.m │ │ │ │ ├── IGListTesterModel.h │ │ │ │ └── IGListTesterModel.m │ │ │ ├── OverlapWindowTester │ │ │ │ ├── BDOverlapWindowTesterImp.h │ │ │ │ └── BDOverlapWindowTesterImp.m │ │ │ └── SubviewToWindow │ │ │ │ ├── BDSubviewToWindowTesterImp.h │ │ │ │ └── BDSubviewToWindowTesterImp.m │ │ └── UITrackTester │ │ │ ├── BDUITrackTesterImp.h │ │ │ ├── BDUITrackTesterImp.m │ │ │ └── BDUITrackTesterImp.xib │ ├── Info.plist │ ├── Model │ │ ├── BDAbstractModel.h │ │ ├── BDAbstractModel.m │ │ ├── BDConfigViewModel.h │ │ ├── BDConfigViewModel.m │ │ ├── BDFeedModel.h │ │ ├── BDFeedModel.m │ │ ├── BDFeedModelDictionary.h │ │ ├── BDFeedModelDictionary.m │ │ ├── BDModelSectionHeader.h │ │ └── BDModelSectionHeader.m │ └── main.m └── Podfile ├── README.md ├── RangersAppLog.bundle ├── Assets.car ├── Info.plist └── _CodeSignature │ ├── CodeDirectory │ ├── CodeRequirements │ ├── CodeRequirements-1 │ ├── CodeResources │ └── CodeSignature ├── RangersAppLog.podspec └── RangersAppLog └── Classes ├── CAID └── libRangersAppLog_CAID.a ├── Core ├── BDAutoTrack+Game.h ├── BDAutoTrack+GameTrack.h ├── BDAutoTrack+LaunchFrom.h ├── BDAutoTrack+OhayooGameTrack.h ├── BDAutoTrack+Profile.h ├── BDAutoTrack+SharedInstance.h ├── BDAutoTrack+Special.h ├── BDAutoTrack.h ├── BDAutoTrackCacheRemover.h ├── BDAutoTrackConfig+AppLog.h ├── BDAutoTrackConfig.h ├── BDAutoTrackNotifications.h ├── BDAutoTrackSchemeHandler.h ├── BDCommonDefine.h ├── BDCommonEnumDefine.h ├── RangersAppLog.h ├── RangersAppLog.m ├── RangersAppLogCore.h └── libRangersAppLog_Core_union.a ├── Host ├── CN │ ├── BDAutoTrackURLHostItemCN.h │ └── libRangersAppLog_Host_CN.a ├── SG │ ├── BDAutoTrackURLHostItemSG.h │ └── libRangersAppLog_Host_SG.a └── VA │ ├── BDAutoTrackURLHostItemVA.h │ └── libRangersAppLog_Host_VA.a ├── Log └── libRangersAppLog_Debugger.a ├── Picker ├── RangersAppLogPicker.h └── libRangersAppLog_Picker.a ├── UITracker ├── BDKeyWindowTracker.h ├── RangersAppLogUITrack.h ├── UIBarButtonItem+TrackInfo.h ├── UIView+TrackInfo.h ├── UIViewController+TrackInfo.h └── libRangersAppLog_UITracker.a └── Unique ├── BDAutoTrackIDFA.h └── libRangersAppLog_Unique.a /.gitignore: -------------------------------------------------------------------------------- 1 | *.m 2 | *.c 3 | *.mm 4 | 5 | RangersAppLog/Classes/Core/* 6 | !RangersAppLog/Classes/Core/Header 7 | !RangersAppLog/Classes/Core/*.h 8 | !RangersAppLog/Classes/Core/*.m 9 | !RangersAppLog/Classes/Core/*.mm 10 | !RangersAppLog/Classes/Core/*.c 11 | 12 | RangersAppLog/Classes/Log/* 13 | !RangersAppLog/Classes/Log/*.h 14 | !RangersAppLog/Classes/Log/*.m 15 | !RangersAppLog/Classes/Log/*.mm 16 | !RangersAppLog/Classes/Log/*.c 17 | 18 | RangersAppLog/Classes/Picker/* 19 | !RangersAppLog/Classes/Picker/Header 20 | !RangersAppLog/Classes/Picker/*.h 21 | !RangersAppLog/Classes/Picker/*.m 22 | !RangersAppLog/Classes/Picker/*.mm 23 | !RangersAppLog/Classes/Picker/*.c 24 | 25 | RangersAppLog/Classes/Unique/* 26 | !RangersAppLog/Classes/Unique/Public 27 | !RangersAppLog/Classes/Unique/*.h 28 | !RangersAppLog/Classes/Unique/*.m 29 | !RangersAppLog/Classes/Unique/*.mm 30 | !RangersAppLog/Classes/Unique/*.c 31 | 32 | RangersAppLog/Classes/UITracker/* 33 | !RangersAppLog/Classes/UITracker/Header 34 | !RangersAppLog/Classes/UITracker/*.h 35 | !RangersAppLog/Classes/UITracker/*.m 36 | !RangersAppLog/Classes/UITracker/*.mm 37 | !RangersAppLog/Classes/UITracker/*.c 38 | 39 | !*.a 40 | ios-arch-iphone 41 | testSDKSpace 42 | 43 | # Xcode 44 | # 45 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 46 | 47 | # cocoapods 48 | Pods 49 | Pods/ 50 | 51 | ## Build generated 52 | build/ 53 | DerivedData/ 54 | 55 | ## Various settings 56 | *.pbxuser 57 | !default.pbxuser 58 | *.mode1v3 59 | !default.mode1v3 60 | *.mode2v3 61 | !default.mode2v3 62 | *.perspectivev3 63 | !default.perspectivev3 64 | xcuserdata/ 65 | 66 | ## Other 67 | *.moved-aside 68 | *.xccheckout 69 | *.xcscmblueprint 70 | 71 | ## Obj-C/Swift specific 72 | *.hmap 73 | *.ipa 74 | *.dSYM.zip 75 | *.dSYM 76 | *.zip 77 | Gemfile 78 | Gemfile.lock 79 | Podfile.lock 80 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/bytedance/cocoapods_sdk_source_repo.git' 2 | 3 | install! 'cocoapods', 4 | :disable_input_output_paths => true, 5 | :generate_multiple_pod_projects => true, 6 | :warn_for_multiple_pod_sources => false 7 | platform :ios, '10.0' 8 | 9 | # require 'bd_pod_extentions' 10 | # plugin 'cocoapods-bytedance-transform' 11 | # bd_use_app("public") 12 | 13 | #use_frameworks! 14 | def common 15 | pod 'RangersAppLog',:path => '../' 16 | # pod 'RangersAppLog/Picker','5.1.6-rc.1' 17 | # pod 'RangersKit', "0.9.1.1-binary", :subspecs => [ 18 | # "Service", 19 | # "Reachability", 20 | # "Defaults", 21 | # "IDFA", 22 | # "Security", 23 | # "Foundation", 24 | # "Timer", 25 | # "Keychain", 26 | # "Database", 27 | # "Decorator", 28 | # ] 29 | end 30 | target 'OCDemo' do 31 | common 32 | end 33 | 34 | target 'SwiftDemo' do 35 | common 36 | end 37 | 38 | post_install do |installer| 39 | installer.pods_project.targets.each do |target| 40 | target.build_configurations.each do |config| 41 | config.build_settings['ENABLE_BITCODE'] = 'NO' 42 | if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 9.0 43 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' 44 | end 45 | end 46 | end 47 | ## for generate_multiple_pod_projects = true 48 | installer.generated_projects.each do |project| 49 | project.targets.each do |target| 50 | target.build_configurations.each do |config| 51 | config.build_settings['ENABLE_BITCODE'] = 'NO' 52 | if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 9.0 53 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' 54 | end 55 | end 56 | end 57 | end 58 | 59 | end 60 | 61 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - RangersAppLog (5.4.0): 3 | - RangersAppLog/Core (= 5.4.0) 4 | - RangersAppLog/Log (= 5.4.0) 5 | - RangersAppLog/Picker (= 5.4.0) 6 | - RangersAppLog/UITracker (= 5.4.0) 7 | - RangersAppLog/Unique (= 5.4.0) 8 | - RangersAppLog/Core (5.4.0) 9 | - RangersAppLog/Log (5.4.0): 10 | - RangersAppLog/Core 11 | - RangersAppLog/Picker (5.4.0): 12 | - RangersAppLog/Log 13 | - RangersAppLog/UITracker 14 | - RangersAppLog/UITracker (5.4.0): 15 | - RangersAppLog/Core 16 | - RangersAppLog/Unique (5.4.0): 17 | - RangersAppLog/Core 18 | 19 | DEPENDENCIES: 20 | - RangersAppLog (from `../`) 21 | 22 | EXTERNAL SOURCES: 23 | RangersAppLog: 24 | :path: "../" 25 | 26 | SPEC CHECKSUMS: 27 | RangersAppLog: 78e7eaaaa8ee0c7023642cf34e44401bb56527c5 28 | 29 | PODFILE CHECKSUM: bb9f217a8b88f3ef78b600e5fb43610e58077d36 30 | 31 | COCOAPODS: 1.9.2 32 | -------------------------------------------------------------------------------- /Example/RangersAppLog.xcodeproj/xcshareddata/xcschemes/OCDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Example/RangersAppLog/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Example/RangersAppLog/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "BDDemoViewController.h" 11 | #import "BDAdapter.h" 12 | #import "BackgroundTask.h" 13 | #import "LocationTracker.h" 14 | #import "BackgroundDownload.h" 15 | #import "LocalPush.h" 16 | 17 | #import 18 | 19 | @interface AppDelegate () 20 | 21 | @end 22 | 23 | @implementation AppDelegate 24 | 25 | - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 26 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 27 | return YES; 28 | } 29 | 30 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 31 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 32 | [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum]; 33 | [[LocalPush sharedInstance] registerUserNotification]; 34 | application.applicationIconBadgeNumber = 0; 35 | 36 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 37 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[BDDemoViewController new]]; 38 | self.window.rootViewController = nav; 39 | [self.window makeKeyAndVisible]; 40 | 41 | 42 | if ([BackgroundTask backgroundAbility] && [LocationTracker checkLocationAbility]) { 43 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 44 | [[LocationTracker sharedInstance] requestAuthorization]; 45 | }); 46 | } 47 | 48 | return YES; 49 | } 50 | 51 | - (BOOL)application:(UIApplication *)application 52 | openURL:(NSURL *)url 53 | options:(NSDictionary *)options { 54 | 55 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 56 | 57 | if ([[BDAutoTrackSchemeHandler sharedHandler] handleURL:url appID:@"159486" scene:nil]) { 58 | return YES; 59 | } 60 | 61 | return NO; 62 | } 63 | 64 | - (void)applicationDidBecomeActive:(UIApplication *)application { 65 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 66 | } 67 | 68 | - (void)applicationWillResignActive:(UIApplication *)application { 69 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 70 | } 71 | 72 | - (void)applicationWillEnterForeground:(UIApplication *)application { 73 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 74 | } 75 | 76 | - (void)applicationDidEnterBackground:(UIApplication *)application { 77 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 78 | } 79 | 80 | - (void)applicationWillTerminate:(UIApplication *)application { 81 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 82 | } 83 | 84 | #pragma mark - background fetch 85 | /// background fetch 30s 86 | - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { 87 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 88 | 89 | NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; 90 | NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; 91 | 92 | NSURL *url = [[NSURL alloc] initWithString:@"https://www.baidu.com"]; 93 | NSURLSessionDataTask *task = [session dataTaskWithURL:url 94 | completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 95 | completionHandler(UIBackgroundFetchResultNewData); 96 | }]; 97 | 98 | // 开始任务 99 | [task resume]; 100 | } 101 | 102 | #pragma mark - backgroundDonwload 103 | 104 | - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler { 105 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 106 | [[BackgroundDownload sharedInstance] addBackgroundHandler:completionHandler forSession:identifier]; 107 | } 108 | 109 | #pragma mark - 远程通知 110 | 111 | - (void)set { 112 | 113 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 114 | } 115 | 116 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { 117 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:application.applicationState]; 118 | completionHandler(UIBackgroundFetchResultNewData); 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/RangersAppLog/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/RangersAppLog/BDAdapter.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAdapter.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | @class BDFeedModel; 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDAdapter : NSObject 15 | 16 | @property (nonatomic, strong) NSMutableArray *events; 17 | 18 | + (instancetype)sharedInstance; 19 | 20 | + (void)startAppLog; 21 | 22 | + (void)eventV3:(NSString *)event params:(nullable NSDictionary *)params; 23 | 24 | + (id)ABTestValue; 25 | 26 | + (void)logout; 27 | 28 | + (void)login; 29 | 30 | + (void)trackKeyWindow:(UIWindow *)keyWindow; 31 | 32 | + (BOOL)handleURL:(NSURL *)URL scene:(nullable id)scene; 33 | 34 | + (void)trackCallback:(NSString *)method state:(NSInteger)state; 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDBaseTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDBaseTableViewController.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class BDFeedModel; 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDBaseTableViewController : UITableViewController 15 | 16 | @property (nonatomic, strong) NSArray *feedList; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDBaseTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDBaseTableViewController.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDBaseTableViewController.h" 10 | #import "BDAdapter.h" 11 | #import "BDFeedLoader.h" 12 | #import "BDFeedModel.h" 13 | 14 | static NSString * const CellReuseIdentifier = @"UITableViewCell_"; 15 | 16 | @interface BDBaseTableViewController () 17 | 18 | @end 19 | 20 | @implementation BDBaseTableViewController 21 | 22 | - (void)loadView { 23 | [super loadView]; 24 | self.feedList = @[]; 25 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellReuseIdentifier]; 26 | } 27 | 28 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 29 | return 1; 30 | } 31 | 32 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 33 | return self.feedList.count; 34 | } 35 | 36 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 37 | BDFeedModel *model = [self.feedList objectAtIndex:indexPath.row]; 38 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellReuseIdentifier]; 39 | if (!cell) { 40 | cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:CellReuseIdentifier]; 41 | } 42 | cell.textLabel.text = [NSString stringWithFormat:@"%zd: %@",(NSInteger)(indexPath.row + 1),model.title]; 43 | 44 | return cell; 45 | } 46 | 47 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 48 | return 44; 49 | } 50 | 51 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 52 | BDFeedModel *model = [self.feedList objectAtIndex:indexPath.row]; 53 | 54 | if (model.actionBlock) { 55 | model.actionBlock(); 56 | } else if (model.nextVCName.length) { 57 | UIViewController *vc = [NSClassFromString(model.nextVCName) new]; 58 | if (vc) { 59 | [self.navigationController pushViewController:vc animated:YES]; 60 | } 61 | } 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDDemoViewController.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDBaseTableViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDDemoViewController : BDBaseTableViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDDemoViewController.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDDemoViewController.h" 10 | #import "BDFeedModel.h" 11 | #import "BDFeedLoader.h" 12 | 13 | @interface BDDemoViewController () 14 | 15 | @end 16 | 17 | @implementation BDDemoViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | self.feedList = [BDFeedLoader loadDemoFeedList]; 22 | self.navigationItem.title = @"Demo"; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDFeedLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedLoader.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class BDFeedModel; 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface BDFeedLoader : NSObject 16 | 17 | + (NSArray *)loadDemoFeedList; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDFeedLoader.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedLoader.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDFeedLoader.h" 10 | #import "BDFeedModel.h" 11 | #import "BDAdapter.h" 12 | #import "BDPlayer.h" 13 | #import "LocationTracker.h" 14 | #import "BackgroundDownload.h" 15 | #import "BackgroundTask.h" 16 | #import "LocalPush.h" 17 | 18 | @implementation BDFeedLoader 19 | 20 | + (NSArray *)loadDemoFeedList { 21 | NSMutableArray *array = [NSMutableArray array]; 22 | 23 | [array addObject:({ 24 | BDFeedModel *model = [BDFeedModel new]; 25 | model.title = @"Result"; 26 | model.nextVCName = @"BDResultViewController"; 27 | 28 | model; 29 | })]; 30 | 31 | [array addObject:({ 32 | BDFeedModel *model = [BDFeedModel new]; 33 | model.title = @"open rangersapplog app"; 34 | model.actionBlock = ^{ 35 | NSString *url = @"rangersapplo://rangersapplog"; 36 | NSURL *URL = [NSURL URLWithString:url]; 37 | if ([[UIApplication sharedApplication] canOpenURL:URL]) { 38 | if (@available(iOS 10.0, *)) { 39 | [[UIApplication sharedApplication] openURL:URL options:@{} completionHandler:^(BOOL success) { 40 | NSLog(@"Open success"); 41 | }]; 42 | } else { 43 | 44 | } 45 | } 46 | }; 47 | 48 | model; 49 | })]; 50 | 51 | 52 | [array addObject:({ 53 | BDFeedModel *model = [BDFeedModel new]; 54 | model.title = @"开始播放,开启后台"; 55 | model.actionBlock = ^{ 56 | [[BDPlayer sharedInstance] play]; 57 | }; 58 | 59 | model; 60 | })]; 61 | 62 | [array addObject:({ 63 | BDFeedModel *model = [BDFeedModel new]; 64 | model.title = @"停止播放"; 65 | model.actionBlock = ^{ 66 | [[BDPlayer sharedInstance] stop]; 67 | }; 68 | 69 | model; 70 | })]; 71 | 72 | [array addObject:({ 73 | BDFeedModel *model = [BDFeedModel new]; 74 | model.title = @"开启一次后台定位"; 75 | model.actionBlock = ^{ 76 | [LocationTracker sharedInstance].enabled = YES; 77 | }; 78 | 79 | model; 80 | })]; 81 | 82 | [array addObject:({ 83 | BDFeedModel *model = [BDFeedModel new]; 84 | model.title = @"开启定位区域"; 85 | model.actionBlock = ^{ 86 | [[LocationTracker sharedInstance] startMonitor]; 87 | }; 88 | 89 | model; 90 | })]; 91 | 92 | [array addObject:({ 93 | BDFeedModel *model = [BDFeedModel new]; 94 | model.title = @"关闭定位区域"; 95 | model.actionBlock = ^{ 96 | [[LocationTracker sharedInstance] startMonitor]; 97 | }; 98 | 99 | model; 100 | })]; 101 | 102 | [array addObject:({ 103 | BDFeedModel *model = [BDFeedModel new]; 104 | model.title = @"开启一个后台下载"; 105 | model.actionBlock = ^{ 106 | [BackgroundDownload sharedInstance].backgroundDownloadEnabled = YES; 107 | }; 108 | 109 | model; 110 | })]; 111 | 112 | [array addObject:({ 113 | BDFeedModel *model = [BDFeedModel new]; 114 | model.title = @"开启一个10s后台任务"; 115 | model.actionBlock = ^{ 116 | [BackgroundTask sharedInstance].enabled = YES; 117 | }; 118 | 119 | model; 120 | })]; 121 | 122 | [array addObject:({ 123 | BDFeedModel *model = [BDFeedModel new]; 124 | model.title = @"前台本地通知"; 125 | model.actionBlock = ^{ 126 | [[LocalPush sharedInstance] scheduleLocalNotification]; 127 | }; 128 | 129 | model; 130 | })]; 131 | 132 | [array addObject:({ 133 | BDFeedModel *model = [BDFeedModel new]; 134 | model.title = @"开启一个后台本地通知"; 135 | model.actionBlock = ^{ 136 | [LocalPush sharedInstance].enabled = YES; 137 | }; 138 | 139 | model; 140 | })]; 141 | 142 | return array; 143 | } 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDFeedModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedModel.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDFeedModel : NSObject 14 | 15 | @property (nonatomic, copy) NSString *title; 16 | @property (nonatomic, copy) NSString *nextVCName; 17 | @property (nonatomic, copy) dispatch_block_t actionBlock; 18 | 19 | @property (nonatomic, assign) NSInteger state; 20 | @property (nonatomic, assign) NSInteger eventIndex; 21 | @property (nonatomic, copy) NSString *methodName; 22 | + (instancetype)modelWithIndex:(NSInteger)index 23 | method:(NSString *)method 24 | state:(NSInteger)state; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDFeedModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedModel.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDFeedModel.h" 10 | 11 | @implementation BDFeedModel 12 | 13 | + (instancetype)modelWithIndex:(NSInteger)index 14 | method:(NSString *)method 15 | state:(NSInteger)state { 16 | BDFeedModel *model = [self new]; 17 | model.eventIndex = index; 18 | model.methodName = method; 19 | model.state = state; 20 | 21 | return model; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDResultViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDResultViewController.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDBaseTableViewController.h" 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDResultViewController : BDBaseTableViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/RangersAppLog/BDResultViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDResultViewController.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDResultViewController.h" 10 | #import "BDAdapter.h" 11 | #import "BDFeedModel.h" 12 | 13 | static NSString * const CellReuseIdentifier = @"UITableViewCell_"; 14 | 15 | @interface BDResultViewController () 16 | 17 | @end 18 | 19 | @implementation BDResultViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | self.feedList = [[BDAdapter sharedInstance].events copy]; 24 | self.navigationItem.title = @"Result"; 25 | } 26 | 27 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 28 | BDFeedModel *model = [self.feedList objectAtIndex:indexPath.row]; 29 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellReuseIdentifier]; 30 | if (!cell) { 31 | cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:CellReuseIdentifier]; 32 | } 33 | cell.textLabel.text = [NSString stringWithFormat:@"%zd:%zd:%@",model.eventIndex, model.state ,model.methodName]; 34 | 35 | return cell; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Background/BackgroundDownload.h: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundDownload.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/7. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BackgroundDownload : NSObject 14 | 15 | @property (nonatomic, assign) BOOL backgroundDownloadEnabled; 16 | 17 | + (instancetype)sharedInstance; 18 | 19 | - (void)addBackgroundHandler:(dispatch_block_t)completionHandler forSession:(NSString *)identifier; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Background/BackgroundDownload.m: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundDownload.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/7. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BackgroundDownload.h" 10 | #import 11 | 12 | @interface BackgroundDownload () 13 | 14 | @property (nonatomic, strong) NSURLSession *session; 15 | @property (nonatomic, strong) NSMutableDictionary *handlers; 16 | 17 | 18 | @end 19 | 20 | @implementation BackgroundDownload 21 | 22 | - (void)dealloc { 23 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 24 | } 25 | 26 | - (void)onDidEnterBackground { 27 | if (!self.backgroundDownloadEnabled) { 28 | return; 29 | } 30 | self.backgroundDownloadEnabled = NO; 31 | [self beginBackgroundDownload]; 32 | } 33 | 34 | - (instancetype)init { 35 | self = [super init]; 36 | if (self) { 37 | NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.applog.background"]; 38 | self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; 39 | self.handlers = [NSMutableDictionary new]; 40 | [[NSNotificationCenter defaultCenter] addObserver:self 41 | selector:@selector(onDidEnterBackground) 42 | name:UIApplicationDidEnterBackgroundNotification 43 | object:nil]; 44 | } 45 | 46 | return self; 47 | } 48 | 49 | + (instancetype)sharedInstance { 50 | static BackgroundDownload *sharedInstance = nil; 51 | static dispatch_once_t onceToken; 52 | dispatch_once(&onceToken, ^{ 53 | sharedInstance = [self new]; 54 | }); 55 | 56 | return sharedInstance; 57 | } 58 | 59 | - (void)beginBackgroundDownload { 60 | NSString *downloadURLString = @"https://github.com/bytedance/RangersAppLog/blob/feature-demo/Example/RangersAppLog/Music/test_song.mp3"; 61 | NSURL* downloadURL = [NSURL URLWithString:downloadURLString]; 62 | NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; 63 | NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:request]; 64 | task.taskDescription = @"com.applog.background"; 65 | [task resume]; 66 | } 67 | 68 | - (void)addBackgroundHandler:(dispatch_block_t)completionHandler forSession:(NSString *)identifier { 69 | if (identifier.length > 0 && completionHandler) { 70 | if ([self.handlers objectForKey:identifier]) { 71 | NSLog(@"error"); 72 | } 73 | [self.handlers setValue:completionHandler forKey:identifier]; 74 | } 75 | } 76 | 77 | #pragma mark - NSURLSessionDelegate 78 | 79 | - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { 80 | NSString *identifier = session.configuration.identifier; 81 | if (identifier.length > 0) { 82 | dispatch_block_t handler = [self.handlers objectForKey:identifier]; 83 | if (handler) { 84 | [self.handlers removeObjectForKey:identifier]; 85 | handler(); 86 | } 87 | } 88 | } 89 | 90 | #pragma mark - NSURLSessionDownloadDelegate 91 | 92 | - (void)URLSession:(NSURLSession *)session 93 | downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { 94 | 95 | } 96 | 97 | 98 | - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask 99 | didWriteData:(int64_t)bytesWritten 100 | totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { 101 | 102 | } 103 | 104 | - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask 105 | didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { 106 | 107 | } 108 | 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Background/BackgroundTask.h: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundTask.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/6. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BackgroundTask : NSObject 14 | 15 | @property (nonatomic, assign) BOOL enabled; 16 | 17 | + (instancetype)sharedInstance; 18 | 19 | - (void)beginBackgroundTask; 20 | - (void)endBackgroundTask; 21 | 22 | + (BOOL)backgroundAbility; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Background/BackgroundTask.m: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundTask.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/6. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BackgroundTask.h" 10 | #import 11 | 12 | #define BDWeakSelf __weak typeof(self) wself = self 13 | #define BDStrongSelf __strong typeof(wself) self = wself 14 | 15 | 16 | @interface BackgroundTask () 17 | 18 | @property (assign) UIBackgroundTaskIdentifier taskID; 19 | 20 | @end 21 | 22 | @implementation BackgroundTask 23 | 24 | - (void)dealloc { 25 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 26 | } 27 | 28 | - (void)onDidEnterBackground { 29 | if (!self.enabled) { 30 | return; 31 | } 32 | self.enabled = NO; 33 | [self beginBackgroundTask]; 34 | BDWeakSelf; 35 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 36 | BDStrongSelf; 37 | [self endBackgroundTask]; 38 | }); 39 | } 40 | 41 | - (instancetype)init { 42 | self = [super init]; 43 | if (self) { 44 | self.taskID = UIBackgroundTaskInvalid; 45 | [[NSNotificationCenter defaultCenter] addObserver:self 46 | selector:@selector(onDidEnterBackground) 47 | name:UIApplicationDidEnterBackgroundNotification 48 | object:nil]; 49 | } 50 | 51 | return self; 52 | } 53 | 54 | + (instancetype)sharedInstance { 55 | static BackgroundTask *_sharedInstance = nil; 56 | static dispatch_once_t onceToken; 57 | dispatch_once(&onceToken, ^{ 58 | _sharedInstance = [self new]; 59 | }); 60 | 61 | return _sharedInstance; 62 | } 63 | 64 | - (void)beginBackgroundTask { 65 | if (self.taskID != UIBackgroundTaskInvalid) { 66 | return; 67 | } 68 | BDWeakSelf; 69 | self.taskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 70 | dispatch_async(dispatch_get_main_queue(), ^{ 71 | BDStrongSelf; 72 | [self endBackgroundTask]; 73 | }); 74 | }]; 75 | } 76 | 77 | - (void)endBackgroundTask { 78 | if (self.taskID != UIBackgroundTaskInvalid) { 79 | return; 80 | } 81 | [[UIApplication sharedApplication] endBackgroundTask:self.taskID]; 82 | self.taskID = UIBackgroundTaskInvalid; 83 | } 84 | 85 | + (BOOL)backgroundAbility { 86 | UIBackgroundRefreshStatus status = [UIApplication sharedApplication].backgroundRefreshStatus; 87 | return status == UIBackgroundRefreshStatusAvailable; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | RangersAppLog 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleURLTypes 22 | 23 | 24 | CFBundleTypeRole 25 | Editor 26 | CFBundleURLName 27 | com.applog.test 28 | CFBundleURLSchemes 29 | 30 | applog 31 | 32 | 33 | 34 | CFBundleVersion 35 | 1 36 | LSApplicationQueriesSchemes 37 | 38 | rangersapplog 39 | 40 | LSRequiresIPhoneOS 41 | 42 | NSLocationAlwaysAndWhenInUseUsageDescription 43 | 需要定位权限 44 | NSLocationAlwaysUsageDescription 45 | 需要定位权限 46 | NSLocationUsageDescription 47 | 需要定位权限 48 | NSLocationWhenInUseUsageDescription 49 | 需要定位权限 50 | UIBackgroundModes 51 | 52 | audio 53 | bluetooth-central 54 | bluetooth-peripheral 55 | external-accessory 56 | fetch 57 | location 58 | processing 59 | remote-notification 60 | voip 61 | 62 | UILaunchStoryboardName 63 | LaunchScreen 64 | UIRequiredDeviceCapabilities 65 | 66 | armv7 67 | 68 | UISupportedInterfaceOrientations 69 | 70 | Privacy - Location When In Use Usage Description 71 | UIInterfaceOrientationPortrait 72 | UIInterfaceOrientationLandscapeLeft 73 | UIInterfaceOrientationLandscapeRight 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Location/LocationTracker.h: -------------------------------------------------------------------------------- 1 | // 2 | // LocationTracker.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/6. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LocationTracker : NSObject 14 | 15 | @property (nonatomic, assign) BOOL enabled; 16 | 17 | + (instancetype)sharedInstance; 18 | 19 | - (void)startMonitor; 20 | - (void)stopMonitor ; 21 | 22 | - (void)requestAuthorization; 23 | 24 | + (BOOL)checkLocationAbility; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Location/LocationTracker.m: -------------------------------------------------------------------------------- 1 | // 2 | // LocationTracker.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/6. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "LocationTracker.h" 10 | #import 11 | #import 12 | #import "BDAdapter.h" 13 | #import "BackgroundTask.h" 14 | 15 | @interface LocationTracker () 16 | 17 | @property (nonatomic, strong) CLLocationManager *locationManager; 18 | @property (nonatomic, strong) BackgroundTask *task; 19 | @property (nonatomic, assign) CLLocationCoordinate2D center; 20 | 21 | 22 | @end 23 | 24 | @implementation LocationTracker 25 | 26 | - (void)dealloc { 27 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 28 | } 29 | 30 | - (void)onDidEnterBackground { 31 | if (!self.enabled) { 32 | return; 33 | } 34 | self.enabled = NO; 35 | [self startBackgroundLocation]; 36 | } 37 | 38 | - (void)onWillEnterForeground { 39 | [self stopLocation]; 40 | [self stopMonitor]; 41 | } 42 | 43 | - (instancetype)init { 44 | self = [super init]; 45 | if (self) { 46 | CLLocationManager *locationManager = [CLLocationManager new]; 47 | locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; 48 | locationManager.allowsBackgroundLocationUpdates = YES; 49 | locationManager.pausesLocationUpdatesAutomatically = NO; 50 | locationManager.delegate = self; 51 | locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; 52 | locationManager.distanceFilter = 100; 53 | 54 | self.locationManager = locationManager; 55 | self.task = [BackgroundTask new]; 56 | [[NSNotificationCenter defaultCenter] addObserver:self 57 | selector:@selector(onDidEnterBackground) 58 | name:UIApplicationDidEnterBackgroundNotification 59 | object:nil]; 60 | [[NSNotificationCenter defaultCenter] addObserver:self 61 | selector:@selector(onWillEnterForeground) 62 | name:UIApplicationWillEnterForegroundNotification 63 | object:nil]; 64 | self.enabled = NO; 65 | } 66 | 67 | return self; 68 | } 69 | 70 | + (instancetype)sharedInstance { 71 | static LocationTracker *sharedInstance = nil; 72 | static dispatch_once_t onceToken; 73 | dispatch_once(&onceToken, ^{ 74 | sharedInstance = [self new]; 75 | }); 76 | 77 | return sharedInstance; 78 | } 79 | 80 | - (void)startBackgroundLocation { 81 | [self startLocation]; 82 | } 83 | 84 | - (void)startLocation { 85 | [self requestAuthorization]; 86 | [self.locationManager startUpdatingLocation]; 87 | /// 500 米一次 88 | [self.locationManager startMonitoringSignificantLocationChanges]; 89 | } 90 | 91 | - (CLCircularRegion *)monitorRegion { 92 | 93 | CLLocationDistance distance = 20; 94 | CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:self.center 95 | radius:distance 96 | identifier:@"com.applog.location"]; 97 | region.notifyOnExit = YES; 98 | region.notifyOnEntry = YES; 99 | 100 | return region; 101 | } 102 | 103 | - (void)startMonitor { 104 | if (![CLLocationManager isMonitoringAvailableForClass:CLCircularRegion.class]) { 105 | return; 106 | } 107 | CLLocationManager *locationManager = self.locationManager; 108 | [locationManager startMonitoringForRegion:[self monitorRegion]]; 109 | } 110 | 111 | - (void)stopMonitor { 112 | if (![CLLocationManager isMonitoringAvailableForClass:CLCircularRegion.class]) { 113 | return; 114 | } 115 | 116 | CLLocationManager *locationManager = self.locationManager; 117 | [locationManager stopMonitoringForRegion:[self monitorRegion]]; 118 | } 119 | 120 | - (void)requestAuthorization { 121 | [self.locationManager requestAlwaysAuthorization]; 122 | } 123 | 124 | - (void)stopLocation { 125 | [self.locationManager stopUpdatingLocation]; 126 | } 127 | 128 | #pragma mark - CLLocationManagerDelegate 129 | 130 | - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { 131 | [manager stopMonitoringForRegion:region]; 132 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:[UIApplication sharedApplication].applicationState]; 133 | } 134 | - (void)locationManager:(CLLocationManager *)manager 135 | didExitRegion:(CLRegion *)region { 136 | [manager stopMonitoringForRegion:region]; 137 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:[UIApplication sharedApplication].applicationState]; 138 | } 139 | 140 | - (void)locationManager:(CLLocationManager *)manager 141 | didUpdateLocations:(NSArray *)locations { 142 | CLLocation *location = [locations lastObject]; 143 | self.center = location.coordinate; 144 | } 145 | 146 | #pragma mark - Tool 147 | 148 | + (BOOL)checkLocationAbility { 149 | if ([CLLocationManager locationServicesEnabled] == NO) { 150 | return NO; 151 | } 152 | 153 | CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus]; 154 | if( authorizationStatus == kCLAuthorizationStatusDenied 155 | || authorizationStatus == kCLAuthorizationStatusRestricted){ 156 | return NO; 157 | } 158 | 159 | return YES; 160 | } 161 | 162 | @end 163 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Music/BDPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDPlayer.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/6. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDPlayer : NSObject 14 | 15 | + (instancetype)sharedInstance; 16 | 17 | - (void)play; 18 | - (void)pause; 19 | - (void)stop; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Music/BDPlayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDPlayer.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/6. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDPlayer.h" 10 | #import 11 | #import 12 | #import 13 | 14 | #define BDWeakSelf __weak typeof(self) wself = self 15 | #define BDStrongSelf __strong typeof(wself) self = wself 16 | 17 | 18 | @interface BDPlayer () 19 | 20 | @property (nonatomic, strong) AVAudioPlayer *player; 21 | 22 | @property (nonatomic, assign) BOOL infoShown; 23 | @property (nonatomic, assign) BOOL handlerRegistered; 24 | 25 | @end 26 | 27 | @implementation BDPlayer 28 | 29 | - (void)dealloc { 30 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 31 | } 32 | 33 | - (void)onSessionInterruption:(NSNotification *)not { 34 | NSLog(@"%@",not.userInfo); 35 | [self pause]; 36 | } 37 | 38 | - (void)onWillTerminate { 39 | [[UIApplication sharedApplication] endReceivingRemoteControlEvents]; 40 | } 41 | 42 | - (instancetype)init { 43 | self = [super init]; 44 | if (self) { 45 | [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 46 | AVAudioSession *session = [AVAudioSession sharedInstance]; 47 | [session setActive:YES error:nil]; 48 | [session setCategory:AVAudioSessionCategoryPlayback error:nil]; 49 | 50 | NSString *musicPath = [[NSBundle mainBundle] pathForResource:@"test_song" ofType:@"mp3"]; 51 | NSURL *url = [[NSURL alloc] initFileURLWithPath:musicPath]; 52 | 53 | NSError *error; 54 | AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; 55 | [player prepareToPlay]; 56 | player.numberOfLoops = -1; 57 | self.player = player; 58 | 59 | [[NSNotificationCenter defaultCenter] addObserver:self 60 | selector:@selector(onWillTerminate) 61 | name:UIApplicationWillTerminateNotification 62 | object:nil]; 63 | 64 | [[NSNotificationCenter defaultCenter] addObserver:self 65 | selector:@selector(onSessionInterruption:) 66 | name:AVAudioSessionInterruptionNotification 67 | object:nil]; 68 | } 69 | 70 | return self; 71 | } 72 | 73 | + (instancetype)sharedInstance { 74 | static BDPlayer *sharedInstance = nil; 75 | static dispatch_once_t onceToken; 76 | dispatch_once(&onceToken, ^{ 77 | sharedInstance = [self new]; 78 | }); 79 | 80 | return sharedInstance; 81 | } 82 | 83 | - (void)play { 84 | if (self.player.isPlaying) { 85 | return; 86 | } 87 | [self.player play]; 88 | [self showPlayingInfo]; 89 | [self registerRemoteControlEventHandler]; 90 | } 91 | 92 | - (void)pause { 93 | if (self.player.isPlaying) { 94 | [self.player pause]; 95 | } 96 | } 97 | 98 | - (void)stop { 99 | if (self.player.isPlaying) { 100 | [self.player stop]; 101 | } 102 | } 103 | 104 | - (void)playAndPause { 105 | if (self.player.isPlaying) { 106 | [self.player pause]; 107 | } else { 108 | [self.player play]; 109 | } 110 | } 111 | 112 | -(void)showPlayingInfo { 113 | if (self.infoShown) { 114 | return; 115 | } 116 | self.infoShown = YES; 117 | NSMutableDictionary *songDict=[NSMutableDictionary dictionary]; 118 | [songDict setObject:@"Test" forKey:MPMediaItemPropertyTitle]; 119 | [songDict setObject:@"Test" forKey:MPMediaItemPropertyArtist]; 120 | [songDict setObject:@(240) forKeyedSubscript:MPMediaItemPropertyPlaybackDuration]; 121 | UIImage *image = [UIImage imageNamed:@"test_song.jpg"]; 122 | MPMediaItemArtwork *imageItem= [[MPMediaItemArtwork alloc] initWithBoundsSize:image.size requestHandler:^UIImage *(CGSize size) { 123 | return image; 124 | }]; 125 | [songDict setObject:imageItem forKey:MPMediaItemPropertyArtwork]; 126 | [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songDict]; 127 | } 128 | 129 | - (void)registerRemoteControlEventHandler { 130 | if (self.handlerRegistered) { 131 | return; 132 | } 133 | self.handlerRegistered = YES; 134 | 135 | MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; 136 | commandCenter.playCommand.enabled = YES; 137 | BDWeakSelf; 138 | [commandCenter.playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) { 139 | BDStrongSelf; 140 | [self play]; 141 | return MPRemoteCommandHandlerStatusSuccess; 142 | }]; 143 | commandCenter.pauseCommand.enabled = YES; 144 | [commandCenter.pauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) { 145 | BDStrongSelf; 146 | [self pause]; 147 | return MPRemoteCommandHandlerStatusSuccess; 148 | }]; 149 | commandCenter.previousTrackCommand.enabled = YES; 150 | [commandCenter.previousTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) { 151 | BDStrongSelf; 152 | [self play]; 153 | return MPRemoteCommandHandlerStatusSuccess; 154 | }]; 155 | commandCenter.nextTrackCommand.enabled = YES; 156 | [commandCenter.nextTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) { 157 | BDStrongSelf; 158 | [self play]; 159 | return MPRemoteCommandHandlerStatusSuccess; 160 | }]; 161 | 162 | commandCenter.togglePlayPauseCommand.enabled = YES; 163 | [commandCenter.togglePlayPauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) { 164 | BDStrongSelf; 165 | [self playAndPause]; 166 | return MPRemoteCommandHandlerStatusSuccess; 167 | }]; 168 | } 169 | 170 | @end 171 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Music/test_song.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/Example/RangersAppLog/Music/test_song.jpg -------------------------------------------------------------------------------- /Example/RangersAppLog/Music/test_song.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/Example/RangersAppLog/Music/test_song.mp3 -------------------------------------------------------------------------------- /Example/RangersAppLog/Push/LocalPush.h: -------------------------------------------------------------------------------- 1 | // 2 | // LocalPush.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/8. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LocalPush : NSObject 14 | 15 | @property (nonatomic, assign) BOOL enabled; 16 | 17 | + (instancetype)sharedInstance; 18 | 19 | - (void)registerUserNotification; 20 | - (void)scheduleLocalNotification; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /Example/RangersAppLog/Push/LocalPush.m: -------------------------------------------------------------------------------- 1 | // 2 | // LocalPush.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/11/8. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import "LocalPush.h" 10 | #import 11 | #import 12 | #import "BDAdapter.h" 13 | 14 | @interface LocalPush () 15 | 16 | @end 17 | 18 | @implementation LocalPush 19 | 20 | - (void)dealloc { 21 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 22 | } 23 | 24 | - (void)onDidEnterBackground { 25 | if (!self.enabled) { 26 | return; 27 | } 28 | self.enabled = NO; 29 | [self scheduleLocalNotification]; 30 | } 31 | 32 | - (instancetype)init { 33 | self = [super init]; 34 | if (self) { 35 | [[NSNotificationCenter defaultCenter] addObserver:self 36 | selector:@selector(onDidEnterBackground) 37 | name:UIApplicationDidEnterBackgroundNotification 38 | object:nil]; 39 | } 40 | 41 | return self; 42 | } 43 | 44 | + (instancetype)sharedInstance { 45 | static LocalPush *_sharedInstance = nil; 46 | static dispatch_once_t onceToken; 47 | dispatch_once(&onceToken, ^{ 48 | _sharedInstance = [self new]; 49 | }); 50 | 51 | return _sharedInstance; 52 | } 53 | 54 | - (void)registerUserNotification { 55 | [UNUserNotificationCenter currentNotificationCenter].delegate = self; 56 | UNAuthorizationOptions opt = UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert ; 57 | [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:opt 58 | completionHandler:^(BOOL granted, NSError* error) { 59 | }]; 60 | } 61 | 62 | - (void)scheduleLocalNotification { 63 | UNMutableNotificationContent *content = [UNMutableNotificationContent new]; 64 | content.title = @"title"; 65 | content.subtitle = @"subtitle"; 66 | content.body = @"body"; 67 | content.badge = @1; 68 | content.launchImageName = @"test_song.jpg"; 69 | content.sound = [UNNotificationSound defaultSound];; 70 | 71 | UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO]; 72 | 73 | UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"scheduleLocalNotification" 74 | content:content 75 | trigger:trigger]; 76 | 77 | [[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications]; 78 | [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request 79 | withCompletionHandler:^(NSError * error) { 80 | }]; 81 | } 82 | 83 | #pragma mark - UNUserNotificationCenterDelegate 84 | 85 | /// if the application is in the foreground 86 | - (void)userNotificationCenter:(UNUserNotificationCenter *)center 87 | willPresentNotification:(UNNotification *)notification 88 | withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler { 89 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:[UIApplication sharedApplication].applicationState]; 90 | completionHandler(UNNotificationPresentationOptionAlert); 91 | } 92 | 93 | - (void)userNotificationCenter:(UNUserNotificationCenter *)center 94 | didReceiveNotificationResponse:(UNNotificationResponse *)response 95 | withCompletionHandler:(void(^)(void))completionHandler { 96 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:[UIApplication sharedApplication].applicationState]; 97 | completionHandler(); 98 | } 99 | 100 | - (void)userNotificationCenter:(UNUserNotificationCenter *)center 101 | openSettingsForNotification:(UNNotification *)notification { 102 | [BDAdapter trackCallback:NSStringFromSelector(_cmd) state:[UIApplication sharedApplication].applicationState]; 103 | } 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /Example/RangersAppLog/RangersAppLog.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Example/RangersAppLog/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/9. 6 | // Copyright © 2019 Bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Example/SwiftDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftDemo 4 | // 5 | // Created by bob on 2020/2/26. 6 | // Copyright © 2020 Bytedance. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RangersAppLog 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | 18 | let window = UIWindow() 19 | self.window = window 20 | 21 | 22 | let nav = UINavigationController(rootViewController: ViewController()) 23 | window.rootViewController = nav 24 | window.makeKeyAndVisible() 25 | 26 | 27 | return true 28 | } 29 | 30 | func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { 31 | 32 | return false 33 | } 34 | 35 | 36 | 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /Example/SwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/SwiftDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/SwiftDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/SwiftDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/SwiftDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/SwiftDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftDemo 4 | // 5 | // Created by bob on 2020/2/26. 6 | // Copyright © 2020 Bytedance. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 12 | 13 | var tableView:UITableView! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | self.view.backgroundColor = .white 18 | //创建表格视图 19 | self.tableView = UITableView(frame: self.view.frame, style:.plain) 20 | //创建一个重用的单元格 21 | self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") 22 | self.view.addSubview(self.tableView!) 23 | self.tableView.delegate = self 24 | self.tableView.dataSource = self 25 | } 26 | 27 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 28 | return 3 29 | } 30 | 31 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 32 | let reuse = tableView.dequeueReusableCell(withIdentifier: "Cell") 33 | let cell = reuse == nil ? reuse! : UITableViewCell() 34 | cell.textLabel?.text = "cell \(indexPath.row)" 35 | 36 | return cell 37 | } 38 | 39 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 40 | print("选中项的indexPath为:\(indexPath)") 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Bytedance Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcodeproj/xcshareddata/xcschemes/ObjCExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 35 | 36 | 37 | 38 | 40 | 46 | 47 | 48 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | 67 | 73 | 74 | 75 | 76 | 82 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "BDAdapter.h" 11 | #import 12 | #import "BDTestIntroducerViewController.h" 13 | #import 14 | 15 | 16 | /// 只输出Log,不会抑制异常继续抛出 17 | void globalNSExceptionHandler(NSException *exception) { 18 | NSLog(@"\n名字:%@",exception.name); 19 | NSLog(@"\n原因:%@",exception.reason); 20 | NSLog(@"\n用户信息:%@",exception.userInfo); 21 | NSLog(@"\n栈内存地址:%@",exception.callStackReturnAddresses); 22 | // NSLog(@"栈描述:%@",exception.callStackSymbols); 23 | } 24 | 25 | @interface AppDelegate () 26 | 27 | @end 28 | 29 | @implementation AppDelegate 30 | 31 | #pragma mark - leftcycle 32 | - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 33 | NSLog(@"%@ %zd",NSStringFromSelector(_cmd),application.applicationState); 34 | return YES; 35 | } 36 | 37 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 38 | // Override point for customization after application launch. 39 | NSSetUncaughtExceptionHandler(&globalNSExceptionHandler); 40 | [BDAdapter startAutoTracker]; 41 | 42 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 43 | BDTestIntroducerViewController *intro = [[BDTestIntroducerViewController alloc] init]; 44 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:intro]; 45 | self.window.rootViewController = nav; 46 | [self.window makeKeyAndVisible]; 47 | 48 | [BDAdapter trackKeyWindow:self.window]; 49 | 50 | [BDAutoTrack eventV3:@"play_video" params:nil]; 51 | return YES; 52 | } 53 | 54 | - (void)applicationDidBecomeActive:(UIApplication *)application { 55 | NSLog(@"%@ %zd", NSStringFromSelector(_cmd), [UIApplication sharedApplication].applicationState); 56 | } 57 | 58 | - (void)applicationWillResignActive:(UIApplication *)application { 59 | NSLog(@"%@ %zd", NSStringFromSelector(_cmd), [UIApplication sharedApplication].applicationState); 60 | } 61 | 62 | - (void)applicationWillEnterForeground:(UIApplication *)application { 63 | NSLog(@"%@ %zd", NSStringFromSelector(_cmd), [UIApplication sharedApplication].applicationState); 64 | } 65 | 66 | - (void)applicationDidEnterBackground:(UIApplication *)application { 67 | NSLog(@"%@ %zd", NSStringFromSelector(_cmd), [UIApplication sharedApplication].applicationState); 68 | } 69 | 70 | - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { 71 | // if([BDAdapter handleURL:url scene:nil]) { 72 | // return YES; 73 | // } 74 | 75 | /// your handle code 76 | 77 | return NO; 78 | } 79 | 80 | 81 | #ifdef __IPHONE_13_0 82 | //- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0)) { 83 | // UISceneConfiguration *config = [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; 84 | // config.delegateClass = [BDSceneDelegate class]; 85 | // return config; 86 | //} 87 | #endif 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/cenci.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "after Guido Reni - Portrait of Beatrice Cenci.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/cenci.imageset/after Guido Reni - Portrait of Beatrice Cenci.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/cenci.imageset/after Guido Reni - Portrait of Beatrice Cenci.jpg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/山花烂漫国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "山花烂漫国画.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/山花烂漫国画.imageset/山花烂漫国画.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/山花烂漫国画.imageset/山花烂漫国画.jpg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/果树国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "果树国画.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/果树国画.imageset/果树国画.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/果树国画.imageset/果树国画.jpg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/梅花国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "梅花国画.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/梅花国画.imageset/梅花国画.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/梅花国画.imageset/梅花国画.jpg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/猫国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "猫国画.jpeg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/猫国画.imageset/猫国画.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/猫国画.imageset/猫国画.jpeg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/竹子国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "竹子国画.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/竹子国画.imageset/竹子国画.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/竹子国画.imageset/竹子国画.jpg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/荷花国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "荷花国画.jpeg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/荷花国画.imageset/荷花国画.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/荷花国画.imageset/荷花国画.jpeg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/迎客松国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "迎客松国画.jpg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/迎客松国画.imageset/迎客松国画.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/迎客松国画.imageset/迎客松国画.jpg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/鸟国画.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "鸟国画.jpeg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Assets.xcassets/鸟国画.imageset/鸟国画.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/ObjCExample/ObjCExample/Assets.xcassets/鸟国画.imageset/鸟国画.jpeg -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/BDAdapter.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAdapter.h 3 | // BDAutoTracker_Example 4 | // 5 | // Created by bob on 2019/8/19. 6 | // Copyright © 2019 ByteDance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class BDFeedModel; 14 | 15 | @interface BDAdapter : NSObject 16 | 17 | + (void)startAutoTracker; 18 | 19 | + (void)trackKeyWindow:(UIWindow *)keyWindow; 20 | 21 | + (BOOL)eventV3:(NSString *)event params:(NSDictionary *)params; 22 | 23 | + (BOOL)handleURL:(NSURL *)URL scene:(nullable id)scene; 24 | 25 | + (void)addTestButtonInWindow:(UIWindow *)window; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/BDColors.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDColors.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/24. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDColors : NSObject 14 | 15 | + (instancetype)sharedInstance; 16 | 17 | - (UIColor *)lightGreen; 18 | - (UIColor *)lightRed; 19 | - (UIColor *)lightBlue; 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/BDColors.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDColors.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/24. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDColors.h" 10 | 11 | @implementation BDColors 12 | 13 | + (instancetype)sharedInstance { 14 | static BDColors *shared; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | shared = [self new]; 18 | }); 19 | return shared; 20 | } 21 | 22 | #pragma mark - colors 23 | - (UIColor *)lightGreen { 24 | return [UIColor colorWithRed:100.0/255 green:155.0/255 blue:100.0/255 alpha:1.0]; 25 | } 26 | 27 | - (UIColor *)lightRed { 28 | return [UIColor colorWithRed:155.0/255 green:100.0/255 blue:100.0/255 alpha:1.0]; 29 | } 30 | 31 | - (UIColor *)lightBlue { 32 | return [UIColor colorWithRed:100.0/255 green:100.0/255 blue:155.0/255 alpha:1.0]; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/BDDemoTextCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDDemoTextCell.h 3 | // BDAutoTracker_Example 4 | // 5 | // Created by bob on 2019/4/17. 6 | // Copyright © 2019 ByteDance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDDemoTextCell : UITableViewCell 14 | 15 | @property (nonatomic, strong, readonly) UILabel *extraLabel; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/BDDemoTextCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDDemoTextCell.m 3 | // BDAutoTracker_Example 4 | // 5 | // Created by bob on 2019/4/17. 6 | // Copyright © 2019 ByteDance. All rights reserved. 7 | // 8 | 9 | #import "BDDemoTextCell.h" 10 | 11 | @interface BDDemoTextCell () 12 | 13 | @property (nonatomic, strong) UILabel *extraLabel; 14 | 15 | @end 16 | 17 | @implementation BDDemoTextCell 18 | 19 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 20 | if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 21 | UILabel *extraLabel = [[UILabel alloc] initWithFrame:self.contentView.bounds]; 22 | extraLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 23 | extraLabel.textAlignment = NSTextAlignmentCenter; 24 | extraLabel.textColor = [UIColor blueColor]; 25 | [self.contentView addSubview: extraLabel]; 26 | self.extraLabel = extraLabel; 27 | } 28 | 29 | return self; 30 | } 31 | 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/BDTestIntroducerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDTestIntroducerViewController.h 3 | // rangersAppLogObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/17. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDTesterIntroducerBase.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | /// APP的首页。介绍各个测试项,点击不同测试项可以进入不同测试场景。 15 | @interface BDTestIntroducerViewController : BDTesterIntroducerBase 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/BDTestIntroducerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDTestIntroducerViewController.m 3 | // rangersAppLogObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/17. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 各测试项的分流入口 8 | 9 | #import "BDFeedModel.h" 10 | #import "BDFeedModelDictionary.h" 11 | #import "BDTesterControllers.h" 12 | #import 13 | //#import 14 | #import 15 | 16 | @interface BDTestIntroducerViewController () 17 | 18 | @end 19 | 20 | static NSString *cellReuseID = @"testIntro_1"; 21 | 22 | @implementation BDTestIntroducerViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | self.title = @"导航首页"; 27 | 28 | // BDAutoTrackAuthorizationStatus status = [BDAutoTrackIDFA authorizationStatus]; 29 | [BDAutoTrackIDFA requestAuthorizationWithHandler:^(BDAutoTrackAuthorizationStatus status) { 30 | NSLog(@"%@", @(status)); 31 | }]; 32 | NSString *idfa = [ASIdentifierManager.sharedManager advertisingIdentifier].UUIDString; 33 | NSLog(@"%@", idfa); 34 | } 35 | 36 | #pragma mark - getter 37 | // 重写父类的getter 38 | - (NSMutableArray *)feedModels { 39 | NSMutableArray *models = [super feedModels]; 40 | if (!models) { 41 | __weak typeof(self) wself = self; 42 | NSArray *tmpModels = @[ 43 | [[BDModelSectionHeader alloc] initWithSectionName:@"功能测试" desc:@""], 44 | [[BDFeedModel alloc] initWithTitle:@"测试DataFinder功能" actionBlock:^{ 45 | __auto_type vc = [[BDFinderTesterImp alloc] init]; 46 | [wself.navigationController pushViewController:vc animated:YES]; 47 | }], 48 | [[BDFeedModel alloc] initWithTitle:@"测试DataPlayer功能" actionBlock:^{ 49 | __auto_type vc = [[BDPlayerTesterImp alloc] init]; 50 | [wself.navigationController pushViewController:vc animated:YES]; 51 | }], 52 | [[BDFeedModel alloc] initWithTitle:@"测试Profile API" actionBlock:^{ 53 | __auto_type vc = [[BDProfileAPITesterImp alloc] init]; 54 | [wself.navigationController pushViewController:vc animated:YES]; 55 | }], 56 | [[BDFeedModel alloc] initWithTitle:@"测试圈选" actionBlock:^{ 57 | __auto_type vc = [[BDUITrackTesterImp alloc] init]; 58 | vc.shouldTestPicker = true; 59 | [wself.navigationController pushViewController:vc animated:YES]; 60 | }], 61 | [[BDFeedModel alloc] initWithTitle:@"测试无埋点" actionBlock:^{ 62 | __auto_type vc = [[BDUITrackTesterImp alloc] initWithNibName:@"BDUITrackTesterImp" bundle:NSBundle.mainBundle]; 63 | vc.shouldTestPicker = false; 64 | [wself.navigationController pushViewController:vc animated:YES]; 65 | }], 66 | 67 | [[BDModelSectionHeader alloc] initWithSectionName:@"兼容性测试" desc:@""], 68 | [[BDFeedModel alloc] initWithTitle:@"测试UI库兼容性" actionBlock:^{ 69 | __auto_type vc = [[BDUICompatibilityTesterSuite alloc] init]; 70 | [wself.navigationController pushViewController:vc animated:YES]; 71 | }], 72 | [[BDFeedModel alloc] initWithTitle:@"测试Hook库兼容性" actionBlock:^{ 73 | __auto_type vc = [[BDHookCompatibilityTesterSuite alloc] init]; 74 | [wself.navigationController pushViewController:vc animated:YES]; 75 | }], 76 | [[BDFeedModel alloc] initWithTitle:@"测试竞品SDK兼容性" actionBlock:^{}], 77 | 78 | [[BDModelSectionHeader alloc] initWithSectionName:@"H5相关测试" desc:@""], 79 | [[BDFeedModel alloc] initWithTitle:@"内嵌H5页面走原生上报" actionBlock:^{ 80 | __auto_type vc = [[BDNativeH5TesterImpViewController alloc] init]; 81 | [wself.navigationController pushViewController:vc animated:YES]; 82 | }], 83 | 84 | [[BDModelSectionHeader alloc] initWithSectionName:@"查看SDK配置参数" desc:@""], 85 | [[BDFeedModel alloc] initWithTitle:@"查看初始化配置" actionBlock:^{ 86 | __auto_type vc = [[BDTesterSDKConfigViewer alloc] init]; 87 | [wself.navigationController pushViewController:vc animated:YES]; 88 | }] 89 | ]; 90 | 91 | models = [NSMutableArray arrayWithArray:tmpModels]; 92 | [self setFeedModels:models]; 93 | } 94 | return models; 95 | } 96 | 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/BDTesterControllers.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDTesterControllers.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #ifndef BDTesterControllers_h 10 | #define BDTesterControllers_h 11 | 12 | #import "BDTesterIntroducerBase.h" 13 | 14 | #import "BDTestIntroducerViewController.h" 15 | 16 | #import "BDHookCompatibilityTesterSuite.h" 17 | #import "BDAspectTesterImp.h" 18 | #import "BDReactiveObjcTesterImp.h" 19 | 20 | #import "BDUICompatibilityTesterSuite.h" 21 | #import "BDIGListKitTesterImp.h" 22 | #import "BDOverlapWindowTesterImp.h" 23 | 24 | #import "BDUITrackTesterImp.h" 25 | 26 | #import "BDPlayerTesterImp.h" 27 | #import "BDFinderTesterImp.h" 28 | 29 | #import "BDTestPickerViewController.h" 30 | 31 | #import "BDTesterSDKConfigViewer.h" 32 | 33 | #import "BDProfileAPITesterImp.h" 34 | 35 | #import "BDNativeH5TesterImpViewController.h" 36 | 37 | #endif /* BDTesterControllers_h */ 38 | 39 | 40 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/BDTesterIntroducerBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDTesterIntroducerBase.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/22. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDFeedModelDictionary.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | /// TesterIntroducer的基类,本身不实例化。 15 | /// 包括一个多section的tableView,用于介绍各种Tester VC。 16 | @interface BDTesterIntroducerBase : UIViewController 17 | @property (strong, nonatomic) UITableView *tableView; 18 | @property (strong, nonatomic) BDFeedModelDictionary *modelObject; 19 | @property (strong, nonatomic) NSMutableArray *feedModels; 20 | 21 | /// override to register a different cell 22 | - (void)registerTableViewCell; 23 | 24 | /// override to provide a different cell reuse id 25 | /// usually no need to override this 26 | - (NSString *)cellReuseID1; 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/BDTesterIntroducerBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDTesterIntroducerBase.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/22. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDTesterIntroducerBase.h" 10 | #import "BDFeedModel.h" 11 | #import "BDModelSectionHeader.h" 12 | 13 | @interface BDTesterIntroducerBase () 14 | 15 | @end 16 | 17 | 18 | @implementation BDTesterIntroducerBase 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | self.tableView = [[UITableView alloc] init]; 22 | self.tableView.frame = self.view.bounds; 23 | self.tableView.delegate = self; 24 | self.tableView.dataSource = self; 25 | [self registerTableViewCell]; 26 | [self.view addSubview:self.tableView]; 27 | 28 | self.view.backgroundColor = UIColor.whiteColor; 29 | // self.title = ; 30 | } 31 | 32 | - (void)registerTableViewCell { 33 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:[self cellReuseID1]]; 34 | } 35 | 36 | #pragma mark - table view delegate 37 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 38 | return [self.modelObject numSections]; 39 | } 40 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 41 | return [self.modelObject numOfItemsInSection:section]; 42 | } 43 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 44 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[self cellReuseID1]]; 45 | BDFeedModel *model = [[self.modelObject itemsForSection:indexPath.section] objectAtIndex:indexPath.row]; 46 | cell.textLabel.text = model.title; 47 | if (model.actionBlock) { 48 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 49 | } 50 | return cell; 51 | } 52 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 53 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 54 | // handle VC push 55 | BDFeedModel *model = [[self.modelObject itemsForSection:indexPath.section] objectAtIndex:indexPath.row]; 56 | if (model.actionBlock) { 57 | model.actionBlock(); 58 | } 59 | } 60 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 61 | BDModelSectionHeader *sectionDevider = [self.modelObject sectionDeviderForSection:section]; 62 | return sectionDevider.sectionName; 63 | } 64 | 65 | #pragma mark - getter 66 | 67 | - (BDFeedModelDictionary *)modelObject { 68 | if (!_modelObject) { 69 | _modelObject = [[BDFeedModelDictionary alloc] initWithModelArray:self.feedModels]; 70 | } 71 | return _modelObject; 72 | } 73 | 74 | //- (NSMutableArray *)feedModels { 75 | // if (!_feedModels) { 76 | //// __weak typeof(self) wself = self; 77 | // NSArray *tmpModels = @[]; 78 | // 79 | // _feedModels = [NSMutableArray arrayWithArray:tmpModels]; 80 | // } 81 | // return _feedModels; 82 | //} 83 | 84 | 85 | #pragma mark - cell reuse ID 86 | - (NSString *)cellReuseID1 { 87 | return @"base_cellReuseID1"; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ConfigViewer/BDConfigViewerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDConfigViewerCell.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDConfigViewerCell : UITableViewCell 14 | @property (weak, nonatomic) IBOutlet UILabel *configKeyLabel; 15 | @property (weak, nonatomic) IBOutlet UITextField *configValueTextField; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ConfigViewer/BDConfigViewerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDConfigViewerCell.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDConfigViewerCell.h" 10 | 11 | @implementation BDConfigViewerCell 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | 18 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 19 | [super setSelected:selected animated:animated]; 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ConfigViewer/BDConfigViewerCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ConfigViewer/BDTesterSDKConfigViewer.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDTesterSDKConfigViewer.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDTesterIntroducerBase.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDTesterSDKConfigViewer : BDTesterIntroducerBase 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ConfigViewer/BDTesterSDKConfigViewer.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDTesterSDKConfigViewer.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDTesterSDKConfigViewer.h" 10 | #import "BDConfigViewModel.h" 11 | #import "BDFeedModel.h" 12 | 13 | @interface BDTesterSDKConfigViewer () 14 | 15 | @end 16 | 17 | @implementation BDTesterSDKConfigViewer 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | self.feedModels = [NSMutableArray arrayWithObjects: 22 | [[BDFeedModel alloc] initWithTitle:@"" actionBlock:nil], 23 | nil]; 24 | } 25 | 26 | - (void)registerTableViewCell { 27 | [super registerTableViewCell]; 28 | // UINib *nib = [UINib nibWithNibName:@"BDConfigViewerCell" bundle:nil]; 29 | // [self.tableView registerNib:nib forCellReuseIdentifier:[self cellReuseID1]]; 30 | } 31 | 32 | #pragma mark - table view delegate 33 | 34 | 35 | /* 36 | #pragma mark - Navigation 37 | 38 | // In a storyboard-based application, you will often want to do a little preparation before navigation 39 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 40 | // Get the new view controller using [segue destinationViewController]. 41 | // Pass the selected object to the new view controller. 42 | } 43 | */ 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/FinderTester/BDFinderTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDFinderTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDTesterIntroducerBase.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDFinderTesterImp : BDTesterIntroducerBase 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/FinderTester/BDFinderTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDFinderTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDFinderTesterImp.h" 10 | #import "BDFeedModel.h" 11 | #import "BDAdapter.h" 12 | #import 13 | 14 | @interface BDFinderTesterImp () 15 | 16 | 17 | @end 18 | 19 | static NSString *cellReuseID = @"finderTester_1"; 20 | 21 | @implementation BDFinderTesterImp 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | self.title = @"Finder场景测试页"; 26 | 27 | NSDictionary *sharedParams = @{ 28 | @"from": @"testerFinder" 29 | }; 30 | 31 | self.feedModels = [NSMutableArray arrayWithObjects: 32 | [[BDFeedModel alloc] initWithTitle:@"注册" actionBlock:^{ 33 | [BDAutoTrack eventV3:@"user_register" params:sharedParams]; 34 | }], 35 | [[BDFeedModel alloc] initWithTitle:@"登录" actionBlock:^{ 36 | [BDAutoTrack eventV3:@"user_login" params:sharedParams]; 37 | }], 38 | [[BDFeedModel alloc] initWithTitle:@"绑定社交账号" actionBlock:^{ 39 | [BDAutoTrack eventV3:@"user_bind_social_account" params:sharedParams]; 40 | }], 41 | [[BDFeedModel alloc] initWithTitle:@"打开视频" actionBlock:^{ 42 | [BDAutoTrack eventV3:@"user_open_video" params:sharedParams]; 43 | }], 44 | [[BDFeedModel alloc] initWithTitle:@"点赞" actionBlock:^{ 45 | [BDAutoTrack eventV3:@"user_like" params:sharedParams]; 46 | }], 47 | [[BDFeedModel alloc] initWithTitle:@"评论" actionBlock:^{ 48 | [BDAutoTrack eventV3:@"user_comment" params:sharedParams]; 49 | }], 50 | [[BDFeedModel alloc] initWithTitle:@"分享" actionBlock:^{ 51 | [BDAutoTrack eventV3:@"user_share" params:sharedParams]; 52 | }], 53 | [[BDFeedModel alloc] initWithTitle:@"创建订单" actionBlock:^{ 54 | [BDAutoTrack eventV3:@"user_place_order" params:sharedParams]; 55 | }], 56 | [[BDFeedModel alloc] initWithTitle:@"支付" actionBlock:^{ 57 | [BDAutoTrack eventV3:@"user_payment" params:sharedParams]; 58 | }], 59 | [[BDFeedModel alloc] initWithTitle:@"购买虚拟物品" actionBlock:^{ 60 | [BDAutoTrack eventV3:@"user_purchase_virtual_item" params:sharedParams]; 61 | }], 62 | nil 63 | ]; 64 | } 65 | 66 | 67 | @end 68 | 69 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/H5Tester/BDNativeH5TesterImpViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDNativeH5TesterImpViewController.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/9/23. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /// H5页面打通无埋点. 14 | /// App内嵌的H5元素UI内的无埋点事件,通过App的无埋点上报渠道采集上报,从而和App关联起来。 15 | /// 1. UIWebView 16 | /// - H5页面要允许注入JS 17 | /// - UIWebView需要设置delegate且delegate不为nil 18 | /// @code 19 | /// UIWebView *webView; 20 | /// webView.delegate = delegate; 21 | /// @endcode 22 | /// 2. WKWebView 23 | /// - WKWebView需要通过initWithFrame: configuration:方法初始化 24 | /// - 如果自己重写初始化方法,请务必调用[[WKWebView alloc] initWithFrame: configuration:]方法 25 | /// @code 26 | /// WKWebView *webView = [[WKWebView alloc] initWithFrame:frame configuration:config]; 27 | /// @endcode 28 | /// 上述操作完成之后再调用[webView loadRequest:request]; 29 | @interface BDNativeH5TesterImpViewController : UIViewController 30 | 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/H5Tester/BDNativeH5TesterImpViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDNativeH5TesterImpViewController.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/9/23. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDNativeH5TesterImpViewController.h" 10 | #import 11 | 12 | @interface BDNativeH5TesterImpViewController () 13 | 14 | @property (strong, nonatomic) WKWebView *webView; 15 | 16 | @end 17 | 18 | @implementation BDNativeH5TesterImpViewController 19 | 20 | - (WKWebView *)webView { 21 | if (!_webView) { 22 | WKWebViewConfiguration *webViewConfig = [[WKWebViewConfiguration alloc] init]; 23 | _webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webViewConfig]; 24 | _webView.UIDelegate = self; 25 | _webView.navigationDelegate = self; 26 | } 27 | return _webView; 28 | } 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | self.view.backgroundColor = [UIColor whiteColor]; 33 | 34 | NSString *htmlFilePath = [NSBundle.mainBundle pathForResource:@"h5_page" ofType:@"html"]; 35 | NSString *htmlContent = [NSString stringWithContentsOfFile:htmlFilePath encoding:NSUTF8StringEncoding error:nil]; 36 | [self.webView loadHTMLString:htmlContent baseURL:nil]; 37 | 38 | self.view = self.webView; 39 | } 40 | 41 | - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { 42 | // 页面加载完成 43 | NSString *script = [NSString stringWithFormat:@"document.querySelector('#webview_class').innerHTML='本H5页面使用%@';", NSStringFromClass([self.webView class])]; 44 | [self.webView evaluateJavaScript:script 45 | completionHandler:^(id _Nullable ret, NSError * _Nullable error) { 46 | // NSLog(@"%@", ret); 47 | }]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/H5Tester/h5_page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 |

14 | 测试H5无埋点打通Native。 15 |

16 | 17 |

18 | 点击下方的按钮,观察XCode调试窗口是否有事件日志输出。如果有说明H5页面无埋点已经打通。 19 |

20 | 21 | 22 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/HookCompatibilityTester/BDAspectTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAspectTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // Hook相关库兼容性测试:测试同时使用Aspect时是否会有兼容性问题 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDAspectTesterImp : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/HookCompatibilityTester/BDAspectTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDAspectTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDAspectTesterImp.h" 10 | 11 | @interface BDAspectTesterImp () 12 | 13 | @end 14 | 15 | @implementation BDAspectTesterImp 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | self.view.backgroundColor = [UIColor whiteColor]; 21 | } 22 | 23 | /* 24 | #pragma mark - Navigation 25 | 26 | // In a storyboard-based application, you will often want to do a little preparation before navigation 27 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 28 | // Get the new view controller using [segue destinationViewController]. 29 | // Pass the selected object to the new view controller. 30 | } 31 | */ 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/HookCompatibilityTester/BDHookCompatibilityTesterSuite.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDHookCompatibilityTesterSuite.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDTesterIntroducerBase.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDHookCompatibilityTesterSuite : BDTesterIntroducerBase 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/HookCompatibilityTester/BDHookCompatibilityTesterSuite.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDHookCompatibilityTesterSuite.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDHookCompatibilityTesterSuite.h" 10 | #import "BDFeedModel.h" 11 | #import "BDModelSectionHeader.h" 12 | #import "BDAspectTesterImp.h" 13 | #import "BDReactiveObjcTesterImp.h" 14 | 15 | 16 | @interface BDHookCompatibilityTesterSuite () 17 | 18 | @end 19 | 20 | @implementation BDHookCompatibilityTesterSuite 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | self.feedModels = [NSMutableArray arrayWithObjects:[ 25 | [BDFeedModel alloc] initWithTitle:@"Aspect库兼容性测试" actionBlock:^{ 26 | __auto_type vc = [[BDAspectTesterImp alloc] init]; 27 | [self.navigationController pushViewController:vc animated:YES]; 28 | }], 29 | [[BDFeedModel alloc] initWithTitle:@"ReactiveObjc库兼容性测试" actionBlock:^{ 30 | __auto_type vc = [[BDReactiveObjcTesterImp alloc] init]; 31 | [self.navigationController pushViewController:vc animated:YES]; 32 | }], 33 | [[BDFeedModel alloc] initWithTitle:@"" actionBlock:^{ 34 | // __auto_type vc = [[ alloc] init]; 35 | // [self.navigationController pushViewController:vc animated:YES]; 36 | }], 37 | nil 38 | ]; 39 | } 40 | 41 | /* 42 | #pragma mark - Navigation 43 | 44 | // In a storyboard-based application, you will often want to do a little preparation before navigation 45 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 46 | // Get the new view controller using [segue destinationViewController]. 47 | // Pass the selected object to the new view controller. 48 | } 49 | */ 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/HookCompatibilityTester/BDReactiveObjCTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDReactiveObjcTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // Hook相关库兼容性测试:测试同时使用ReactiveObjC时是否会有兼容性问题 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDReactiveObjcTesterImp : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/HookCompatibilityTester/BDReactiveObjCTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDReactiveObjcTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDReactiveObjcTesterImp.h" 10 | 11 | @interface BDReactiveObjcTesterImp () 12 | 13 | @end 14 | 15 | @implementation BDReactiveObjcTesterImp 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | self.view.backgroundColor = [UIColor whiteColor]; 21 | } 22 | 23 | /* 24 | #pragma mark - Navigation 25 | 26 | // In a storyboard-based application, you will often want to do a little preparation before navigation 27 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 28 | // Get the new view controller using [segue destinationViewController]. 29 | // Pass the selected object to the new view controller. 30 | } 31 | */ 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/New Group/NewCaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NewCaseViewController.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/9/27. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDTesterIntroducerBase.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NewCaseViewController : BDTesterIntroducerBase 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/New Group/NewCaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NewCaseViewController.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/9/27. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "NewCaseViewController.h" 10 | 11 | @interface NewCaseViewController () 12 | 13 | @end 14 | 15 | @implementation NewCaseViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.title = @"一个新用例"; 20 | 21 | self.feedModels = [NSMutableArray new]; 22 | } 23 | 24 | /* 25 | #pragma mark - Navigation 26 | 27 | // In a storyboard-based application, you will often want to do a little preparation before navigation 28 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 29 | // Get the new view controller using [segue destinationViewController]. 30 | // Pass the selected object to the new view controller. 31 | } 32 | */ 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/PickerTester/BDTestPickerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDTestPickerViewController.h 3 | // rangersAppLogObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/17. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDTestPickerViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/PickerTester/BDTestPickerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDTestPickerViewController.m 3 | // rangersAppLogObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/17. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDTestPickerViewController.h" 10 | 11 | @interface BDTestPickerViewController () 12 | 13 | @end 14 | 15 | @implementation BDTestPickerViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.title = @"圈选测试"; 20 | } 21 | 22 | /* 23 | #pragma mark - Navigation 24 | 25 | // In a storyboard-based application, you will often want to do a little preparation before navigation 26 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 27 | // Get the new view controller using [segue destinationViewController]. 28 | // Pass the selected object to the new view controller. 29 | } 30 | */ 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/PlayerTester/BDPlayerTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDPlayerTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 测试DataPlayer场景 8 | 9 | #import 10 | #import "BDTesterIntroducerBase.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDPlayerTesterImp : BDTesterIntroducerBase 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/PlayerTester/BDPlayerTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDPlayerTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDPlayerTesterImp.h" 10 | #import "BDAutoTrack+Game.h" 11 | #import "BDFeedModel.h" 12 | #import "BDAdapter.h" 13 | #import 14 | 15 | @interface BDPlayerTesterImp () 16 | 17 | @end 18 | 19 | static NSString *cellReuseID = @"playerTester_1"; 20 | 21 | @implementation BDPlayerTesterImp 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | self.title = @"Player场景测试页"; 27 | 28 | NSDictionary *sharedParams = @{ 29 | @"from": @"testerPlayer" 30 | }; 31 | static int level = 1; 32 | self.feedModels = [NSMutableArray arrayWithObjects: 33 | [[BDFeedModel alloc] initWithTitle:@"注册" actionBlock:^{ 34 | [BDAutoTrack registerEventByMethod:@"wechat" isSuccess:YES]; 35 | }], 36 | [[BDFeedModel alloc] initWithTitle:@"登陆" actionBlock:^{ 37 | [BDAutoTrack loginEventByMethod:@"wechat" isSuccess:YES]; 38 | }], 39 | [[BDFeedModel alloc] initWithTitle:@"绑定社交账号" actionBlock:^{ 40 | [BDAutoTrack accessAccountEventByType:@"weibo" isSuccess:YES]; 41 | }], 42 | [[BDFeedModel alloc] initWithTitle:@"游戏初始化" actionBlock:^{ 43 | [BDAutoTrack eventV3:@"game_initialized" params:sharedParams]; 44 | }], 45 | [[BDFeedModel alloc] initWithTitle:@"开始游戏" actionBlock:^{ 46 | [BDAutoTrack eventV3:@"game_started" params:sharedParams]; 47 | }], 48 | [[BDFeedModel alloc] initWithTitle:@"结束游戏" actionBlock:^{ 49 | [BDAutoTrack eventV3:@"game_ended" params:sharedParams]; 50 | }], 51 | [[BDFeedModel alloc] initWithTitle:@"升级" actionBlock:^{ 52 | level += 1; 53 | [BDAutoTrack updateLevelEventWithLevel:level]; 54 | }], 55 | [[BDFeedModel alloc] initWithTitle:@"开始展示广告位" actionBlock:^{ 56 | [BDAutoTrack eventV3:@"start_display_ad" params:sharedParams]; 57 | }], 58 | [[BDFeedModel alloc] initWithTitle:@"点击广告位" actionBlock:^{ 59 | [BDAutoTrack eventV3:@"click_ad" params:sharedParams]; 60 | }], 61 | [[BDFeedModel alloc] initWithTitle:@"结束展示广告位" actionBlock:^{ 62 | [BDAutoTrack eventV3:@"end_display_ad" params:sharedParams]; 63 | }], 64 | [[BDFeedModel alloc] initWithTitle:@"获取游戏币" actionBlock:^{ 65 | [BDAutoTrack eventV3:@"acquire_game_coins" params:sharedParams]; 66 | }], 67 | [[BDFeedModel alloc] initWithTitle:@"加入购物车" actionBlock:^{ 68 | [BDAutoTrack addCartEventWithContentType:@"内购" 69 | contentName:@"传奇武器" 70 | contentID:@"contentId1234" 71 | contentNumber:1 72 | isSuccess:YES]; 73 | }], 74 | [[BDFeedModel alloc] initWithTitle:@"提交购买/下单" actionBlock:^{ 75 | [BDAutoTrack checkoutEventWithContentType:@"内购" 76 | contentName:@"传奇武器" contentID:@"contentId1234" 77 | contentNumber:100 78 | isVirtualCurrency:YES 79 | virtualCurrency:@"游戏币" 80 | currency:@"RMB" 81 | currency_amount:1 82 | isSuccess:YES]; 83 | }], 84 | [[BDFeedModel alloc] initWithTitle:@"支付" actionBlock:^{ 85 | [BDAutoTrack purchaseEventWithContentType:@"内购" 86 | contentName:@"传奇武器" 87 | contentID:@"contentId1234" 88 | contentNumber:100 89 | paymentChannel:@"App Store" 90 | currency:@"RMB" currency_amount:1 isSuccess:YES]; 91 | }], 92 | [[BDFeedModel alloc] initWithTitle:@"自定义V3事件" actionBlock:^{ 93 | [BDAdapter eventV3:@"player_custom_V3_event" params:@{@"from": @"playerTester"}]; 94 | }], 95 | nil 96 | ]; 97 | } 98 | 99 | 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ProfileAPITester/BDProfileAPITesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDProfileAPITesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/9/14. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDTesterIntroducerBase.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDProfileAPITesterImp : BDTesterIntroducerBase 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ProfileAPITester/BDProfileAPITesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDProfileAPITesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/9/14. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDProfileAPITesterImp.h" 10 | #import "BDModelSectionHeader.h" 11 | #import "BDProfileAPITester_UI.h" 12 | #import 13 | 14 | static NSString *cellReuseID = @"finderTester_1"; 15 | 16 | @interface BDProfileAPITesterImp () 17 | 18 | @end 19 | 20 | @implementation BDProfileAPITesterImp 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | self.title = @"Profile API测试页"; 25 | 26 | NSDictionary *profileDict = @{@"user_level": @(100), 27 | @"interests": @[@"跑团", @"爬山", @"看书"]}; 28 | __block int noInterest = 1; 29 | __weak BDAutoTrack *sharedTrack = [BDAutoTrack sharedTrack]; 30 | __weak typeof(self) wself = self; 31 | self.feedModels = [NSMutableArray arrayWithObjects: 32 | [[BDFeedModel alloc] initWithTitle:@"切换user unique id(重新注册激活)" actionBlock:^{ 33 | [sharedTrack setCurrentUserUniqueID:NSUUID.UUID.UUIDString]; 34 | }], 35 | [[BDFeedModel alloc] initWithTitle:@"进入测试UI" actionBlock:^{ 36 | __auto_type vc = [[BDProfileAPITester_UI alloc] init]; 37 | [wself.navigationController pushViewController:vc animated:YES]; 38 | }], 39 | 40 | // [[BDModelSectionHeader alloc] initWithSectionName:@"set" desc:@""], 41 | // [[BDFeedModel alloc] initWithTitle:@"set" actionBlock:^{ 42 | // [sharedTrack profileSet:profileDict]; 43 | // }], 44 | // 45 | // [[BDModelSectionHeader alloc] initWithSectionName:@"setOnce" desc:@""], 46 | // [[BDFeedModel alloc] initWithTitle:@"setOnce" actionBlock:^{ 47 | // [sharedTrack profileSetOnce:profileDict]; 48 | // }], 49 | // 50 | // 51 | // [[BDModelSectionHeader alloc] initWithSectionName:@"Increment" desc:@""], 52 | // [[BDFeedModel alloc] initWithTitle:@"Increment" actionBlock:^{ 53 | // [sharedTrack profileIncrement:@{@"user_level": @(2)}]; 54 | // }], 55 | // 56 | // [[BDModelSectionHeader alloc] initWithSectionName:@"Append" desc:@""], 57 | // [[BDFeedModel alloc] initWithTitle:@"Append" actionBlock:^{ 58 | // [sharedTrack profileAppend:@{ 59 | // @"interests": [@"habbit-" stringByAppendingString:@(noInterest++).stringValue] 60 | // }]; 61 | // }], 62 | // 63 | // [[BDModelSectionHeader alloc] initWithSectionName:@"Unset" desc:@""], 64 | // [[BDFeedModel alloc] initWithTitle:@"Unset" actionBlock:^{ 65 | // [sharedTrack profileUnset:@"user_level"]; 66 | // [sharedTrack profileUnset:@"interests"]; 67 | // }], 68 | nil 69 | ]; 70 | } 71 | 72 | /* 73 | #pragma mark - Navigation 74 | 75 | // In a storyboard-based application, you will often want to do a little preparation before navigation 76 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 77 | // Get the new view controller using [segue destinationViewController]. 78 | // Pass the selected object to the new view controller. 79 | } 80 | */ 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/ProfileAPITester/BDProfileAPITester_UI.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDProfileAPITester_UI.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/10/10. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDProfileAPITester_UI : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/BDUICompatibilityTesterSuite.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDUICompatibilityTesterSuite.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDTesterIntroducerBase.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDUICompatibilityTesterSuite : BDTesterIntroducerBase 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/BDUICompatibilityTesterSuite.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDUICompatibilityTesterSuite.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDUICompatibilityTesterSuite.h" 10 | #import "BDFeedModel.h" 11 | #import "BDModelSectionHeader.h" 12 | #import "BDIGListKitTesterImp.h" 13 | #import "BDOverlapWindowTesterImp.h" 14 | #import "BDSubviewToWindowTesterImp.h" 15 | 16 | @interface BDUICompatibilityTesterSuite () 17 | 18 | @end 19 | 20 | @implementation BDUICompatibilityTesterSuite 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | self.title = @"UI兼容性测试"; 26 | 27 | self.feedModels = [NSMutableArray arrayWithObjects:[ 28 | [BDFeedModel alloc] initWithTitle:@"IGListKit" actionBlock:^{ 29 | __auto_type vc = [[BDIGListKitTesterImp alloc] init]; 30 | [self.navigationController pushViewController:vc animated:YES]; 31 | }], 32 | [[BDFeedModel alloc] initWithTitle:@"overlapped window" actionBlock:^{ 33 | __auto_type vc = [[BDOverlapWindowTesterImp alloc] init]; 34 | [self.navigationController pushViewController:vc animated:YES]; 35 | }], 36 | [[BDFeedModel alloc] initWithTitle:@"add buttons as window's subviews" actionBlock:^{ 37 | __auto_type vc = [[BDSubviewToWindowTesterImp alloc] init]; 38 | [self.navigationController pushViewController:vc animated:YES]; 39 | }], 40 | nil 41 | ]; 42 | } 43 | 44 | /* 45 | #pragma mark - Navigation 46 | 47 | // In a storyboard-based application, you will often want to do a little preparation before navigation 48 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 49 | // Get the new view controller using [segue destinationViewController]. 50 | // Pass the selected object to the new view controller. 51 | } 52 | */ 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/IGListTester/BDChinesePaintingSectionController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDChinesePaintingSectionController.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/24. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDChinesePaintingSectionController : IGListSectionController 14 | 15 | @property (strong, nonatomic) NSString *picName; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/IGListTester/BDChinesePaintingSectionController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDChinesePaintingSectionController.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/24. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDChinesePaintingSectionController.h" 10 | 11 | @interface BDChinesePaintingSectionController () 12 | 13 | @end 14 | 15 | 16 | @implementation BDChinesePaintingSectionController 17 | 18 | 19 | - (NSInteger)numberOfItems { 20 | return 1; 21 | } 22 | 23 | - (CGSize)sizeForItemAtIndex:(NSInteger)index { 24 | CGFloat width = [[self collectionContext] containerSize].width ?: 0; 25 | return CGSizeMake(width, width); 26 | } 27 | 28 | - (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { 29 | id ctx = [self collectionContext]; 30 | 31 | UICollectionViewCell * cell = [ctx dequeueReusableCellOfClass:[UICollectionViewCell class] forSectionController:self atIndex:index]; 32 | 33 | UIImage *img = [UIImage imageNamed:self.picName]; 34 | UIImageView *imgView = [[UIImageView alloc] initWithImage:img]; 35 | imgView.frame = cell.contentView.bounds; 36 | [cell.contentView addSubview:imgView]; 37 | 38 | return cell; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/IGListTester/BDIGListKitTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDIGListKitTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // UI兼容性测试:测试同时使用IGListKit时是否会有兼容性问题 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDIGListKitTesterImp : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/IGListTester/BDIGListKitTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDIGListKitTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDIGListKitTesterImp.h" 10 | #import 11 | #import "IGListTesterModel.h" 12 | #import "BDChinesePaintingSectionController.h" 13 | 14 | @interface BDIGListKitTesterImp () 15 | 16 | @property (strong, nonatomic) UICollectionView *collectionView; 17 | @property (strong, nonatomic) IGListAdapter *adapter; 18 | 19 | @end 20 | 21 | @implementation BDIGListKitTesterImp 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds 27 | collectionViewLayout:UICollectionViewFlowLayout.new]; 28 | self.collectionView.backgroundColor = [UIColor colorWithRed:100.0/255 green:155.0/255 blue:100.0/255 alpha:1.0]; 29 | 30 | self.adapter.collectionView = self.collectionView; 31 | self.adapter.dataSource = self; 32 | [self.view addSubview:self.collectionView]; 33 | } 34 | 35 | #pragma mark - ListAdapterDataSource 36 | 37 | - (nonnull NSArray> *)objectsForListAdapter:(nonnull IGListAdapter *)listAdapter { 38 | return @[@"猫国画", @"荷花国画", @"梅花国画", @"迎客松国画", 39 | @"果树国画", @"竹子国画", @"山花烂漫国画"]; 40 | } 41 | 42 | - (nonnull IGListSectionController *)listAdapter:(nonnull IGListAdapter *)listAdapter sectionControllerForObject:(nonnull id)object { 43 | BDChinesePaintingSectionController *sectionController = [BDChinesePaintingSectionController new]; 44 | if ([object isKindOfClass:NSString.class]) { 45 | sectionController.picName = object; 46 | } 47 | return sectionController; 48 | } 49 | 50 | - (nullable UIView *)emptyViewForListAdapter:(nonnull IGListAdapter *)listAdapter { 51 | return nil; 52 | } 53 | 54 | 55 | #pragma mark - getter 56 | - (IGListAdapter *)adapter { 57 | if (!_adapter) { 58 | IGListAdapterUpdater *updater = [[IGListAdapterUpdater alloc] init]; 59 | _adapter = [[IGListAdapter alloc] initWithUpdater:updater 60 | viewController:self 61 | workingRangeSize:1]; 62 | } 63 | return _adapter; 64 | } 65 | 66 | @end 67 | 68 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/IGListTester/IGListTesterModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // IGListTesterModel.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/23. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface IGListTesterModel : NSObject 14 | @property (strong, nonatomic, readonly) NSString *uuid; 15 | @property (strong, nonatomic) NSString *picName; 16 | 17 | - (instancetype)initWithPictureName:(NSString *)picName; 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/IGListTester/IGListTesterModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // IGListTesterModel.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/23. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "IGListTesterModel.h" 10 | #import 11 | 12 | @interface IGListTesterModel () 13 | 14 | @end 15 | 16 | @implementation IGListTesterModel 17 | 18 | - (instancetype)init { 19 | self = [super init]; 20 | if (self) { 21 | _uuid = NSUUID.UUID.UUIDString; 22 | } 23 | return self; 24 | } 25 | 26 | - (instancetype)initWithPictureName:(NSString *)picName { 27 | self = [self init]; 28 | if (self) { 29 | _picName = picName; 30 | } 31 | return self; 32 | } 33 | 34 | #pragma mark - IGListDiffable 35 | - (nonnull id)diffIdentifier { 36 | return self.uuid; 37 | } 38 | 39 | - (BOOL)isEqualToDiffableObject:(nullable NSObject *)object { 40 | if ([object isKindOfClass:IGListTesterModel.class]) { 41 | return false; 42 | } 43 | 44 | return [self.uuid isEqualToString:((IGListTesterModel *)object).uuid]; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/OverlapWindowTester/BDOverlapWindowTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDOverlapWindowTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // UI兼容性测试:测试使用Overlap Window时是否会有兼容性问题 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDOverlapWindowTesterImp : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/OverlapWindowTester/BDOverlapWindowTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDOverlapWindowTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDOverlapWindowTesterImp.h" 10 | #import "BDColors.h" 11 | 12 | @interface BDOverlapWindowTesterImp () 13 | @property (strong, nonatomic) UIWindow *overlappedWindow; 14 | @end 15 | 16 | @implementation BDOverlapWindowTesterImp 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.view.backgroundColor = [[BDColors sharedInstance] lightRed]; 21 | 22 | self.overlappedWindow.hidden = false; 23 | } 24 | 25 | #pragma mark - getter 26 | - (UIWindow *)overlappedWindow { 27 | if (!_overlappedWindow) { 28 | UIImage *img = [UIImage imageNamed:@"cenci"]; 29 | CGFloat imgWidth = img.size.width, imgHeight = img.size.height; 30 | UIImageView *imgView = [[UIImageView alloc] initWithImage:img]; 31 | 32 | UIWindow *keyWindow = [UIApplication.sharedApplication keyWindow]; 33 | CGFloat keyWindowWidth = keyWindow.bounds.size.width; 34 | 35 | CGRect frame = CGRectMake(0, 150, keyWindowWidth, keyWindowWidth / imgWidth * imgHeight); 36 | _overlappedWindow = [[UIWindow alloc] initWithFrame:frame]; 37 | 38 | imgView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); 39 | 40 | [_overlappedWindow addSubview:imgView]; 41 | } 42 | return _overlappedWindow; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/SubviewToWindow/BDSubviewToWindowTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDSubviewToWindowTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/24. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDSubviewToWindowTesterImp : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UICompatibilityTester/SubviewToWindow/BDSubviewToWindowTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDSubviewToWindowTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/24. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDSubviewToWindowTesterImp.h" 10 | #import "BDColors.h" 11 | 12 | @interface BDSubviewToWindowTesterImp () 13 | 14 | @property (weak, nonatomic) UIWindow *keyWindow; 15 | @property (weak, nonatomic) UIButton *button1; 16 | @property (weak, nonatomic) UIButton *button2; 17 | 18 | @end 19 | 20 | @implementation BDSubviewToWindowTesterImp 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | self.view.backgroundColor = [BDColors.sharedInstance lightGreen]; 25 | [self addTestButtonInWindow:self.keyWindow]; 26 | 27 | } 28 | 29 | - (void)addTestButtonInWindow:(UIWindow *)window { 30 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 31 | CGFloat top = window.bounds.size.height - 144; 32 | CGFloat left = (window.bounds.size.width - 200)/2; 33 | UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(left, top, 200, 44)]; 34 | button.backgroundColor = [BDColors.sharedInstance lightBlue]; 35 | [button setTitle:@"Button 2" forState:(UIControlStateNormal)]; 36 | [button addTarget:self action:@selector(handleButtonEvent:) forControlEvents:(UIControlEventTouchUpInside)]; 37 | self.button1 = button; 38 | [window addSubview:button]; 39 | 40 | top -= 60; 41 | button = [[UIButton alloc] initWithFrame:CGRectMake(left, top, 200, 44)]; 42 | button.backgroundColor = [BDColors.sharedInstance lightBlue]; 43 | [button setTitle:@"Button 1" forState:(UIControlStateNormal)]; 44 | [button addTarget:self action:@selector(handleButtonEvent:) forControlEvents:(UIControlEventTouchUpInside)]; 45 | self.button2 = button; 46 | [window addSubview:button]; 47 | }); 48 | } 49 | 50 | - (void)viewWillDisappear:(BOOL)animated { 51 | [self.button1 removeFromSuperview]; 52 | [self.button2 removeFromSuperview]; 53 | } 54 | 55 | #pragma mark - handlers 56 | - (void)handleButtonEvent:(UIButton *)sender { 57 | NSLog(@"%@ is touched", sender.class); 58 | } 59 | 60 | #pragma mark - getter 61 | - (UIWindow *)keyWindow { 62 | return [UIApplication.sharedApplication keyWindow]; 63 | } 64 | 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UITrackTester/BDUITrackTesterImp.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDUITrackTesterImp.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 测试无埋点 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDUITrackTesterImp : UIViewController 14 | 15 | @property (nonatomic) BOOL shouldTestPicker; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Controllers/UITrackTester/BDUITrackTesterImp.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDUITrackTesterImp.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDUITrackTesterImp.h" 10 | 11 | @interface BDUITrackTesterImp () 12 | 13 | @end 14 | 15 | @implementation BDUITrackTesterImp 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.title = self.shouldTestPicker ? @"圈选测试" : @"无埋点测试"; 20 | 21 | CGRect frame = self.navigationController.navigationBar.frame; 22 | CGFloat top = frame.origin.y + frame.size.height; 23 | CGRect newFrame = self.view.frame; 24 | newFrame.origin.y = top; 25 | newFrame.size.height -= top; 26 | [self.view setFrame:newFrame]; // bug:UI被NavBar覆盖了 27 | 28 | if(self.shouldTestPicker) { 29 | // todo 30 | } 31 | } 32 | 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.1 19 | CFBundleVersion 20 | 1.1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDAbstractModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAbstractModel.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /// 所有Model的抽象祖先类 14 | @interface BDAbstractModel : NSObject 15 | 16 | @property (nonatomic, copy) dispatch_block_t actionBlock; 17 | @property (nonatomic, assign) NSInteger cellType; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDAbstractModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDAbstractModel.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDAbstractModel.h" 10 | 11 | @implementation BDAbstractModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDConfigViewModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDConfigViewModel.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDAbstractModel.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDConfigViewModel : BDAbstractModel 14 | 15 | @property (strong, nonatomic) NSString *configKey; 16 | @property (strong, nonatomic) NSString *configValue; 17 | 18 | - (instancetype)initWithConfigKey:(NSString *)configKey value:(NSString *)value; 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDConfigViewModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDConfigViewModel.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/25. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDConfigViewModel.h" 10 | 11 | @implementation BDConfigViewModel 12 | 13 | - (instancetype)initWithConfigKey:(NSString *)configKey value:(NSString *)value { 14 | self = [super init]; 15 | if (self) { 16 | self.configKey = configKey; 17 | self.configValue = value; 18 | } 19 | return self; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDFeedModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedModel.h 3 | // BDAutoTracker_Example 4 | // 5 | // Created by bob on 2019/4/17. 6 | // Copyright © 2019 ByteDance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BDAbstractModel.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDFeedModel : BDAbstractModel 15 | 16 | @property (nonatomic, copy) NSString *title; 17 | 18 | //@property (nonatomic, copy) NSString *httpURL; 19 | 20 | - (instancetype)initWithTitle:(NSString *)title actionBlock:(dispatch_block_t)actionBlock; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDFeedModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedModel.m 3 | // BDAutoTracker_Example 4 | // 5 | // Created by bob on 2019/4/17. 6 | // Copyright © 2019 ByteDance. All rights reserved. 7 | // 8 | 9 | #import "BDFeedModel.h" 10 | 11 | @implementation BDFeedModel 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | self.cellType = 0; 17 | } 18 | 19 | return self; 20 | } 21 | 22 | - (instancetype)initWithTitle:(NSString *)title actionBlock:(dispatch_block_t)actionBlock { 23 | self = [self init]; 24 | if (self) { 25 | self.title = title; 26 | self.actionBlock = actionBlock; 27 | } 28 | return self; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDFeedModelDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedModelDictionary.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/22. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 作为 UITableView 的 Model 8 | /* 9 | * 实现: 10 | * 类内部维护两个字典。 11 | * 1. section:modelItems MAP 12 | * { 13 | * @(0): @[BDAbstractModel, BDAbstractModel, ...], 14 | * @(1): @[BDAbstractModel, BDAbstractModel, ...] 15 | * } 16 | * 17 | * 2. section:sectionMeta MAP 18 | * { 19 | * @(0): BDModelSectionHeader, 20 | * @(1): BDModelSectionHeader 21 | * } 22 | */ 23 | 24 | 25 | #import 26 | #import "BDFeedModel.h" 27 | #import "BDModelSectionHeader.h" 28 | 29 | NS_ASSUME_NONNULL_BEGIN 30 | 31 | @interface BDFeedModelDictionary : NSObject 32 | 33 | - (instancetype)initWithModelArray:(NSArray *)array; 34 | 35 | - (BOOL)setSectionDevider:(BDModelSectionHeader *)sectionDevider ToSection:(NSInteger)section; 36 | 37 | - (BOOL)appendItem:(BDAbstractModel *)item ToSection:(NSInteger)section; 38 | 39 | - (BOOL)appendItems:(NSArray *)items ToSection:(NSInteger)section; 40 | 41 | - (BOOL)clear; 42 | 43 | - (NSArray *)itemsForSection:(NSInteger)section; 44 | 45 | - (BDModelSectionHeader *)sectionDeviderForSection:(NSInteger)section; 46 | 47 | - (NSUInteger)numOfItemsInSection:(NSInteger)section; 48 | 49 | - (NSUInteger)numSections; 50 | 51 | @end 52 | 53 | NS_ASSUME_NONNULL_END 54 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDFeedModelDictionary.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDFeedModelDictionary.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/22. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // TODO: 1. 生成公共API签名 Done. 2. 单元测试 8 | 9 | #import "BDFeedModelDictionary.h" 10 | 11 | @interface BDFeedModelDictionary () 12 | @property (strong, nonatomic) NSMutableDictionary *sectionMetaMap; 13 | @property (strong, nonatomic) NSMutableDictionary *> *sectionItemMap; 14 | 15 | @end 16 | 17 | @implementation BDFeedModelDictionary 18 | 19 | #pragma mark - create and modify 20 | - (instancetype)initWithModelArray:(NSArray *)array { 21 | self = [super init]; 22 | if (self) { 23 | if (array && array.count > 0) { // 第一个 section devider 单独处理 24 | NSObject *obj = array[0]; 25 | if (![obj isKindOfClass:BDModelSectionHeader.class]) { 26 | // 用户没有提供第一个默认section devider,我们帮他加上 27 | BDModelSectionHeader *firstDevider = [[BDModelSectionHeader alloc] initWithSectionName:@"default section" desc:@""]; 28 | array = [@[firstDevider] arrayByAddingObjectsFromArray:array]; 29 | } 30 | } 31 | 32 | NSInteger countSection = 0; 33 | for (int i = 0; i < array.count; ++i) { 34 | NSObject *obj = [array objectAtIndex:i]; 35 | 36 | if ([obj isKindOfClass:BDModelSectionHeader.class]) { 37 | [self setSectionDevider:(BDModelSectionHeader *)obj ToSection:countSection]; 38 | for (int j = i + 1; j < array.count; ++j) { 39 | obj = [array objectAtIndex:j]; 40 | if ([obj isKindOfClass:BDAbstractModel.class]) { 41 | [self appendItem:(BDAbstractModel *)obj 42 | ToSection:countSection]; 43 | } else if ([obj isKindOfClass:BDModelSectionHeader.class]) { 44 | i = j - 1; 45 | break; 46 | } else if (j == array.count - 1) { 47 | i = j; 48 | break; 49 | } 50 | } 51 | ++countSection; 52 | } 53 | } // end for 54 | } 55 | return self; 56 | } 57 | 58 | - (BOOL)setSectionDevider:(BDModelSectionHeader *)sectionDevider ToSection:(NSInteger)section { 59 | if (!sectionDevider) { 60 | return NO; 61 | } 62 | [self.sectionMetaMap setObject:sectionDevider forKey:@(section)]; 63 | return YES; 64 | } 65 | 66 | - (BOOL)appendItem:(BDAbstractModel *)item ToSection:(NSInteger)section { 67 | if (!item) { 68 | return NO; 69 | } 70 | NSMutableArray *mArray = [self __itemsForSection:section]; 71 | [mArray addObject:item]; 72 | return YES; 73 | } 74 | 75 | - (BOOL)appendItems:(NSArray *)items ToSection:(NSInteger)section { 76 | NSMutableArray *mArray = [self __itemsForSection:section]; 77 | [mArray addObjectsFromArray:items]; 78 | return YES; 79 | } 80 | 81 | - (BOOL)clear { 82 | self.sectionItemMap = nil; 83 | self.sectionMetaMap = nil; 84 | return YES; 85 | } 86 | 87 | #pragma mark - table view query 88 | /// 返回特定section的model数据 89 | /// 注意不要直接修改返回的数组,任何修改必须通过本类的public API来完成。 90 | /// @param section section index 91 | - (NSArray *)itemsForSection:(NSInteger)section { 92 | NSMutableArray *items = [self __itemsForSection:section]; 93 | return items; 94 | } 95 | 96 | - (BDModelSectionHeader *)sectionDeviderForSection:(NSInteger)section { 97 | BDModelSectionHeader *sectionDevider = [self.sectionMetaMap objectForKey:@(section)]; 98 | return sectionDevider; 99 | } 100 | 101 | - (NSUInteger)numOfItemsInSection:(NSInteger)section { 102 | NSMutableArray *items = [self.sectionItemMap objectForKey:@(section)]; 103 | return items.count; 104 | } 105 | 106 | - (NSUInteger)numSections { 107 | return [self.sectionItemMap count]; 108 | } 109 | 110 | /* private method */ 111 | #pragma mark - private 112 | - (NSMutableArray *)__itemsForSection:(NSInteger)section { 113 | if (![self.sectionItemMap objectForKey:@(section)]) { 114 | [self.sectionItemMap setObject:[NSMutableArray new] forKey:@(section)]; 115 | } 116 | return [self.sectionItemMap objectForKey:@(section)]; 117 | } 118 | 119 | #pragma mark - getter 120 | - (NSMutableDictionary *)sectionMetaMap { 121 | if (!_sectionMetaMap) { 122 | _sectionMetaMap = [NSMutableDictionary new]; 123 | } 124 | return _sectionMetaMap; 125 | } 126 | 127 | - (NSMutableDictionary *> *)sectionItemMap { 128 | if (!_sectionItemMap) { 129 | _sectionItemMap = [NSMutableDictionary new]; 130 | } 131 | return _sectionItemMap; 132 | } 133 | 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDModelSectionHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDModelSectionHeader.h 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/22. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 没有实际数据。只是用于在FeedModel数组中标识一个Section. 8 | 9 | #import "BDFeedModel.h" 10 | #import "BDAbstractModel.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface BDModelSectionHeader : NSObject 15 | 16 | @property (strong, nonatomic) NSString *sectionName; 17 | @property (nonatomic) NSUInteger sectionLength; 18 | @property (strong, nonatomic) NSString *sectionDescription; 19 | 20 | - (instancetype)initWithSectionName:(NSString *)name desc:(NSString *)desc; 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/Model/BDModelSectionHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDModelSectionHeader.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/22. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import "BDModelSectionHeader.h" 10 | 11 | @implementation BDModelSectionHeader 12 | 13 | - (instancetype)initWithSectionName:(NSString *)name desc:(NSString *)desc { 14 | self = [super init]; 15 | if (self) { 16 | self.sectionName = name; 17 | self.sectionDescription = desc; 18 | } 19 | return self; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ObjCExample/ObjCExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ObjCExample 4 | // 5 | // Created by 朱元清 on 2020/8/21. 6 | // Copyright © 2020 bytedance. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /ObjCExample/Podfile: -------------------------------------------------------------------------------- 1 | install! 'cocoapods', 2 | :disable_input_output_paths => true, 3 | :generate_multiple_pod_projects => true, 4 | :warn_for_multiple_pod_sources => false 5 | 6 | platform :ios, '9.0' 7 | inhibit_all_warnings! 8 | 9 | target "ObjCExample" do 10 | pod 'RangersAppLog', 11 | :path => '../', 12 | :subspecs => [ 13 | 'Host/CN', 14 | 'Core', 15 | 'Unique', 16 | 'CAID', 17 | 'Log', 18 | 'Picker', 19 | 'UITracker', 20 | ], 21 | :testspecs => [ 22 | # 'Tests', 23 | ], 24 | :inhibit_warnings => false 25 | 26 | # UI Compatibility Test 27 | pod 'IGListKit', '4.0.0' 28 | end 29 | 30 | def update_deployment_config(config = nil) 31 | return if config.nil? 32 | config.build_settings['ENABLE_BITCODE'] = 'YES' 33 | if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 9.0 34 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' 35 | end 36 | end 37 | 38 | post_install do |installer| 39 | installer.pods_project.build_configurations.each do |config| 40 | update_deployment_config(config) 41 | end 42 | 43 | installer.pods_project.targets.each do |target| 44 | target.build_configurations.each do |config| 45 | update_deployment_config(config) 46 | end 47 | end 48 | ## for generate_multiple_pod_projects = true 49 | installer.generated_projects.each do |project| 50 | project.build_configurations.each do |config| 51 | update_deployment_config(config) 52 | end 53 | 54 | project.targets.each do |target| 55 | target.build_configurations.each do |config| 56 | update_deployment_config(config) 57 | end 58 | end 59 | end 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /RangersAppLog.bundle/Assets.car: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog.bundle/Assets.car -------------------------------------------------------------------------------- /RangersAppLog.bundle/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog.bundle/Info.plist -------------------------------------------------------------------------------- /RangersAppLog.bundle/_CodeSignature/CodeDirectory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog.bundle/_CodeSignature/CodeDirectory -------------------------------------------------------------------------------- /RangersAppLog.bundle/_CodeSignature/CodeRequirements: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog.bundle/_CodeSignature/CodeRequirements -------------------------------------------------------------------------------- /RangersAppLog.bundle/_CodeSignature/CodeRequirements-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog.bundle/_CodeSignature/CodeRequirements-1 -------------------------------------------------------------------------------- /RangersAppLog.bundle/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Assets.car 8 | 9 | y7Il5mVEXZw0+d23G8PXQ2kxqPU= 10 | 11 | 12 | files2 13 | 14 | Assets.car 15 | 16 | hash 17 | 18 | y7Il5mVEXZw0+d23G8PXQ2kxqPU= 19 | 20 | hash2 21 | 22 | BWlCP/0QDL2g88emWUP8wmVl1C1Vw4idtzv4H/F13TE= 23 | 24 | 25 | 26 | rules 27 | 28 | ^.* 29 | 30 | ^.*\.lproj/ 31 | 32 | optional 33 | 34 | weight 35 | 1000 36 | 37 | ^.*\.lproj/locversion.plist$ 38 | 39 | omit 40 | 41 | weight 42 | 1100 43 | 44 | ^Base\.lproj/ 45 | 46 | weight 47 | 1010 48 | 49 | ^version.plist$ 50 | 51 | 52 | rules2 53 | 54 | .*\.dSYM($|/) 55 | 56 | weight 57 | 11 58 | 59 | ^(.*/)?\.DS_Store$ 60 | 61 | omit 62 | 63 | weight 64 | 2000 65 | 66 | ^.* 67 | 68 | ^.*\.lproj/ 69 | 70 | optional 71 | 72 | weight 73 | 1000 74 | 75 | ^.*\.lproj/locversion.plist$ 76 | 77 | omit 78 | 79 | weight 80 | 1100 81 | 82 | ^Base\.lproj/ 83 | 84 | weight 85 | 1010 86 | 87 | ^Info\.plist$ 88 | 89 | omit 90 | 91 | weight 92 | 20 93 | 94 | ^PkgInfo$ 95 | 96 | omit 97 | 98 | weight 99 | 20 100 | 101 | ^embedded\.provisionprofile$ 102 | 103 | weight 104 | 20 105 | 106 | ^version\.plist$ 107 | 108 | weight 109 | 20 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /RangersAppLog.bundle/_CodeSignature/CodeSignature: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog.bundle/_CodeSignature/CodeSignature -------------------------------------------------------------------------------- /RangersAppLog.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'RangersAppLog' 3 | s.version = '5.6.6' 4 | s.summary = 'ByteDance Rangers AppLog.' 5 | s.description = 'ByteDance Rangers AppLog SDK.' 6 | s.homepage = 'https://github.com/bytedance/RangersAppLog' 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { 'duanwenbin' => 'duanwenbin@bytedance.com' } 9 | s.source = { :git => 'https://github.com/bytedance/RangersAppLog.git', :tag => s.version.to_s } 10 | 11 | s.ios.deployment_target = '9.0' 12 | s.requires_arc = true 13 | s.static_framework = true 14 | s.pod_target_xcconfig = { 15 | 'OTHER_LDFLAGS' => '-lObjC', 16 | 'DEFINES_MODULE' => 'YES', 17 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' 18 | } 19 | s.user_target_xcconfig = { 20 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' 21 | } 22 | 23 | s.subspec 'Core' do |bd| 24 | bd.source_files = 'RangersAppLog/Classes/Core/*.{h,m,c}' 25 | bd.vendored_library = 'RangersAppLog/Classes/Core/*.a' 26 | bd.frameworks = 'UIKit','Foundation','Security','AdSupport','CoreTelephony','CoreFoundation','SystemConfiguration','CoreGraphics' 27 | bd.library = 'z','sqlite3' 28 | bd.public_header_files = 'RangersAppLog/Classes/Core/*.h' 29 | end 30 | 31 | s.subspec 'Host' do |bd| 32 | bd.dependency 'RangersAppLog/Core' 33 | bd.subspec 'CN' do |cn| 34 | cn.source_files = 'RangersAppLog/Classes/Host/CN/*.{h,m,c}' 35 | cn.public_header_files = 'RangersAppLog/Classes/Host/CN/*.h' 36 | cn.vendored_library = 'RangersAppLog/Classes/Host/CN/*.a' 37 | end 38 | bd.subspec 'SG' do |sg| 39 | sg.source_files = 'RangersAppLog/Classes/Host/SG/*.{h,m,c}' 40 | sg.public_header_files = 'RangersAppLog/Classes/Host/SG/*.h' 41 | sg.vendored_library = 'RangersAppLog/Classes/Host/SG/*.a' 42 | end 43 | bd.subspec 'VA' do |va| 44 | va.source_files = 'RangersAppLog/Classes/Host/VA/*.{h,m,c}' 45 | va.public_header_files = 'RangersAppLog/Classes/Host/VA/*.h' 46 | va.vendored_library = 'RangersAppLog/Classes/Host/VA/*.a' 47 | end 48 | end 49 | 50 | s.subspec 'Log' do |bd| 51 | bd.vendored_library = 'RangersAppLog/Classes/Log/*.a' 52 | bd.dependency 'RangersAppLog/Core' 53 | end 54 | 55 | s.subspec 'Unique' do |bd| 56 | bd.frameworks = 'AdSupport' #, 'AppTrackingTransparency' 57 | bd.dependency 'RangersAppLog/Core' 58 | bd.source_files = 'RangersAppLog/Classes/Unique/*.{h,m,c}' 59 | bd.public_header_files = 'RangersAppLog/Classes/Unique/*.h' 60 | bd.vendored_library = 'RangersAppLog/Classes/Unique/*.a' 61 | end 62 | 63 | s.subspec 'CAID' do |ss| 64 | ss.vendored_library = 'RangersAppLog/Classes/CAID/*.a' 65 | ss.dependency 'RangersAppLog/Core' 66 | end 67 | 68 | s.subspec 'UITracker' do |bd| 69 | bd.vendored_library = 'RangersAppLog/Classes/UITracker/*.a' 70 | bd.source_files = 'RangersAppLog/Classes/UITracker/*.{h,m,c}' 71 | bd.frameworks = 'Foundation','UIKit','WebKit' 72 | bd.public_header_files = 'RangersAppLog/Classes/UITracker/*.h' 73 | bd.dependency 'RangersAppLog/Core' 74 | end 75 | 76 | s.subspec 'Picker' do |bd| 77 | bd.vendored_library = 'RangersAppLog/Classes/Picker/*.a' 78 | bd.frameworks = 'Foundation','UIKit','WebKit','CoreText' 79 | bd.dependency 'RangersAppLog/Log' 80 | bd.dependency 'RangersAppLog/UITracker' 81 | bd.source_files = 'RangersAppLog/Classes/Picker/*.{h,m,c}' 82 | bd.public_header_files = 'RangersAppLog/Classes/Picker/*.h' 83 | end 84 | 85 | end 86 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/CAID/libRangersAppLog_CAID.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/CAID/libRangersAppLog_CAID.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrack+LaunchFrom.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrack+LaunchFrom.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2020/6/3. 6 | // 7 | 8 | #import "BDAutoTrack.h" 9 | #import "BDCommonDefine.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDAutoTrack (LaunchFrom) 14 | 15 | /* 16 | @abstract 初始化之后,支持设置APP的启动方式,会体现的上报的数据中,参考 17 | */ 18 | + (void)setLaunchFrom:(BDAutoTrackLaunchFrom)from; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrack+OhayooGameTrack.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrack+OhayooGameTrack.h 3 | // RangersAppLog 4 | // 5 | // Created by 陈奕 on 2019/11/26. 6 | // 7 | 8 | #import "BDAutoTrack.h" 9 | 10 | typedef NSString * OhayooCustomHeaderKey NS_TYPED_ENUM; 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | /* ohayoo custom header key. 均以"ohayoo_"开头 */ 15 | FOUNDATION_EXTERN OhayooCustomHeaderKey OhayooCustomHeaderKeyPackageChannel; 16 | FOUNDATION_EXTERN OhayooCustomHeaderKey OhayooCustomHeaderKeyZoneID; 17 | FOUNDATION_EXTERN OhayooCustomHeaderKey OhayooCustomHeaderKeyServerID; 18 | FOUNDATION_EXTERN OhayooCustomHeaderKey OhayooCustomHeaderKeySDKOpenID; 19 | FOUNDATION_EXTERN OhayooCustomHeaderKey OhayooCustomHeaderKeyUserType; 20 | FOUNDATION_EXTERN OhayooCustomHeaderKey OhayooCustomHeaderKeyRoleID; 21 | FOUNDATION_EXTERN OhayooCustomHeaderKey OhayooCustomHeaderKeyLevel; 22 | 23 | #pragma mark - OhayooGameTrack 24 | 25 | @interface BDAutoTrack (OhayooGameTrack) 26 | 27 | /** 28 | 初始化信息:gt_init_info 29 | lev int 当前玩家等级 30 | scene_id int 当前场景id 31 | scene_lev int 当前场景的用户等级 32 | coin_type string 获得货币的类型 33 | coin_left int 用户身上剩余的货币数量 34 | roleId string 角色id 35 | 触发条件:用户启动游戏,初始化完成时上报 36 | 37 | @discussion 上报参数比GameTrack的多了 sceneID sceneLev 38 | */ 39 | - (void)gameInitInfoEventWithLevel:(NSInteger)level 40 | sceneID:(NSInteger)sceneID 41 | sceneLev:(NSInteger)sceneLev 42 | coinType:(NSString *)coinType 43 | coinLeft:(NSInteger)coinLeft 44 | roleId:(NSString *)roleId 45 | otherParams:(nullable NSDictionary *)otherParams; 46 | 47 | /** 48 | @abstract 将相应ohayoo字段设置到custom header中的辅助方法。实际上是调用`setCustomHeaderValue:forKey:`。 49 | @discussion 使用示例: 50 | @code 51 | [BDAutoTrack ohayooHeaderSetObject:@"channel_123" forKey:OhayooCustomHeaderKeyPackageChannel]; 52 | @code 53 | */ 54 | - (void)ohayooHeaderSetObject:(NSObject *)object forKey:(OhayooCustomHeaderKey)key; 55 | 56 | - (void)ohayooHeaderRemoveObjectForKey:(OhayooCustomHeaderKey)key; 57 | 58 | @end 59 | 60 | 61 | #pragma mark - SharedOhayooGameTrack 62 | @interface BDAutoTrack (SharedOhayooGameTrack) 63 | 64 | /** 65 | 初始化信息:gt_init_info 66 | lev int 当前玩家等级 67 | scene_id int 当前场景id 68 | scene_lev int 当前场景的用户等级 69 | coin_type string 获得货币的类型 70 | coin_left int 用户身上剩余的货币数量 71 | roleId string 角色id 72 | 触发条件:用户启动游戏,初始化完成时上报 73 | 74 | @discussion 上报参数比GameTrack的多了 sceneID sceneLev 75 | */ 76 | + (void)gameInitInfoEventWithLevel:(NSInteger)level 77 | sceneID:(NSInteger)sceneID 78 | sceneLev:(NSInteger)sceneLev 79 | coinType:(NSString *)coinType 80 | coinLeft:(NSInteger)coinLeft 81 | roleId:(NSString *)roleId 82 | otherParams:(nullable NSDictionary *)otherParams; 83 | 84 | /** 85 | @abstract 将相应ohayoo字段设置到custom header中的辅助方法。实际上是调用`setCustomHeaderValue:forKey:`。 86 | @discussion 使用示例: 87 | @code 88 | [BDAutoTrack ohayooHeaderSetObject:@"channel_123" forKey:OhayooCustomHeaderKeyPackageChannel]; 89 | @code 90 | */ 91 | + (void)ohayooHeaderSetObject:(NSObject *)object forKey:(OhayooCustomHeaderKey)key; 92 | 93 | + (void)ohayooHeaderRemoveObjectForKey:(OhayooCustomHeaderKey)key; 94 | 95 | 96 | @end 97 | 98 | NS_ASSUME_NONNULL_END 99 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrack+Profile.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrack+Profile.h 3 | // Applog 4 | // 5 | // Created by 朱元清 on 2020/9/11. 6 | // 7 | 8 | #import "BDAutoTrack.h" 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface BDAutoTrack (Profile) 13 | 14 | #pragma mark 实例方法 15 | /// @abstract 设置一组profile属性 16 | /// @discussion 参数字典的值只能是以下类型:字符串、整型、浮点型、字符串数组 17 | /// @param profileDict 字典。包含一个或多个要设置的profile属性和值 18 | - (void)profileSet:(NSDictionary *)profileDict; 19 | 20 | /// @abstract 设置一组profile属性。若一个接口是通过重复调用该接口无效。 21 | /// @discussion 与profileSet接口不同的是:若某profile已成功通过setOnce接口设置,那么对该profile再次调用setOnce接口无效。 22 | /// 一个通过setOnce设置的profile被unset后,无法再次通过setOnce设置。 23 | /// 参数字典的值只能是以下类型:字符串、整型、浮点型、字符串数组 24 | /// @param profileDict 字典。包含一个或多个要设置的profile属性和值 25 | - (void)profileSetOnce:(NSDictionary *)profileDict; 26 | 27 | /// @abstract unset一个之前被profileSet或profileSetOnce接口设置的profile 28 | /// @param profileName 要unset的profile的名称 29 | - (void)profileUnset:(NSString *)profileName; 30 | 31 | /// @abstract 为数值类型的profile属性做自增操作 32 | /// @discussion 只能自增整数(可以为负整数)。如果传入浮点数,SDK将忽略。 33 | /// @param profileDict 字典。包含一个或多个要设置的数值类型profile属性和要增加的值。 34 | - (void)profileIncrement:(NSDictionary *)profileDict; 35 | 36 | /// @abstract 为数组类型的profile属性添加一个值 37 | /// @discussion 参数字典的值只能为字符串或者字符串数组。e.g. 38 | /// @code 39 | /// NSDitcionary *profileDict = @{ 40 | /// @"needs": @"洗衣机", 41 | /// @"favorites": @[@"海尔", @"海信", @"美的"] 42 | /// } 43 | /// [track profileAppend:profileDict]; 44 | /// @param profileDict 字典。包含一个或多个要设置的数组类型的profile属性和要添加的值 45 | - (void)profileAppend:(NSDictionary *)profileDict; 46 | 47 | #pragma mark 类方法 48 | /// @abstract 设置一组profile属性 49 | /// @discussion 参数字典的值只能是以下类型:字符串、整型、浮点型、字符串数组 50 | /// @param profileDict 字典。包含一个或多个要设置的profile属性和值 51 | + (void)profileSet:(NSDictionary *)profileDict; 52 | 53 | /// @abstract 设置一组profile属性。若一个接口是通过重复调用该接口无效。 54 | /// @discussion 与profileSet接口不同的是:若某profile已成功通过setOnce接口设置,那么对该profile再次调用setOnce接口无效。 55 | /// 一个通过setOnce设置的profile被unset后,无法再次通过setOnce设置。 56 | /// 参数字典的值只能是以下类型:字符串、整型、浮点型、字符串数组 57 | /// @param profileDict 字典。包含一个或多个要设置的profile属性和值 58 | + (void)profileSetOnce:(NSDictionary *)profileDict; 59 | 60 | /// @abstract unset一个之前被profileSet或profileSetOnce接口设置的profile 61 | /// @param profileName 要unset的profile的名称 62 | + (void)profileUnset:(NSString *)profileName; 63 | 64 | /// @abstract 为数值类型的profile属性做自增操作 65 | /// @discussion 只能自增整数(可以为负整数)。如果传入浮点数,SDK将忽略。 66 | /// @param profileDict 字典。包含一个或多个要设置的数值类型profile属性和要增加的值。 67 | + (void)profileIncrement:(NSDictionary *)profileDict; 68 | 69 | /// @abstract 为数组类型的profile属性添加一个值 70 | /// @discussion 参数字典的值只能为字符串或者字符串数组。e.g. 71 | /// @code 72 | /// NSDitcionary *profileDict = @{ 73 | /// @"needs": @"洗衣机", 74 | /// @"favorites": @[@"海尔", @"海信", @"美的"] 75 | /// } 76 | /// [BDAutoTrack profileAppend:profileDict]; 77 | /// @param profileDict 字典。包含一个或多个要设置的数组类型的profile属性和要添加的值 78 | + (void)profileAppend:(NSDictionary *)profileDict; 79 | 80 | 81 | @end 82 | 83 | NS_ASSUME_NONNULL_END 84 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrack+Special.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrack+Special.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/6/2. 6 | // 7 | 8 | #import "BDAutoTrack.h" 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | /*! 13 | BDAutoTrack 内部支持上报接口,外部客户请勿调用 14 | */ 15 | @interface BDAutoTrack (Special) 16 | 17 | + (NSDictionary *)specialParamsWitAppID:(NSString *)appID 18 | appName:(NSString *)appName 19 | type:(NSString *)productType __attribute__((deprecated("推荐使多实例上报"))); 20 | 21 | - (BOOL)eventV3:(NSString *)event params:(nullable NSDictionary *)params specialParams:(NSDictionary *)specialParams __attribute__((deprecated("推荐使多实例上报"))); 22 | 23 | - (BOOL)customEvent:(NSString *)category params:(NSDictionary *)params __attribute__((deprecated("推荐使多实例上报"))); 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrackCacheRemover.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackCacheRemover.h 3 | // RangersAppLog 4 | // 5 | // Created by 朱元清 on 2020/11/2. 6 | // 7 | 8 | #import 9 | #import "RangersAppLog.h" 10 | 11 | /** 12 | 本文件包含SDK缓存的接口。仅限于开发调试阶段清除SDK缓存之用途。生产环境禁止使用! 13 | 本文件接口主要是为了自动化测试中快速删除缓存。 14 | 如果您不是自动化测试,建议通过在手机或模拟器上删除应用的方式来清除缓存,更方便快捷;不必使用本文件的接口。 15 | */ 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface BDAutoTrackCacheRemover : NSObject 20 | 21 | 22 | /*********************************** SDK私有缓存 ************************************/ 23 | /// 永久删除 SDK 私有缓存(包括deviceID\ssID\installID\userUniqueID\ABTest配置等信息) 24 | - (void)removeDefaultsForAppID:(NSString *)appID; 25 | 26 | 27 | /*********************************** StandardDefaults ************************************/ 28 | /// 临时将应用层移除出StandardDefaults的搜索列表 29 | - (void)removeCurrentBundleFromStandardDefaultsSearchList; 30 | 31 | /// 永久删除 StandardDefaults 的应用层缓存 32 | - (void)removeCurrentBundleFromStandardDefaults; 33 | 34 | 35 | /*********************************** KeyChain ************************************/ 36 | /// 删除SDK再 keychian 中的缓存 37 | - (void)removeKeychainForAppID:(NSString *)appID serviceVendor:(BDAutoTrackServiceVendor)vendor; 38 | 39 | @end 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrackConfig+AppLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackConfig+AppLog.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2020/3/25. 6 | // 7 | 8 | #import "BDAutoTrackConfig.h" 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface BDAutoTrackConfig (AppLog) 13 | 14 | /*! @abstract 是否开启无埋点。同时需要在Tea配置。 15 | @discussion 如果设置NO且Tea平台配置NO,则不会采集无埋点事件 16 | @discussion 如果设置NO且Tea平台配置YES,则拉取配置成功后开始采集无埋点事件 17 | @discussion 如果设置YES且Tea平台配置NO,则拉取配置成功后停止采集无埋点事件 18 | @discussion 如果设置YES且Tea平台配置YES,则采集无埋点事件 19 | */ 20 | @property (nonatomic, assign) BOOL autoTrackEnabled; 21 | 22 | /*! @abstract 游戏模式,开启游戏模式会默认上报游戏心跳事件 */ 23 | @property (nonatomic, assign) BOOL gameModeEnable; 24 | 25 | /*! @abstract 是否自动激活。默认YES,一般情况请不要修改 */ 26 | @property (nonatomic, assign) BOOL autoActiveUser; 27 | 28 | /*! @abstract 采集事件的时候输出日志,在控制台中可以查看 29 | @discussion 需要同时设置logger,因为NSLog低效,且在iOS 13中有问题。release版本请设置为NO 30 | */ 31 | @property (nonatomic, assign) BOOL showDebugLog; 32 | 33 | /*! @abstract 采集事件的时候输出日志,在控制台中可以查看 34 | @discussion logger为nil,则不会输出日志 35 | */ 36 | @property (nonatomic, copy, nullable) BDAutoTrackLogger logger; 37 | 38 | /*! @abstract 日志上报是否加密。用于debug情况可以抓包调试 */ 39 | @property (nonatomic, assign) BOOL logNeedEncrypt; 40 | 41 | /*! @abstract 是否自动拉配置。默认YES,一般情况请不要修改。仅私有化部署情况,可能不需要自动拉取配置 */ 42 | @property (nonatomic, assign) BOOL autoFetchSettings; 43 | 44 | /*! @abstract 是否开AB。默认YES,一般情况请不要修改 */ 45 | @property (nonatomic, assign) BOOL abEnable; 46 | 47 | @end 48 | 49 | NS_ASSUME_NONNULL_END 50 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrackConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackConfig.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2020/3/25. 6 | // 7 | 8 | #import 9 | #import "BDCommonDefine.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BDAutoTrackConfig : NSObject 14 | 15 | /*! @abstract channel默认 @"App Store", Release版本只有 @"App Store", debug版本可以任意设置. */ 16 | @property (nonatomic, copy) NSString *channel; 17 | 18 | /*! @abstract 申请appID时候填写的英文名称 */ 19 | @property (nonatomic, copy, nullable) NSString *appName; 20 | 21 | /*! @abstract AppID,非空,必须设置 */ 22 | @property (nonatomic, copy) NSString *appID; 23 | 24 | /*! @abstract 默认国内,初始化时一定要传正确的值 25 | @discussion 发生变化时候请调用 `+[BDAutoTrack setServiceVendor:]`更新值 26 | @discussion 会影响注册和日志上报。所以如果发生变化后,下次启动初始化请传入正确的值 27 | */ 28 | @property (nonatomic, copy) BDAutoTrackServiceVendor serviceVendor; 29 | 30 | 31 | /*! @abstract 根据App ID获取一个config 32 | @param appID AppID 33 | @result 一个config实例, 其他参数非必填,或者有默认值,可以直接通过setter 设置 34 | */ 35 | + (instancetype)configWithAppID:(NSString *)appID; 36 | 37 | 38 | /*! 39 | 使用示例1: 40 | BDAutoTrackConfig *config = [BDAutoTrackConfig configWithSecondAppID:appid]; 41 | // 初始化完成之后,可以调用其他接口 42 | BDAutoTrack *track = [BDAutoTrack trackWithConfig:config] 43 | 44 | // 设置一些属性等配置 45 | [track setCurrentUserUniqueID:@"123"]; 46 | 47 | // 开始上报 48 | [track satrtTrack]; 49 | 50 | // 用变量引用住track用于上报 51 | [track eventV3:xxx params:xxx]; 52 | */ 53 | 54 | /*! @abstract 根据App ID获取一个config 55 | @param appID AppID 56 | @result 一个config实例, 此config默认设置了不会激活和拉取settings。可用于第三方SDK需要上报一些事件,但是不需要激活等 57 | */ 58 | + (instancetype)configWithSecondAppID:(NSString *)appID; 59 | 60 | @end 61 | 62 | NS_ASSUME_NONNULL_END 63 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrackNotifications.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackConstants.h 3 | // Pods-BDAutoTracker_Example 4 | // 5 | // Created by bob on 2019/5/16. 6 | // 7 | 8 | #import 9 | 10 | /*! @abstract UIViewController 切换事件通知 11 | userInfo 12 | @{ kBDAutoTrackViewControllerFormer:NSStringFromClass(from.class), 13 | kBDAutoTrackViewControllerAfter:NSStringFromClass(to.class), 14 | kBDAutoTrackSwitchIsBack:@(isBack) 15 | }; 16 | @discussion 通知在主线程,一般情况下监听后,请勿同步进行耗时操作 17 | */ 18 | FOUNDATION_EXTERN NSString * const BDAutoTrackVCSwitchEventNotification; 19 | 20 | FOUNDATION_EXTERN NSString * const kBDAutoTrackViewControllerFormer; 21 | FOUNDATION_EXTERN NSString * const kBDAutoTrackViewControllerAfter; 22 | FOUNDATION_EXTERN NSString * const kBDAutoTrackSwitchIsBack; 23 | 24 | /*! @abstract SDK 注册成功通知 25 | userInfo 26 | @{ kBDAutoTrackNotificationAppID :appID, 27 | kBDAutoTrackNotificationRangersDeviceID :did, 28 | kBDAutoTrackNotificationSSID :ssid, 29 | kBDAutoTrackNotificationInstallID :iid 30 | kBDAutoTrackNotificationUserUniqueID :uuid 31 | }; 32 | @discussion 通知在子线程,uuid可能为 nil. 33 | @discussion 初始化 SDK 的时候,如果本地已经有 ID 值,会有一次通知 34 | 触发重新注册请求后,请求成功会有另一次通知 35 | 触发条件: 36 | 1. -[BDAuTrack startTrack] 37 | 2. -[BDAuTrack setCurrentUserUniqueID:] 且与上次不一致,包括 nil 38 | 3. -[BDAuTrack setServiceVendor:] 且与上次不一致 39 | */ 40 | FOUNDATION_EXTERN NSString * const BDAutoTrackNotificationRegisterSuccess; 41 | 42 | /*! 43 | @abstract SDK 注册请求失败通知。SDK在注册阶段默认有3次重试策略。每一次注册请求的失败都会触发此通知,并携带剩余的重试次数。 44 | userInfo 45 | @{ 46 | @"message": @"register request failure", 47 | @"remainingRetry": 剩余重试机会(次数) 48 | }; 49 | */ 50 | FOUNDATION_EXTERN NSString * const BDAutoTrackNotificationRegisterFailure; 51 | 52 | /*! @abstract SDK 激活成功通知 53 | userInfo 54 | @{ kBDAutoTrackNotificationAppID :appID, 55 | }; 56 | @discussion 通知在子线程,每次触发注册成功后,会触发激活请求 57 | */ 58 | FOUNDATION_EXTERN NSString * const BDAutoTrackNotificationActiveSuccess; 59 | 60 | /*! @abstract SDK ABTest配置拉取成功通知 61 | userInfo 62 | @{ kBDAutoTrackNotificationAppID :appID, 63 | kBDAutoTrackNotificationData :data, 64 | }; 65 | @discussion 通知在子线程,每次触发注册成功后,且该 App ID 配置了 ABTest 功能,会触发 ABTest 配置拉取。 66 | 收到通知成功后,则可以开始读取 ABTest 值,如果未收到通知,则读取的 ABTest 为上次拉取成功的值。 67 | 这里重点说明不需要去解析data的结构,简单check一下data.count == 0 即可 68 | 如果需要获取所有的ABTest配置,请使用 -[BDAutoTrack allABTestConfigs] 接口 69 | */ 70 | FOUNDATION_EXTERN NSString * const BDAutoTrackNotificationABTestSuccess; 71 | 72 | /*! @abstract SDK通知的userInfo的 key 定义 73 | */ 74 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationAppID; 75 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationRangersDeviceID; 76 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationSSID; 77 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationInstallID; 78 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationUserUniqueID; 79 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationData; 80 | 81 | /*! @abstract SDK ABTestVid发生变化时候的通知 82 | userInfo 83 | @{ kBDAutoTrackNotificationAppID :appID, 84 | kBDAutoTrackNotificationABTestVids :vids, 85 | kBDAutoTrackNotificationABTestExternalVids:externalVids 86 | }; 87 | @discussion 通知在子线程,每次Vid发生变化时触发。需要该 App ID 配置了 ABTest 功能,否则不会有通知。 88 | */ 89 | FOUNDATION_EXTERN NSString * const BDAutoTrackNotificationABTestVidsChanged; 90 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationABTestVids; 91 | FOUNDATION_EXTERN NSString * const kBDAutoTrackNotificationABTestExternalVids; 92 | 93 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDAutoTrackSchemeHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackSchemeHandler.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/9/24. 6 | // 7 | 8 | #import 9 | #import "BDCommonDefine.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /* 如果是iOS 13中重写UISceneDelegate的回调,则按照i以下code 14 | - (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts { 15 | for (UIOpenURLContext *context in URLContexts) { 16 | NSURL *URL = context.URL; 17 | if ([[BDAutoTrackSchemeHandler sharedHandler] handleURL:URL appID:@"appid" scene:scene]) { 18 | continue; 19 | } 20 | 21 | /// your handle code for the URL 22 | } 23 | } 24 | 25 | 如果是iOS 13一下,重写UIApplicationDelegate的回调方法,则参考以下code 26 | - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { 27 | if ([[BDAutoTrackSchemeHandler sharedHandler] handleURL:url appID:@"appid" scene:nil]) { 28 | return YES; 29 | } 30 | 31 | /// your handle code 32 | 33 | return NO; 34 | } 35 | */ 36 | 37 | @interface BDAutoTrackSchemeHandler : NSObject 38 | 39 | + (instancetype)sharedHandler; 40 | 41 | - (BOOL)handleURL:(NSURL *)URL appID:(NSString *)appID scene:(nullable id)scene; 42 | 43 | - (void)registerHandler:(id)handler; 44 | - (void)unregisterHandler:(id)handler; 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDCommonDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDCommonDefine.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2020/3/25. 6 | // 7 | 8 | #import 9 | #import "BDCommonEnumDefine.h" 10 | 11 | #define APPLOG_API_AVALIABLE(x) 12 | #define APPLOG_API_DEPRECATED 13 | #define APPLOG_API_DEPRECATED_WITH_REPLACEMENT(msg, ver) 14 | // 编译时断言 15 | #define APPLOG_STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1] 16 | 17 | #ifndef BDCommonDefine_h 18 | #define BDCommonDefine_h 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | /* 23 | request IDFA handler 24 | */ 25 | typedef void (^BDAutoTrackAuthorizationHandler)(BDAutoTrackAuthorizationStatus status); 26 | 27 | /*! @abstract 日志输出 28 | @param log 输出的日志 29 | @discussion 请使用自己的日志SDK输出日志 30 | */ 31 | typedef void(^BDAutoTrackLogger)(NSString * _Nullable log); 32 | 33 | 34 | /*! @abstract 自定义请求链接,把相关请求发送到对应的自定义的URL上 35 | @param vendor 地区 36 | @param requestURLType 上面的六个枚举值 37 | @discussion 一般情况不需要实现;如果实现,针对想改变的枚举值返回一个准确的URL,其他不想修改的返回nil即可 38 | @result 返回自定义的URL 39 | */ 40 | typedef NSString * _Nullable (^BDAutoTrackRequestURLBlock)(BDAutoTrackServiceVendor vendor, BDAutoTrackRequestURLType requestURLType); 41 | 42 | /*! @abstract 自定义请求链接的Host,把相关请求发送到对应的自定义的Host上,path仍然按照SDK规则拼接 43 | @param vendor 地区 44 | @param requestURLType 上面的六个枚举值 45 | @discussion 一般情况不需要实现;如果实现,返回值类似 https://github.com/ 46 | @result 返回自定义的URL 47 | */ 48 | typedef NSString * _Nullable (^BDAutoTrackRequestHostBlock)(BDAutoTrackServiceVendor vendor, BDAutoTrackRequestURLType requestURLType); 49 | 50 | 51 | /*! @abstract 自定义上报信息 52 | @discussion 每次上报都会回调,设置一次即可,格式要求同日志要求,需要可序列化;如果无法序列化,会被丢弃 53 | @result NSDictionary custom数据 54 | */ 55 | typedef NSDictionary *_Nonnull (^BDAutoTrackCustomHeaderBlock)(void); 56 | 57 | @protocol BDAutoTrackSchemeHandler 58 | 59 | /*! @abstract 处理scheme 60 | @discussion 请参考下面接口调用示例 61 | @param URL scheme的完整URL,透传参数 62 | @param appID 初始化SDK的AppID 63 | @param scene 适配iOS 13的参数,透传参数 64 | @result 返回YES,表示已经处理了该URL,NO表示没有处理 65 | */ 66 | - (BOOL)handleURL:(NSURL *)URL appID:(NSString *)appID scene:(nullable id)scene; 67 | 68 | @end 69 | 70 | NS_ASSUME_NONNULL_END 71 | #endif /* BDCommonDefine_h */ 72 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/BDCommonEnumDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDCommonEnumDefine.h 3 | // RangersAppLog 4 | // 5 | // Created by 朱元清 on 2020/8/10. 6 | // 7 | 8 | #import 9 | 10 | #ifndef BDCommonEnumDefine_h 11 | #define BDCommonEnumDefine_h 12 | 13 | /*! @abstract 日志上报地区属性 14 | @discussion 上报地区请勿擅自选择,需要与申请服务的地区一致,或者咨询接口人确认 15 | */ 16 | typedef NSString* BDAutoTrackServiceVendor NS_EXTENSIBLE_STRING_ENUM; 17 | FOUNDATION_EXTERN BDAutoTrackServiceVendor const BDAutoTrackServiceVendorPrivate; // 私有化,此时一定要设置BDAutoTrackRequestURLBlock 18 | 19 | 20 | 21 | /*! 22 | 请求URL type 23 | */ 24 | typedef NSInteger BDAutoTrackRequestURLType NS_TYPED_ENUM; 25 | 26 | FOUNDATION_EXTERN BDAutoTrackRequestURLType const BDAutoTrackRequestURLRegister; /// 注册 27 | FOUNDATION_EXTERN BDAutoTrackRequestURLType const BDAutoTrackRequestURLActivate; /// 激活 28 | FOUNDATION_EXTERN BDAutoTrackRequestURLType const BDAutoTrackRequestURLSettings; /// 基本配置 29 | FOUNDATION_EXTERN BDAutoTrackRequestURLType const BDAutoTrackRequestURLABTest; /// ABTest配置 30 | FOUNDATION_EXTERN BDAutoTrackRequestURLType const BDAutoTrackRequestURLLog; /// 日志上报 31 | FOUNDATION_EXTERN BDAutoTrackRequestURLType const BDAutoTrackRequestURLLogBackup;/// 日志上报备用 32 | FOUNDATION_EXTERN BDAutoTrackRequestURLType const BDAutoTrackRequestURLSuccessRatio; /// 成功率日志上报 33 | 34 | 35 | typedef NS_ENUM(NSUInteger, BDAutoTrackLaunchFrom) { 36 | /// 初始状态 37 | BDAutoTrackLaunchFromInitialState = 0, 38 | /// 用户手动点击进入app 39 | BDAutoTrackLaunchFromUserClick, 40 | /// 用户通过push点击进入app 41 | BDAutoTrackLaunchFromRemotePush, 42 | /// 用户通过widget点击进入app 43 | BDAutoTrackLaunchFromWidget, 44 | /// 用户通过sptlight点击进入app 45 | BDAutoTrackLaunchFromSpotlight, 46 | /// 用户通过外部app唤醒进入app 47 | BDAutoTrackLaunchFromExternal, 48 | /// 用户手动切回前台 49 | BDAutoTrackLaunchFromBackground, 50 | /// from siri 51 | BDAutoTrackLaunchFromSiri, 52 | }; 53 | 54 | /** 55 | IDFA Authorization Status 56 | */ 57 | typedef NS_ENUM(NSInteger, BDAutoTrackAuthorizationStatus) { 58 | BDAutoTrackAuthorizationStatusNotDetermined = 0, 59 | BDAutoTrackAuthorizationStatusRestricted, 60 | BDAutoTrackAuthorizationStatusDenied, 61 | BDAutoTrackAuthorizationStatusAuthorized 62 | }; 63 | 64 | #endif /* BDCommonEnumDefine_h */ 65 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/RangersAppLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // RangersAppLog.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2020/4/1. 6 | // 7 | 8 | #ifndef RangersAppLog_h 9 | #define RangersAppLog_h 10 | 11 | #import 12 | 13 | #if __has_include() 14 | #import 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | 22 | #import 23 | #import 24 | 25 | #import 26 | #import 27 | 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | #import 34 | #import 35 | 36 | #import 37 | #import 38 | 39 | #endif 40 | 41 | #if __has_include() 42 | #import 43 | 44 | #import 45 | #import 46 | #import 47 | #import 48 | #endif 49 | 50 | #if __has_include() 51 | #import 52 | #endif 53 | 54 | #if __has_include() 55 | #import 56 | #endif 57 | 58 | #if __has_include() 59 | #import 60 | #endif 61 | 62 | #if __has_include() 63 | #import 64 | #endif 65 | 66 | #if __has_include() 67 | #import 68 | #endif 69 | 70 | #endif /* RangersAppLog_h */ 71 | 72 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/RangersAppLog.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Core/RangersAppLog.m -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/RangersAppLogCore.h: -------------------------------------------------------------------------------- 1 | // 2 | // RangersAppLogCore.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/10/17. 6 | // 7 | 8 | #ifndef RangersAppLogCore_h 9 | #define RangersAppLogCore_h 10 | 11 | #import "BDCommonDefine.h" 12 | #import "BDAutoTrackConfig.h" 13 | #import "BDAutoTrackConfig+AppLog.h" 14 | 15 | #import "BDAutoTrack.h" 16 | 17 | #import "BDAutoTrack+Game.h" 18 | #import "BDAutoTrack+GameTrack.h" 19 | #import "BDAutoTrack+Special.h" 20 | #import "BDAutoTrack+OhayooGameTrack.h" 21 | 22 | #import "BDAutoTrackSchemeHandler.h" 23 | #import "BDAutoTrackNotifications.h" 24 | 25 | #import 26 | #if __has_include() 27 | #import 28 | #endif 29 | 30 | #if __has_include() 31 | #import 32 | #endif 33 | 34 | #if __has_include() 35 | #import 36 | #endif 37 | 38 | 39 | #endif /* RangersAppLogCore_h */ 40 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Core/libRangersAppLog_Core_union.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Core/libRangersAppLog_Core_union.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/Host/CN/BDAutoTrackURLHostItemCN.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackURLHostItemCN.h 3 | // RangersAppLog-RangersAppLog 4 | // 5 | // Created by 朱元清 on 2020/8/6. 6 | // 7 | 8 | #import "BDCommonEnumDefine.h" 9 | 10 | FOUNDATION_EXPORT BDAutoTrackServiceVendor const BDAutoTrackServiceVendorCN; 11 | 12 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Host/CN/libRangersAppLog_Host_CN.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Host/CN/libRangersAppLog_Host_CN.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/Host/SG/BDAutoTrackURLHostItemSG.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackURLHostItemSG.h 3 | // RangersAppLog 4 | // 5 | // Created by 朱元清 on 2020/8/6. 6 | // 7 | 8 | #import "BDCommonEnumDefine.h" 9 | 10 | FOUNDATION_EXPORT BDAutoTrackServiceVendor const BDAutoTrackServiceVendorSG; 11 | 12 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Host/SG/libRangersAppLog_Host_SG.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Host/SG/libRangersAppLog_Host_SG.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/Host/VA/BDAutoTrackURLHostItemVA.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackURLHostItemVA.h 3 | // RangersAppLog 4 | // 5 | // Created by 朱元清 on 2020/8/6. 6 | // 7 | 8 | #import "BDCommonEnumDefine.h" 9 | 10 | FOUNDATION_EXPORT BDAutoTrackServiceVendor const BDAutoTrackServiceVendorVA; 11 | 12 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Host/VA/libRangersAppLog_Host_VA.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Host/VA/libRangersAppLog_Host_VA.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/Log/libRangersAppLog_Debugger.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Log/libRangersAppLog_Debugger.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/Picker/RangersAppLogPicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // RangersAppLogPicker.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2020/4/1. 6 | // 7 | 8 | #ifndef RangersAppLogPicker_h 9 | #define RangersAppLogPicker_h 10 | 11 | 12 | #endif /* RangersAppLogPicker_h */ 13 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Picker/libRangersAppLog_Picker.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Picker/libRangersAppLog_Picker.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/UITracker/BDKeyWindowTracker.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDKeyWindowTracker.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/8/12. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | UIKIT_EXTERN NSString * const BDDefaultScene; 13 | 14 | @interface BDKeyWindowTracker : NSObject 15 | 16 | /*! @abstract keyWindow for BDDefaultScene 17 | @discussion setter等同于调用`-[BDKeyWindowTracker trackScene:BDDefaultScene keyWindow:keyWindow]` 18 | @discussion getter等同于调用`-[BDKeyWindowTracker keyWindowForScene:BDDefaultScene]` 19 | @discussion 如果只有一个Scene,或者说没有Scene,比如低于iOS 13,则可以只使用keyWindow属性即可 20 | */ 21 | @property (nonatomic, strong, nullable) UIWindow *keyWindow; 22 | 23 | + (instancetype)sharedInstance; 24 | 25 | /*! @abstract 设置scene的keywindow 26 | @discussion 发生变化可以更新,不需要一直重复设置 27 | @param scene 某个UIWindowScene的唯一标志,推荐使用 scene = [NSString stringWithFormat:@"%p",windowScene]; 28 | @param keyWindow 该scene的keywindow 29 | */ 30 | - (void)trackScene:(NSString *)scene keyWindow:(nullable UIWindow *)keyWindow; 31 | 32 | /*! @abstract 获取该scene的keywindow 33 | @param scene 某个UIWindowScene的唯一标志,推荐使用 scene = [NSString stringWithFormat:@"%p",windowScene]; 34 | @result keyWindow 返回该scene的keywindow 35 | */ 36 | - (nullable UIWindow *)keyWindowForScene:(NSString *)scene; 37 | 38 | /*! @abstract 移除scene的keywindow 39 | @param scene 某个UIWindowScene的唯一标志,推荐使用 scene = [NSString stringWithFormat:@"%p",windowScene]; 40 | */ 41 | - (void)removeKeyWindowForScene:(NSString *)scene; /// when you want set nil 42 | 43 | @end 44 | 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/UITracker/RangersAppLogUITrack.h: -------------------------------------------------------------------------------- 1 | // 2 | // RangersAppLogUITrack.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2019/10/17. 6 | // 7 | 8 | #ifndef RangersAppLogUITrack_h 9 | #define RangersAppLogUITrack_h 10 | 11 | #import "RangersAppLogCore.h" 12 | 13 | #import "UIBarButtonItem+TrackInfo.h" 14 | #import "UIView+TrackInfo.h" 15 | #import "UIViewController+TrackInfo.h" 16 | #import "BDKeyWindowTracker.h" 17 | 18 | #endif /* RangersAppLogUITrack_h */ 19 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/UITracker/UIBarButtonItem+TrackInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIBarButtonItem+TrackInfo.h 3 | // Applog 4 | // 5 | // Created by bob on 2019/1/21. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface UIBarButtonItem (TrackInfo) 13 | 14 | /*! @abstract 手动设置的导航栏按钮 ID 15 | @discussion 如果设置,被点击的时候会采集,可以唯一标志a该导航栏按钮 16 | */ 17 | @property (nonatomic, copy) NSString *bdAutoTrackID; 18 | 19 | /*! @abstract 手动设置的导航栏按钮 content 20 | @discussion 如果设置,被点击的时候会采集 21 | */ 22 | @property (nonatomic, copy) NSString *bdAutoTrackContent; 23 | 24 | /*! @abstract 手动设置的extra信息 25 | @discussion 如果设置,被点击的时候会采集 26 | */ 27 | @property (nonatomic, copy) NSDictionary *bdAutoTrackExtraInfos; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/UITracker/UIView+TrackInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+AutoTrack.h 3 | // Applog 4 | // 5 | // Created by bob on 2019/1/15. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface UIView (TrackInfo) 13 | 14 | /*! @abstract 手动设置的ViewID 15 | @discussion 如果设置,被点击的时候会采集,可以唯一标志该View 16 | */ 17 | @property (nonatomic, copy) NSString *bdAutoTrackViewID; 18 | 19 | /*! @abstract 手动设置的ViewContent 20 | @discussion如果设置,被点击的时候会采集 21 | */ 22 | @property (nonatomic, copy) NSString *bdAutoTrackViewContent; 23 | 24 | /*! @abstract 手动设置的extra信息 25 | @discussion 如果设置,被点击的时候会采集 26 | */ 27 | @property (nonatomic, copy) NSDictionary *bdAutoTrackExtraInfos; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/UITracker/UIViewController+TrackInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+AutoTrack.h 3 | // Applog 4 | // 5 | // Created by bob on 2019/1/20. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface UIViewController (TrackInfo) 13 | 14 | /*! @abstract 手动设置的PageTitle 15 | @discussion 如果设置,页面切换的时候会采集 16 | @discussion 如果设置,该VC里面的View被点击的时候会采集 17 | */ 18 | @property (nonatomic, copy) NSString *bdAutoTrackPageTitle; 19 | 20 | /*! @abstract 手动设置的PageID 21 | @discussion 如果设置,页面切换的时候会采集 22 | @discussion 如果设置,该VC里面的View被点击的时候会采集 23 | */ 24 | @property (nonatomic, copy) NSString *bdAutoTrackPageID; 25 | 26 | /*! @abstract 手动设置的extra信息 27 | @discussion 如果设置,页面切换的时候会采集 28 | @discussion 如果设置,该VC里面的View被点击的时候会采集 29 | */ 30 | @property (nonatomic, copy) NSDictionary *bdAutoTrackExtraInfos; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/UITracker/libRangersAppLog_UITracker.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/UITracker/libRangersAppLog_UITracker.a -------------------------------------------------------------------------------- /RangersAppLog/Classes/Unique/BDAutoTrackIDFA.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDAutoTrackIDFA.h 3 | // RangersAppLog 4 | // 5 | // Created by bob on 2020/8/28. 6 | // 7 | 8 | #import "BDCommonDefine.h" 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface BDAutoTrackIDFA : NSObject 13 | 14 | /** 15 | if you want to use idfa, you should request Authorization 16 | */ 17 | + (BDAutoTrackAuthorizationStatus)authorizationStatus; 18 | + (void)requestAuthorizationWithHandler:(nullable BDAutoTrackAuthorizationHandler)completion; 19 | + (nullable NSString *)trackingIdentifier; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /RangersAppLog/Classes/Unique/libRangersAppLog_Unique.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytedance/RangersAppLog/60469f7be6491c7c5c2d26a4b266efc6d2be05a1/RangersAppLog/Classes/Unique/libRangersAppLog_Unique.a --------------------------------------------------------------------------------