├── android ├── .gitignore ├── .npmignore ├── src │ └── main │ │ ├── java │ │ └── in │ │ │ └── esseak │ │ │ ├── Main.java │ │ │ └── react_native_umeng │ │ │ ├── UmengPackage.java │ │ │ └── UmengModule.java │ │ ├── res │ │ └── values │ │ │ └── strings.xml │ │ └── AndroidManifest.xml ├── libs │ └── umeng-analytics-v5.6.7.jar ├── build.gradle ├── proguard-rules.pro └── rn-umeng.iml ├── .gitignore ├── ios └── RCTUmeng │ ├── RCTUmeng │ ├── UMAnalytics_Sdk │ │ ├── v_4.2.4 │ │ └── UMMobClick.framework │ │ │ ├── Versions │ │ │ ├── Current │ │ │ └── A │ │ │ │ ├── UMMobClick │ │ │ │ └── Headers │ │ │ │ ├── MobClickSocialAnalytics.h │ │ │ │ ├── MobClickGameAnalytics.h │ │ │ │ └── MobClick.h │ │ │ ├── Headers │ │ │ └── UMMobClick │ ├── RCTUmeng.h │ └── RCTUmeng.m │ └── RCTUmeng.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── aevit.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ ├── xcuserdata │ └── aevit.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── RCTUmeng.xcscheme │ └── project.pbxproj ├── screenshots ├── screenshot0.png └── screenshot1.png ├── package.json ├── main.js └── README.md /android/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /android/.npmignore: -------------------------------------------------------------------------------- 1 | /build 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_* 3 | *.log 4 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/v_4.2.4: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/UMMobClick: -------------------------------------------------------------------------------- 1 | Versions/Current/UMMobClick -------------------------------------------------------------------------------- /android/src/main/java/in/esseak/Main.java: -------------------------------------------------------------------------------- 1 | package in.esseak; 2 | 3 | public class Main { 4 | } 5 | -------------------------------------------------------------------------------- /screenshots/screenshot0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esseak/rn-umeng/HEAD/screenshots/screenshot0.png -------------------------------------------------------------------------------- /screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esseak/rn-umeng/HEAD/screenshots/screenshot1.png -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | rn-umeng 3 | 4 | -------------------------------------------------------------------------------- /android/libs/umeng-analytics-v5.6.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esseak/rn-umeng/HEAD/android/libs/umeng-analytics-v5.6.7.jar -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/Versions/A/UMMobClick: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esseak/rn-umeng/HEAD/ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/Versions/A/UMMobClick -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng.xcodeproj/project.xcworkspace/xcuserdata/aevit.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esseak/rn-umeng/HEAD/ios/RCTUmeng/RCTUmeng.xcodeproj/project.xcworkspace/xcuserdata/aevit.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rn-umeng", 3 | "version": "1.0.6", 4 | "description": "RN-Umeng", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "test" 8 | }, 9 | "keywords": [ 10 | "react native", 11 | "umeng" 12 | ], 13 | "author": "mike", 14 | "license": "MIT" 15 | } 16 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/RCTUmeng.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTUmeng.h 3 | // RCTUmeng 4 | // 5 | // Created by aevit on 2017/7/26. 6 | // Copyright © 2017年 aevit. All rights reserved. 7 | // 8 | 9 | #import 10 | #if __has_include() 11 | #import 12 | #else 13 | #import "RCTBridgeModule.h" 14 | #endif 15 | 16 | @interface RCTUmeng : NSObject 17 | - (void) startWithAppkey:(NSString *) appkey; 18 | - (void) setDebugMode:(BOOL)value; 19 | - (void) onEvent:(NSString *)eventId attributes:(NSDictionary *)attributes counter:(NSString *)counter; 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng.xcodeproj/xcuserdata/aevit.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RCTUmeng.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | E175797D1F289A840053007F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile files('libs/umeng-analytics-v5.6.7.jar') 24 | compile 'com.facebook.react:react-native:+' 25 | } 26 | -------------------------------------------------------------------------------- /android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/mike/Desktop/adt-bundle-mac-x86_64-20140702/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /android/src/main/java/in/esseak/react_native_umeng/UmengPackage.java: -------------------------------------------------------------------------------- 1 | package in.esseak.react_native_umeng; 2 | 3 | import com.facebook.react.bridge.JavaScriptModule; 4 | import com.facebook.react.bridge.NativeModule; 5 | import com.facebook.react.bridge.ReactApplicationContext; 6 | import com.facebook.react.ReactPackage; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by mike on 16/4/26. 15 | */ 16 | public class UmengPackage implements ReactPackage { 17 | @Override 18 | public List createNativeModules(ReactApplicationContext reactContext) { 19 | return Arrays.asList(new NativeModule[]{ 20 | new UmengModule(reactContext), 21 | }); 22 | } 23 | 24 | public List> createJSModules() { 25 | return Collections.emptyList(); 26 | } 27 | 28 | @Override 29 | public List createViewManagers(ReactApplicationContext reactContext) { 30 | return Collections.emptyList(); 31 | } 32 | } -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import { NativeModules,Platform } from 'react-native'; 2 | const umengClient = NativeModules.Umeng; 3 | 4 | export default class MobclickAgent{ 5 | 6 | static setCrashReportEnabled(value){ 7 | umengClient.setCrashReportEnabled(true); 8 | } 9 | 10 | static startWithAppkey(value){ 11 | umengClient.startWithAppkey(value); 12 | } 13 | 14 | //android 15 | static startWithAppkeyAndChannel(value,channel){ 16 | umengClient.startWithAppkeyAndChannel(value,channel); 17 | } 18 | 19 | //iOS 20 | static setBackgroundTaskEnabled(value){ 21 | } 22 | 23 | //ios 24 | static setAppVersion(value){ 25 | if(Platform.OS === 'ios') 26 | { 27 | umengClient.setAppVersion(value); 28 | } 29 | } 30 | 31 | static enableEncrypt(value){ 32 | umengClient.enableEncrypt(value); 33 | } 34 | 35 | static onProfileSignIn(puid,provider = undefined){ 36 | umengClient.onProfileSignIn(puid,provider); 37 | } 38 | static onProfileSignOff(){ 39 | umengClient.onProfileSignOff(); 40 | } 41 | static onPageStart(pageName){ 42 | umengClient.onPageStart(pageName); 43 | } 44 | 45 | static onPageEnd(pageName){ 46 | umengClient.onPageEnd(pageName); 47 | } 48 | 49 | //iOS 50 | static onLogPageViewInseconds(pageName,du = 0){ 51 | umengClient.logPageView(pageName,du); 52 | } 53 | 54 | static onEvent(eventId,dataMap = undefined,counter = undefined){ 55 | 56 | if (counter !== undefined) { 57 | counter = counter + ''; 58 | } 59 | umengClient.onEvent(eventId,dataMap,counter); 60 | 61 | } 62 | 63 | static setDebugMode(value){ 64 | umengClient.setDebugMode(value); 65 | } 66 | static setLogEnabled(value){ 67 | umengClient.setDebugMode(value); 68 | } 69 | 70 | //android 71 | static openActivityDurationTrack(value){ 72 | umengClient.openActivityDurationTrack(value); 73 | } 74 | 75 | //android 76 | static onResume(){ 77 | umengClient.onResume(); 78 | } 79 | 80 | //android 81 | static onPause(){ 82 | umengClient.onPause(); 83 | } 84 | 85 | static getDeviceInfo(cb){ 86 | umengClient.getDeviceInfo(function (infoStr) { 87 | cb(infoStr); 88 | }); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng.xcodeproj/xcuserdata/aevit.xcuserdatad/xcschemes/RCTUmeng.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/RCTUmeng.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTUmeng.m 3 | // RCTUmeng 4 | // 5 | // Created by aevit on 2017/7/26. 6 | // Copyright © 2017年 aevit. All rights reserved. 7 | // 8 | 9 | #import "RCTUmeng.h" 10 | 11 | #import 12 | //#import "MobClick.h" 13 | 14 | 15 | @implementation RCTUmeng 16 | 17 | RCT_EXPORT_MODULE(); 18 | 19 | - (dispatch_queue_t)methodQueue 20 | { 21 | return dispatch_get_main_queue(); 22 | } 23 | 24 | RCT_EXPORT_METHOD(setCrashReportEnabled:(BOOL)value) 25 | { 26 | [MobClick setCrashReportEnabled:value]; 27 | } 28 | 29 | RCT_EXPORT_METHOD(enableEncrypt:(BOOL)value) 30 | { 31 | [MobClick setEncryptEnabled:value]; 32 | } 33 | 34 | RCT_EXPORT_METHOD(startWithAppkey:(NSString *)appkey) 35 | { 36 | UMConfigInstance.appKey = appkey; 37 | [MobClick startWithConfigure:UMConfigInstance]; 38 | // [MobClick startWithAppkey:appkey]; 39 | } 40 | 41 | RCT_EXPORT_METHOD(setAppVersion:(NSString*)version) 42 | { 43 | [MobClick setAppVersion:version]; 44 | } 45 | 46 | RCT_EXPORT_METHOD(setDebugMode:(BOOL)value) 47 | { 48 | [MobClick setLogEnabled:value]; 49 | } 50 | 51 | //RCT_EXPORT_METHOD(onProfileSignIn:(NSString *)puid) 52 | //{ 53 | // NSLog(@"onProfileSignIn"); 54 | // [MobClick profileSignInWithPUID:puid]; 55 | //} 56 | 57 | RCT_EXPORT_METHOD(onProfileSignIn:(NSString *)puid provider:(NSString *)provider) 58 | { 59 | [MobClick profileSignInWithPUID:puid provider:provider]; 60 | } 61 | 62 | RCT_EXPORT_METHOD(onProfileSignOff) 63 | { 64 | [MobClick profileSignOff]; 65 | } 66 | 67 | RCT_EXPORT_METHOD(onPageStart:(NSString *)pageName) 68 | { 69 | [MobClick beginLogPageView:pageName]; 70 | } 71 | 72 | RCT_EXPORT_METHOD(onPageEnd:(NSString *)pageName) 73 | { 74 | [MobClick endLogPageView:pageName]; 75 | } 76 | 77 | RCT_EXPORT_METHOD(logPageView:(NSString *)pageName seconds:(int)seconds) 78 | { 79 | [MobClick logPageView:pageName seconds:seconds]; 80 | 81 | } 82 | 83 | RCT_EXPORT_METHOD(onEvent:(NSString *)eventId attributes:(NSDictionary *)attributes counter:(NSString *)counter) 84 | { 85 | if (attributes) { 86 | if (counter) { 87 | int intCounter = counter.intValue; 88 | [MobClick event:eventId attributes:attributes counter:intCounter]; 89 | }else{ 90 | [MobClick event:eventId attributes:attributes]; 91 | } 92 | }else{ 93 | [MobClick event:eventId]; 94 | } 95 | } 96 | 97 | RCT_EXPORT_METHOD(getDeviceInfo:(RCTResponseSenderBlock)callback) 98 | { 99 | Class cls = NSClassFromString(@"UMANUtil"); 100 | SEL deviceIDSelector = @selector(openUDIDString); 101 | NSString *deviceID = nil; 102 | if(cls && [cls respondsToSelector:deviceIDSelector]){ 103 | deviceID = [cls performSelector:deviceIDSelector]; 104 | } 105 | NSData* jsonData = [NSJSONSerialization dataWithJSONObject:@{@"oid" : deviceID} 106 | options:NSJSONWritingPrettyPrinted 107 | error:nil]; 108 | NSString *strInfo = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 109 | callback(@[strInfo]); 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/Versions/A/Headers/MobClickSocialAnalytics.h: -------------------------------------------------------------------------------- 1 | // 2 | // MobClickSocialAnalytics.h 3 | // SocialSDK 4 | // 5 | // Created by yeahugo on 13-3-4. 6 | // Copyright (c) 2013年 Umeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NSString * MobClickSocialTypeString; 12 | 13 | extern MobClickSocialTypeString const MobClickSocialTypeSina; //新浪微博 14 | extern MobClickSocialTypeString const MobClickSocialTypeTencent; //腾讯微博 15 | extern MobClickSocialTypeString const MobClickSocialTypeRenren; //人人网 16 | extern MobClickSocialTypeString const MobClickSocialTypeQzone; //Qzone 17 | extern MobClickSocialTypeString const MobClickSocialTypeRenren; //人人网 18 | extern MobClickSocialTypeString const MobClickSocialTypeDouban; //douban 19 | extern MobClickSocialTypeString const MobClickSocialTypeWxsesion; //微信好友分享 20 | extern MobClickSocialTypeString const MobClickSocialTypeWxtimeline; //微信朋友圈 21 | extern MobClickSocialTypeString const MobClickSocialTypeHuaban; //花瓣 22 | extern MobClickSocialTypeString const MobClickSocialTypeKaixin; //开心 23 | extern MobClickSocialTypeString const MobClickSocialTypeFacebook; //facebook 24 | extern MobClickSocialTypeString const MobClickSocialTypeTwitter; //twitter 25 | extern MobClickSocialTypeString const MobClickSocialTypeInstagram; //instagram 26 | extern MobClickSocialTypeString const MobClickSocialTypeFlickr; //flickr 27 | extern MobClickSocialTypeString const MobClickSocialTypeQQ; //qq 28 | extern MobClickSocialTypeString const MobClickSocialTypeWxfavorite; //微信收藏 29 | extern MobClickSocialTypeString const MobClickSocialTypeLwsession; //来往 30 | extern MobClickSocialTypeString const MobClickSocialTypeLwtimeline; //来往动态 31 | extern MobClickSocialTypeString const MobClickSocialTypeYxsession; //易信 32 | extern MobClickSocialTypeString const MobClickSocialTypeYxtimeline; //易信朋友圈 33 | 34 | 35 | /** 36 | 微博类,发送微博之后在回调方法初始化此对象 37 | 38 | */ 39 | @interface MobClickSocialWeibo : NSObject 40 | 41 | 42 | /** 43 | 微博平台类型,使用上面定义的几种常量字符串 44 | */ 45 | @property (nonatomic, copy) NSString *platformType; 46 | 47 | /** 48 | 微博id 49 | */ 50 | @property (nonatomic, copy) NSString *weiboId; 51 | 52 | /** 53 | 用户在微博平台的id 54 | */ 55 | @property (nonatomic, copy) NSString *userId; 56 | 57 | /** 58 | 微博平台的自定义字段,例如定义{‘gender’:0,’name’:’xxx’} 59 | */ 60 | @property (nonatomic, strong) NSDictionary *param; 61 | 62 | 63 | /** 64 | 初始化方法,在发送微博结束的回调方法使用此初始化方法 65 | 66 | @param platformType 微博平台类型 67 | @param weiboId 微博id,可以设置为nil 68 | @param userId 用户id 69 | @param param 微博平台自定义字段,可以设置为nil 70 | 71 | @return 微博对象 72 | */ 73 | -(id)initWithPlatformType:(MobClickSocialTypeString)platformType weiboId:(NSString *)weiboId usid:(NSString *)usid param:(NSDictionary *)param; 74 | 75 | @end 76 | 77 | /** 78 | 发送统计完成的block对象 79 | */ 80 | typedef void (^MobClickSocialAnalyticsCompletion)(NSDictionary * response, NSError *error); 81 | 82 | 83 | /** 84 | 负责统计微博类。 85 | 分享微博完成之后需要先构造`MobClickSocialWeibo`组成微博数组,然后再用类方法发送微博数组 86 | 87 | ``` 88 | +(void)postWeiboCounts:(NSArray *)weibos appKey:(NSString *)appKey topic:(NSString *)topic completion:(MobClickSocialAnalyticsCompletion)completion; 89 | ``` 90 | 91 | 例如 92 | 93 | 94 | MobClickSocialWeibo *tencentWeibo = [[MobClickSocialWeibo alloc] initWithPlatformType:UMSocialTypeTencent weiboId:nil userId:@"tencent123" param:@{@"gender":@"1"}]; 95 | [MobClickSocialAnalytics postWeibos:@[tencentWeibo] appKey:@"507fcab25270157b37000010" topic:@"test" completion:^(NSDictionary *result, NSError *error) { 96 | NSLog(@"result is %@", result); 97 | }]; 98 | 99 | */ 100 | 101 | @interface MobClickSocialAnalytics : NSObject 102 | /** 103 | 发送统计微博 104 | 105 | @param weibos UMSocialWeibo对象组成的数组 106 | @param appKey 友盟appkey 107 | @param topic 话题,可选,可以设置为nil 108 | @parma completion 发送完成的事件处理block 109 | 110 | */ 111 | +(void)postWeiboCounts:(NSArray *)weibos appKey:(NSString *)appKey topic:(NSString *)topic completion:(MobClickSocialAnalyticsCompletion)completion; 112 | @end 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Umeng 2 | 3 | A Umeng lib for React Native 4 | 5 | # iOS Install 6 | 7 | 在 `package.json` 里添加: 8 | 9 | ``` 10 | "rn-umeng": "git+https://github.com/RnTouna/rn-umeng.git" 11 | ``` 12 | 13 | 然后执行命令 14 | 15 | ```bash 16 | yarn install (或 npm install) 17 | react-native link rn-umeng 18 | ``` 19 | 20 | 在工程target的 `Build Phases->Link Binary with Libraries` 中加入 21 | `CoreTelephony.framework libz.tbd libsqlite3.tbd` 22 | 23 | 在 `Build Settings->Search Paths->Framework Search Paths` 中加入路径 `$(SRCROOT)/../node_modules/rn-umeng/ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk` 24 | 25 | 在 `Build Settings->Link->Other Linker Flags` 中加入 `-framework "UMMobClick"` 26 | 27 | # Android Install (Manual) 28 | 29 | ```bash 30 | $ npm install --save rn-umeng 31 | ``` 32 | 33 | #### Add Gradle Module Manually 34 | 35 | Module Source: 36 | 37 | ```bash 38 | $PROJECT_DIR/node_modules/rn-umeng/android 39 | ``` 40 | 41 | ![image](https://raw.githubusercontent.com/esseak/rn-umeng/master/screenshots/screenshot0.png) 42 | 43 | ![image](https://raw.githubusercontent.com/esseak/rn-umeng/master/screenshots/screenshot1.png) 44 | 45 | #### Add UmengPackage 46 | 47 | ```java 48 | ReactInstanceManager.builder() ... 49 | .addPackage(new UmengPackage()) 50 | ``` 51 | 52 | #### onResume and onPause 53 | ```java 54 | @Override 55 | protected void onResume() { 56 | super.onResume(); 57 | MobclickAgent.onResume(this); 58 | } 59 | 60 | @Override 61 | protected void onPause() { 62 | super.onPause(); 63 | MobclickAgent.onPause(this); 64 | } 65 | ``` 66 | 67 | # Usage 68 | 69 | The api mapping below 70 | 71 | React Native Side | iOS Side | Android Side 72 | --------------------------|---------------------|----------------------- 73 | startWithAppkey(string) | startWithAppkey(NSString) | AnalyticsConfig.setAppkey(String appkey) 74 | startWithAppkeyAndChannel(string,string) | N/A | UMAnalyticsConfig(Context context, String appkey, String channelId) 75 | setAppVersion(string) | setAppVersion(string) | Not need to set it 76 | setDebugMode(bool) | setLogEnabled(BOOL) | MobclickAgent.setDebugMode( true ) 77 | enableEncrypt(boole) | setEncryptEnabled(BOOL) | AnalyticsConfig.enableEncrypt(boolean enable) 78 | setCrashReportEnabled(boole) | setCrashReportEnabled(BOOL) | MobclickAgent.setCatchUncaughtExceptions(false) 79 | onEvent(string) |event:(NSString *)eventId | MobclickAgent.onEvent(Context context, String eventId) 80 | onEvent(string,{key:"value"}) | onEvent:(NSString *)eventId attributes:(NSDictionary *)attributes | MobclickAgent.onEvent(Context context, String eventId, HashMap map) 81 | onEvent(string,{key:"value"},0) | onEvent:(NSString *)eventId attributes:(NSDictionary *)attributes counter:(NSString *)counter | MobclickAgent.onEventValue(Context context, String id, Map m, int du) 82 | onProfileSignIn('ID') | profileSignInWithPUID:(NSString *)puid | onProfileSignIn(String ID) 83 | onProfileSignIn('ID','Provider') | profileSignInWithPUID:(NSString *)puid provider:(NSString *)provider | onProfileSignIn(String Provider, String ID) 84 | onProfileSignOff() | profileSignOff | onProfileSignOff() 85 | onPageStart(string) | beginLogPageView:(NSString *)pageName | MobclickAgent.onPageStart(String pageName) 86 | onPageEnd(string) | endLogPageView:(NSString *)pageName | MobclickAgent.onPageEnd(String pageName) 87 | onLogPageViewInseconds('pageName',10) | logPageView:pageName seconds:seconds | N/A 88 | openActivityDurationTrack(boole) | N/A | MobclickAgent.openActivityDurationTrack(boolean value) 89 | onResume() | N/A | MobclickAgent.onResume() 90 | onPause() | N/A | MobclickAgent.onPause() 91 | getDeviceInfo((infoStr)=>{}) | getDeviceInfo | getDeviceInfo 92 | 93 | In your project code 94 | 95 | ```javascript 96 | import MobclickAgent from 'rn-umeng'; 97 | MobclickAgent.startWithAppkey('your appkey'); 98 | MobclickAgent.setDebugMode(true); 99 | MobclickAgent.onEvent("testEvent"); 100 | ``` 101 | 102 | 103 | # Changelog 104 | 105 | 106 | ### - 1.0.6 107 | - support RN 0.40 108 | 109 | ### - 1.0.5 110 | 111 | - fix error in LazyReactPackage 112 | 113 | ### - 1.0.4 114 | 115 | - add Android channel set 116 | 117 | ### - 1.0.3 118 | 119 | - add Android lib (but Manually,rnpm link not works,fix later) 120 | - update readme.md 121 | 122 | 123 | ### - 1.0.2 124 | - Project initialization 125 | 126 | # License 127 | MIT 128 | 129 | 130 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/Versions/A/Headers/MobClickGameAnalytics.h: -------------------------------------------------------------------------------- 1 | // 2 | // MobClickGameAnalytics.h 3 | // Analytics 4 | // 5 | // Copyright (C) 2010-2014 Umeng.com . All rights reserved. 6 | 7 | @interface MobClickGameAnalytics : NSObject 8 | 9 | #pragma mark - account function 10 | /** active user sign-in. 11 | 使用sign-In函数后,如果结束该PUID的统计,需要调用sign-Off函数 12 | @param puid : user's ID 13 | @param provider : 不能以下划线"_"开头,使用大写字母和数字标识; 如果是上市公司,建议使用股票代码。 14 | @return void. 15 | */ 16 | + (void)profileSignInWithPUID:(NSString *)puid; 17 | + (void)profileSignInWithPUID:(NSString *)puid provider:(NSString *)provider; 18 | 19 | /** active user sign-off. 20 | 停止sign-in PUID的统计 21 | @return void. 22 | */ 23 | + (void)profileSignOff; 24 | 25 | #pragma mark GameLevel methods 26 | ///--------------------------------------------------------------------------------------- 27 | /// @name set game level 28 | ///--------------------------------------------------------------------------------------- 29 | 30 | /** 设置玩家的等级. 31 | */ 32 | 33 | /** 设置玩家等级属性. 34 | @param level 玩家等级 35 | @return void 36 | */ 37 | + (void)setUserLevelId:(int)level; 38 | 39 | ///--------------------------------------------------------------------------------------- 40 | /// @name 关卡统计 41 | ///--------------------------------------------------------------------------------------- 42 | 43 | /** 记录玩家进入关卡,通过关卡及失败的情况. 44 | */ 45 | 46 | 47 | /** 进入关卡. 48 | @param level 关卡 49 | @return void 50 | */ 51 | + (void)startLevel:(NSString *)level; 52 | 53 | /** 通过关卡. 54 | @param level 关卡,如果level == nil 则为当前关卡 55 | @return void 56 | */ 57 | + (void)finishLevel:(NSString *)level; 58 | 59 | /** 未通过关卡. 60 | @param level 关卡,如果level == nil 则为当前关卡 61 | @return void 62 | */ 63 | 64 | + (void)failLevel:(NSString *)level; 65 | 66 | 67 | #pragma mark - 68 | #pragma mark Pay methods 69 | 70 | ///--------------------------------------------------------------------------------------- 71 | /// @name 支付统计 72 | ///--------------------------------------------------------------------------------------- 73 | 74 | /** 记录玩家交易兑换货币的情况 75 | @param currencyAmount 现金或等价物总额 76 | @param currencyType 为ISO4217定义的3位字母代码,如CNY,USD等(如使用其它自定义等价物作为现金,可使用ISO4217中未定义的3位字母组合传入货币类型) 77 | @param virtualAmount 虚拟币数量 78 | @param channel 支付渠道 79 | @param orderId 交易订单ID 80 | @return void 81 | */ 82 | + (void)exchange:(NSString *)orderId currencyAmount:(double)currencyAmount currencyType:(NSString *)currencyType virtualCurrencyAmount:(double)virtualAmount paychannel:(int)channel; 83 | 84 | /** 玩家支付货币兑换虚拟币. 85 | @param cash 真实货币数量 86 | @param source 支付渠道 87 | @param coin 虚拟币数量 88 | @return void 89 | */ 90 | 91 | + (void)pay:(double)cash source:(int)source coin:(double)coin; 92 | 93 | /** 玩家支付货币购买道具. 94 | @param cash 真实货币数量 95 | @param source 支付渠道 96 | @param item 道具名称 97 | @param amount 道具数量 98 | @param price 道具单价 99 | @return void 100 | */ 101 | + (void)pay:(double)cash source:(int)source item:(NSString *)item amount:(int)amount price:(double)price; 102 | 103 | 104 | #pragma mark - 105 | #pragma mark Buy methods 106 | 107 | ///--------------------------------------------------------------------------------------- 108 | /// @name 虚拟币购买统计 109 | ///--------------------------------------------------------------------------------------- 110 | 111 | /** 记录玩家使用虚拟币的消费情况 112 | */ 113 | 114 | 115 | /** 玩家使用虚拟币购买道具 116 | @param item 道具名称 117 | @param amount 道具数量 118 | @param price 道具单价 119 | @return void 120 | */ 121 | + (void)buy:(NSString *)item amount:(int)amount price:(double)price; 122 | 123 | 124 | #pragma mark - 125 | #pragma mark Use methods 126 | 127 | 128 | ///--------------------------------------------------------------------------------------- 129 | /// @name 道具消耗统计 130 | ///--------------------------------------------------------------------------------------- 131 | 132 | /** 记录玩家道具消费情况 133 | */ 134 | 135 | 136 | /** 玩家使用虚拟币购买道具 137 | @param item 道具名称 138 | @param amount 道具数量 139 | @param price 道具单价 140 | @return void 141 | */ 142 | 143 | + (void)use:(NSString *)item amount:(int)amount price:(double)price; 144 | 145 | 146 | #pragma mark - 147 | #pragma mark Bonus methods 148 | 149 | 150 | ///--------------------------------------------------------------------------------------- 151 | /// @name 虚拟币及道具奖励统计 152 | ///--------------------------------------------------------------------------------------- 153 | 154 | /** 记录玩家获赠虚拟币及道具的情况 155 | */ 156 | 157 | 158 | /** 玩家获虚拟币奖励 159 | @param coin 虚拟币数量 160 | @param source 奖励方式 161 | @return void 162 | */ 163 | 164 | + (void)bonus:(double)coin source:(int)source; 165 | 166 | /** 玩家获道具奖励 167 | @param item 道具名称 168 | @param amount 道具数量 169 | @param price 道具单价 170 | @param source 奖励方式 171 | @return void 172 | */ 173 | 174 | + (void)bonus:(NSString *)item amount:(int)amount price:(double)price source:(int)source; 175 | 176 | #pragma mark DEPRECATED 177 | 178 | //已经被新的setUserLevelId:方法替代,请使用新的API。 179 | + (void)setUserLevel:(NSString *)level; 180 | 181 | //已经被新的active user方法替代,请使用新的API。 182 | + (void)setUserID:(NSString *)userId sex:(int)sex age:(int)age platform:(NSString *)platform; 183 | 184 | @end 185 | -------------------------------------------------------------------------------- /android/src/main/java/in/esseak/react_native_umeng/UmengModule.java: -------------------------------------------------------------------------------- 1 | package in.esseak.react_native_umeng; 2 | 3 | import android.Manifest; 4 | import android.annotation.SuppressLint; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.os.Build; 8 | import android.text.TextUtils; 9 | 10 | import com.facebook.react.bridge.Callback; 11 | import com.facebook.react.bridge.ReactApplicationContext; 12 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 13 | import com.facebook.react.bridge.ReactMethod; 14 | import com.facebook.react.bridge.ReadableMap; 15 | import com.facebook.react.bridge.ReadableMapKeySetIterator; 16 | import com.umeng.analytics.AnalyticsConfig; 17 | import com.umeng.analytics.MobclickAgent; 18 | 19 | import java.util.HashMap; 20 | 21 | /** 22 | * Created by mike on 16/4/26. 23 | */ 24 | public class UmengModule extends ReactContextBaseJavaModule { 25 | 26 | private static Boolean startedWithAppkey = false; 27 | private Context context; 28 | public UmengModule(ReactApplicationContext reactContext) { 29 | super(reactContext); 30 | context = reactContext.getBaseContext(); 31 | } 32 | 33 | @Override 34 | public String getName() { 35 | return "Umeng"; 36 | } 37 | 38 | @ReactMethod 39 | public void startWithAppkey(String value){ 40 | if (!startedWithAppkey){ 41 | AnalyticsConfig.setAppkey(context,value); 42 | AnalyticsConfig.setChannel("android"); 43 | startedWithAppkey = true; 44 | } 45 | } 46 | 47 | @ReactMethod 48 | public void startWithAppkeyAndChannel(String value,String channel){ 49 | if (!startedWithAppkey){ 50 | AnalyticsConfig.setAppkey(context,value); 51 | AnalyticsConfig.setChannel(channel); 52 | startedWithAppkey = true; 53 | } 54 | } 55 | 56 | @ReactMethod 57 | public void setCrashReportEnabled(Boolean value){ 58 | MobclickAgent.setCatchUncaughtExceptions(value); 59 | } 60 | 61 | @ReactMethod 62 | public void enableEncrypt(Boolean value){ 63 | AnalyticsConfig.enableEncrypt(value); 64 | } 65 | 66 | @ReactMethod 67 | public void onPageStart(String pageName){ 68 | MobclickAgent.onPageStart(pageName); 69 | } 70 | 71 | @ReactMethod 72 | public void onPageEnd(String pageName){ 73 | MobclickAgent.onPageEnd(pageName); 74 | } 75 | 76 | @ReactMethod 77 | public void onProfileSignIn(String ID,String Provider){ 78 | if (Provider != null){ 79 | MobclickAgent.onProfileSignIn(Provider,ID); 80 | }else{ 81 | MobclickAgent.onProfileSignIn(ID); 82 | } 83 | } 84 | 85 | @ReactMethod 86 | public void onProfileSignOff(){ 87 | MobclickAgent.onProfileSignOff(); 88 | } 89 | 90 | @ReactMethod 91 | public void onEvent(String eventId, ReadableMap dataMap, String counter){ 92 | HashMap map = null; 93 | if (dataMap != null){ 94 | map = new HashMap(); 95 | ReadableMapKeySetIterator readableMapKeySetIterator = dataMap.keySetIterator(); 96 | while (readableMapKeySetIterator.hasNextKey()){ 97 | String aKey = readableMapKeySetIterator.nextKey(); 98 | String aValue = dataMap.getString(aKey); 99 | map.put(aKey,aValue); 100 | } 101 | } 102 | 103 | if (map != null&&counter != null){ 104 | MobclickAgent.onEventValue(context,eventId,map,Integer.parseInt(counter)); 105 | }else if(map!=null){ 106 | MobclickAgent.onEvent(context,eventId,map); 107 | }else{ 108 | MobclickAgent.onEvent(context,eventId); 109 | } 110 | 111 | } 112 | 113 | @ReactMethod 114 | public void openActivityDurationTrack(Boolean value){ 115 | MobclickAgent.openActivityDurationTrack(value); 116 | } 117 | 118 | @ReactMethod 119 | public void onResume(){ 120 | MobclickAgent.onResume(context); 121 | } 122 | 123 | @ReactMethod 124 | public void onPause(){ 125 | MobclickAgent.onPause(context); 126 | } 127 | 128 | @ReactMethod 129 | public void setDebugMode(Boolean value){ 130 | MobclickAgent.setDebugMode(value); 131 | } 132 | 133 | @ReactMethod 134 | public void setLogEnabled(Boolean value){ 135 | MobclickAgent.setDebugMode(value); 136 | } 137 | 138 | @ReactMethod 139 | public void getDeviceInfo(Callback dataCallBack){ 140 | String infoStr = mGetDeviceInfo(context); 141 | dataCallBack.invoke(infoStr); 142 | } 143 | 144 | @SuppressLint("NewApi") 145 | 146 | public static boolean checkPermission(Context context, String permission) { 147 | boolean result = false; 148 | 149 | if (Build.VERSION.SDK_INT >= 23) { 150 | if (context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) { 151 | result = true; 152 | } 153 | } else { 154 | PackageManager pm = context.getPackageManager(); 155 | 156 | if (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) { 157 | result = true; 158 | } 159 | } 160 | 161 | return result; 162 | } 163 | 164 | 165 | public static String mGetDeviceInfo(Context context) { 166 | try { 167 | org.json.JSONObject json = new org.json.JSONObject(); 168 | android.telephony.TelephonyManager tm = (android.telephony.TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 169 | 170 | String device_id = null; 171 | 172 | if (checkPermission(context, Manifest.permission.READ_PHONE_STATE)) { 173 | device_id = tm.getDeviceId(); 174 | } 175 | 176 | android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) context.getSystemService(Context.WIFI_SERVICE); 177 | 178 | String mac = wifi.getConnectionInfo().getMacAddress(); 179 | 180 | json.put("mac", mac); 181 | 182 | if (TextUtils.isEmpty(device_id)) { 183 | device_id = mac; 184 | } 185 | 186 | 187 | if (TextUtils.isEmpty(device_id)) { 188 | device_id = android.provider.Settings.Secure.getString(context.getContentResolver(), 189 | android.provider.Settings.Secure.ANDROID_ID); 190 | } 191 | 192 | json.put("device_id", device_id); 193 | 194 | return json.toString(); 195 | } catch (Exception e) { 196 | e.printStackTrace(); 197 | } 198 | 199 | return null; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /android/rn-umeng.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 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 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng/UMAnalytics_Sdk/UMMobClick.framework/Versions/A/Headers/MobClick.h: -------------------------------------------------------------------------------- 1 | // 2 | // MobClick.h 3 | // Analytics 4 | // 5 | // Copyright (C) 2010-2016 Umeng.com . All rights reserved. 6 | 7 | #import 8 | #import 9 | 10 | #define XcodeAppVersion [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] 11 | typedef void(^CallbackBlock)(); 12 | 13 | /** 14 | REALTIME只在“集成测试”设备的DEBUG模式下有效,其它情况下的REALTIME会改为使用BATCH策略。 15 | */ 16 | typedef enum { 17 | REALTIME = 0, //实时发送 (只在“集成测试”设备的DEBUG模式下有效) 18 | BATCH = 1, //启动发送 19 | SEND_INTERVAL = 6, //最小间隔发送 ([90-86400]s, default 90s) 20 | SMART_POLICY = 8, 21 | } ReportPolicy; 22 | 23 | /** 24 | 统计的场景类别,默认为普通统计;若使用游戏统计API,则需选择游戏场景类别,如E_UM_GAME。 25 | */ 26 | typedef NS_ENUM (NSUInteger, eScenarioType) 27 | { 28 | E_UM_NORMAL = 0, // default value 29 | E_UM_GAME = 1, // game 30 | }; 31 | 32 | /** @brief 统计SDK的配置实例,具体参照该类成员的参数定义 33 | * 示例代码: UMConfigInstance.appKey = @"xxxxxxxxxxxxxx..."; 34 | * UMConfigInstance.token = @"yyyyyyyy...."; 35 | * [MobClick startWithConfigure:UMConfigInstance]; 36 | */ 37 | #define UMConfigInstance [UMAnalyticsConfig sharedInstance] 38 | @interface UMAnalyticsConfig : NSObject 39 | /** required: appkey string */ 40 | @property(nonatomic, copy) NSString *appKey; 41 | /** optional: default: nil*/ 42 | @property(nonatomic, copy) NSString *secret; 43 | /** optional: default: "App Store"*/ 44 | @property(nonatomic, copy) NSString *channelId; 45 | /** optional: default: YES */ 46 | @property(nonatomic) BOOL bCrashReportEnabled; 47 | /** optional: default: BATCH */ 48 | @property(nonatomic) ReportPolicy ePolicy; 49 | /** optional: default: E_UM_NORMAL */ 50 | @property(nonatomic) eScenarioType eSType; 51 | 52 | + (instancetype)sharedInstance; 53 | @end 54 | 55 | @class CLLocation; 56 | @interface MobClick : NSObject 57 | 58 | #pragma mark basics 59 | ///--------------------------------------------------------------------------------------- 60 | /// @name 初始化统计 61 | ///--------------------------------------------------------------------------------------- 62 | 63 | /** 初始化友盟统计模块 64 | @param UMAnalyticsConfig 实例类,具体参照该类成员的参数定义 65 | @return void 66 | */ 67 | + (void) startWithConfigure:(UMAnalyticsConfig *)configure; 68 | 69 | ///--------------------------------------------------------------------------------------- 70 | /// @name 设置 71 | ///--------------------------------------------------------------------------------------- 72 | 73 | /** 设置app版本号。由于历史原因需要和xcode3工程兼容,友盟提取的是Build号(CFBundleVersion), 74 | 如果需要和App Store上的版本一致,请调用此方法。 75 | @param appVersion 版本号,例如设置成`XcodeAppVersion`. 76 | @return void. 77 | */ 78 | + (void)setAppVersion:(NSString *)appVersion; 79 | 80 | /** 开启CrashReport收集, 默认YES(开启状态). 81 | @param value 设置为NO,可关闭友盟CrashReport收集功能. 82 | @return void. 83 | */ 84 | + (void)setCrashReportEnabled:(BOOL)value; 85 | 86 | /** 设置是否打印sdk的log信息, 默认NO(不打印log). 87 | @param value 设置为YES,umeng SDK 会输出log信息可供调试参考. 除非特殊需要,否则发布产品时需改回NO. 88 | @return void. 89 | */ 90 | + (void)setLogEnabled:(BOOL)value; 91 | 92 | /** 设置是否对日志信息进行加密, 默认NO(不加密). 93 | @param value 设置为YES, umeng SDK 会将日志信息做加密处理 94 | @return void. 95 | */ 96 | + (void)setEncryptEnabled:(BOOL)value; 97 | 98 | /** 当reportPolicy == SEND_INTERVAL 时设定log发送间隔 99 | @param second 单位为秒,最小90秒,最大86400秒(24hour). 100 | @return void. 101 | */ 102 | + (void)setLogSendInterval:(double)second; 103 | 104 | 105 | 106 | #pragma mark event logs 107 | ///--------------------------------------------------------------------------------------- 108 | /// @name 页面计时 109 | ///--------------------------------------------------------------------------------------- 110 | 111 | /** 手动页面时长统计, 记录某个页面展示的时长. 112 | @param pageName 统计的页面名称. 113 | @param seconds 单位为秒,int型. 114 | @return void. 115 | */ 116 | + (void)logPageView:(NSString *)pageName seconds:(int)seconds; 117 | 118 | /** 自动页面时长统计, 开始记录某个页面展示时长. 119 | 使用方法:必须配对调用beginLogPageView:和endLogPageView:两个函数来完成自动统计,若只调用某一个函数不会生成有效数据。 120 | 在该页面展示时调用beginLogPageView:,当退出该页面时调用endLogPageView: 121 | @param pageName 统计的页面名称. 122 | @return void. 123 | */ 124 | + (void)beginLogPageView:(NSString *)pageName; 125 | 126 | /** 自动页面时长统计, 结束记录某个页面展示时长. 127 | 使用方法:必须配对调用beginLogPageView:和endLogPageView:两个函数来完成自动统计,若只调用某一个函数不会生成有效数据。 128 | 在该页面展示时调用beginLogPageView:,当退出该页面时调用endLogPageView: 129 | @param pageName 统计的页面名称. 130 | @return void. 131 | */ 132 | + (void)endLogPageView:(NSString *)pageName; 133 | 134 | 135 | ///--------------------------------------------------------------------------------------- 136 | /// @name 事件统计 137 | ///--------------------------------------------------------------------------------------- 138 | /** 结构化事件 139 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID。 140 | 141 | @param keyPath 字符串数组代表的结构化事件路径,其长度最大为8,不能使用unicode 48以内的字符,keyPath[0]必须在网站注册事件ID. 142 | @param value 事件的数值 143 | @param (optional) label 标签 144 | @return void. 145 | */ 146 | + (void)event:(NSArray *)keyPath value:(int)value label:(NSString *)label; 147 | 148 | /** 自定义事件,数量统计. 149 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID 150 | 151 | @param eventId 网站上注册的事件Id. 152 | @param label 分类标签。不同的标签会分别进行统计,方便同一事件的不同标签的对比,为nil或空字符串时后台会生成和eventId同名的标签. 153 | @param accumulation 累加值。为减少网络交互,可以自行对某一事件ID的某一分类标签进行累加,再传入次数作为参数。 154 | @return void. 155 | */ 156 | + (void)event:(NSString *)eventId; //等同于 event:eventId label:eventId; 157 | /** 自定义事件,数量统计. 158 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID 159 | */ 160 | + (void)event:(NSString *)eventId label:(NSString *)label; // label为nil或@""时,等同于 event:eventId label:eventId; 161 | 162 | /** 自定义事件,数量统计. 163 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID 164 | */ 165 | + (void)event:(NSString *)eventId attributes:(NSDictionary *)attributes; 166 | 167 | + (void)event:(NSString *)eventId attributes:(NSDictionary *)attributes counter:(int)number; 168 | 169 | /** 自定义事件,时长统计. 170 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 171 | beginEvent,endEvent要配对使用,也可以自己计时后通过durations参数传递进来 172 | 173 | @param eventId 网站上注册的事件Id. 174 | @param label 分类标签。不同的标签会分别进行统计,方便同一事件的不同标签的对比,为nil或空字符串时后台会生成和eventId同名的标签. 175 | @param primarykey 这个参数用于和event_id一起标示一个唯一事件,并不会被统计;对于同一个事件在beginEvent和endEvent 中要传递相同的eventId 和 primarykey 176 | @param millisecond 自己计时需要的话需要传毫秒进来 177 | @return void. 178 | 179 | @warning 每个event的attributes不能超过10个 180 | eventId、attributes中key和value都不能使用空格和特殊字符,必须是NSString,且长度不能超过255个字符(否则将截取前255个字符) 181 | id, ts, du是保留字段,不能作为eventId及key的名称 182 | */ 183 | + (void)beginEvent:(NSString *)eventId; 184 | 185 | /** 自定义事件,时长统计. 186 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 187 | */ 188 | 189 | + (void)endEvent:(NSString *)eventId; 190 | /** 自定义事件,时长统计. 191 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 192 | */ 193 | 194 | + (void)beginEvent:(NSString *)eventId label:(NSString *)label; 195 | /** 自定义事件,时长统计. 196 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 197 | */ 198 | 199 | + (void)endEvent:(NSString *)eventId label:(NSString *)label; 200 | /** 自定义事件,时长统计. 201 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 202 | */ 203 | 204 | + (void)beginEvent:(NSString *)eventId primarykey :(NSString *)keyName attributes:(NSDictionary *)attributes; 205 | /** 自定义事件,时长统计. 206 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 207 | */ 208 | 209 | + (void)endEvent:(NSString *)eventId primarykey:(NSString *)keyName; 210 | /** 自定义事件,时长统计. 211 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 212 | */ 213 | 214 | + (void)event:(NSString *)eventId durations:(int)millisecond; 215 | /** 自定义事件,时长统计. 216 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 217 | */ 218 | 219 | + (void)event:(NSString *)eventId label:(NSString *)label durations:(int)millisecond; 220 | /** 自定义事件,时长统计. 221 | 使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID. 222 | */ 223 | + (void)event:(NSString *)eventId attributes:(NSDictionary *)attributes durations:(int)millisecond; 224 | 225 | 226 | #pragma mark - user methods 227 | /** active user sign-in. 228 | 使用sign-In函数后,如果结束该PUID的统计,需要调用sign-Off函数 229 | @param puid : user's ID 230 | @param provider : 不能以下划线"_"开头,使用大写字母和数字标识; 如果是上市公司,建议使用股票代码。 231 | @return void. 232 | */ 233 | + (void)profileSignInWithPUID:(NSString *)puid; 234 | + (void)profileSignInWithPUID:(NSString *)puid provider:(NSString *)provider; 235 | 236 | /** active user sign-off. 237 | 停止sign-in PUID的统计 238 | @return void. 239 | */ 240 | + (void)profileSignOff; 241 | 242 | ///--------------------------------------------------------------------------------------- 243 | /// @name 地理位置设置 244 | /// 需要链接 CoreLocation.framework 并且 #import 245 | ///--------------------------------------------------------------------------------------- 246 | 247 | /** 设置经纬度信息 248 | @param latitude 纬度. 249 | @param longitude 经度. 250 | @return void 251 | */ 252 | + (void)setLatitude:(double)latitude longitude:(double)longitude; 253 | 254 | /** 设置经纬度信息 255 | @param location CLLocation 经纬度信息 256 | @return void 257 | */ 258 | + (void)setLocation:(CLLocation *)location; 259 | 260 | ///--------------------------------------------------------------------------------------- 261 | /// @name Utility函数 262 | ///--------------------------------------------------------------------------------------- 263 | 264 | /** 判断设备是否越狱,依据是否存在apt和Cydia.app 265 | */ 266 | + (BOOL)isJailbroken; 267 | 268 | /** 判断App是否被破解 269 | */ 270 | + (BOOL)isPirated; 271 | 272 | #pragma mark DEPRECATED 273 | /** 友盟模块启动 274 | [MobClick startWithConfigure:]通常在application:didFinishLaunchingWithOptions:里被调用监听App启动和退出事件, 275 | 如果开发者无法在此处添加友盟的[MobClick startWithConfigure:]方法,App的启动事件可能会无法监听,此时需要手动调用[MobClick startSession:nil]来启动友盟的session。 276 | 上述情况通常发生在某些第三方框架生成的app里,普通app不用关注该API. 277 | */ 278 | + (void)startSession:(NSNotification *)notification; 279 | 280 | + (void)setCrashCBBlock:(CallbackBlock)cbBlock; 281 | @end 282 | -------------------------------------------------------------------------------- /ios/RCTUmeng/RCTUmeng.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E17579831F289A840053007F /* RCTUmeng.m in Sources */ = {isa = PBXBuildFile; fileRef = E17579821F289A840053007F /* RCTUmeng.m */; }; 11 | E17579841F289A840053007F /* RCTUmeng.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = E17579811F289A840053007F /* RCTUmeng.h */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | E175797C1F289A840053007F /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = "include/$(PRODUCT_NAME)"; 19 | dstSubfolderSpec = 16; 20 | files = ( 21 | E17579841F289A840053007F /* RCTUmeng.h in CopyFiles */, 22 | ); 23 | runOnlyForDeploymentPostprocessing = 0; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | E15706071F28A63F00B8C100 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; 29 | E15706091F28A72500B8C100 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 30 | E157060C1F28AF3B00B8C100 /* UMMobClick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = UMMobClick.framework; sourceTree = ""; }; 31 | E175797E1F289A840053007F /* libRCTUmeng.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTUmeng.a; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | E17579811F289A840053007F /* RCTUmeng.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTUmeng.h; sourceTree = ""; }; 33 | E17579821F289A840053007F /* RCTUmeng.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTUmeng.m; sourceTree = ""; }; 34 | E17579921F289B4F0053007F /* v_4.2.4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = v_4.2.4; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | E175797B1F289A840053007F /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | E15706061F28A63F00B8C100 /* Frameworks */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | E15706091F28A72500B8C100 /* libz.tbd */, 52 | E15706071F28A63F00B8C100 /* CoreTelephony.framework */, 53 | ); 54 | name = Frameworks; 55 | sourceTree = ""; 56 | }; 57 | E17579751F289A840053007F = { 58 | isa = PBXGroup; 59 | children = ( 60 | E17579801F289A840053007F /* RCTUmeng */, 61 | E175797F1F289A840053007F /* Products */, 62 | E15706061F28A63F00B8C100 /* Frameworks */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | E175797F1F289A840053007F /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | E175797E1F289A840053007F /* libRCTUmeng.a */, 70 | ); 71 | name = Products; 72 | sourceTree = ""; 73 | }; 74 | E17579801F289A840053007F /* RCTUmeng */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | E17579811F289A840053007F /* RCTUmeng.h */, 78 | E17579821F289A840053007F /* RCTUmeng.m */, 79 | E17579901F289B4F0053007F /* UMAnalytics_Sdk */, 80 | ); 81 | path = RCTUmeng; 82 | sourceTree = ""; 83 | }; 84 | E17579901F289B4F0053007F /* UMAnalytics_Sdk */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | E157060C1F28AF3B00B8C100 /* UMMobClick.framework */, 88 | E17579921F289B4F0053007F /* v_4.2.4 */, 89 | ); 90 | path = UMAnalytics_Sdk; 91 | sourceTree = ""; 92 | }; 93 | /* End PBXGroup section */ 94 | 95 | /* Begin PBXNativeTarget section */ 96 | E175797D1F289A840053007F /* RCTUmeng */ = { 97 | isa = PBXNativeTarget; 98 | buildConfigurationList = E17579871F289A840053007F /* Build configuration list for PBXNativeTarget "RCTUmeng" */; 99 | buildPhases = ( 100 | E175797A1F289A840053007F /* Sources */, 101 | E175797B1F289A840053007F /* Frameworks */, 102 | E175797C1F289A840053007F /* CopyFiles */, 103 | ); 104 | buildRules = ( 105 | ); 106 | dependencies = ( 107 | ); 108 | name = RCTUmeng; 109 | productName = RCTUmeng; 110 | productReference = E175797E1F289A840053007F /* libRCTUmeng.a */; 111 | productType = "com.apple.product-type.library.static"; 112 | }; 113 | /* End PBXNativeTarget section */ 114 | 115 | /* Begin PBXProject section */ 116 | E17579761F289A840053007F /* Project object */ = { 117 | isa = PBXProject; 118 | attributes = { 119 | LastUpgradeCheck = 0830; 120 | ORGANIZATIONNAME = aevit; 121 | TargetAttributes = { 122 | E175797D1F289A840053007F = { 123 | CreatedOnToolsVersion = 8.3.3; 124 | ProvisioningStyle = Automatic; 125 | }; 126 | }; 127 | }; 128 | buildConfigurationList = E17579791F289A840053007F /* Build configuration list for PBXProject "RCTUmeng" */; 129 | compatibilityVersion = "Xcode 3.2"; 130 | developmentRegion = English; 131 | hasScannedForEncodings = 0; 132 | knownRegions = ( 133 | en, 134 | ); 135 | mainGroup = E17579751F289A840053007F; 136 | productRefGroup = E175797F1F289A840053007F /* Products */; 137 | projectDirPath = ""; 138 | projectRoot = ""; 139 | targets = ( 140 | E175797D1F289A840053007F /* RCTUmeng */, 141 | ); 142 | }; 143 | /* End PBXProject section */ 144 | 145 | /* Begin PBXSourcesBuildPhase section */ 146 | E175797A1F289A840053007F /* Sources */ = { 147 | isa = PBXSourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | E17579831F289A840053007F /* RCTUmeng.m in Sources */, 151 | ); 152 | runOnlyForDeploymentPostprocessing = 0; 153 | }; 154 | /* End PBXSourcesBuildPhase section */ 155 | 156 | /* Begin XCBuildConfiguration section */ 157 | E17579851F289A840053007F /* Debug */ = { 158 | isa = XCBuildConfiguration; 159 | buildSettings = { 160 | ALWAYS_SEARCH_USER_PATHS = NO; 161 | CLANG_ANALYZER_NONNULL = YES; 162 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 163 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 164 | CLANG_CXX_LIBRARY = "libc++"; 165 | CLANG_ENABLE_MODULES = YES; 166 | CLANG_ENABLE_OBJC_ARC = YES; 167 | CLANG_WARN_BOOL_CONVERSION = YES; 168 | CLANG_WARN_CONSTANT_CONVERSION = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 171 | CLANG_WARN_EMPTY_BODY = YES; 172 | CLANG_WARN_ENUM_CONVERSION = YES; 173 | CLANG_WARN_INFINITE_RECURSION = YES; 174 | CLANG_WARN_INT_CONVERSION = YES; 175 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 176 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 177 | CLANG_WARN_UNREACHABLE_CODE = YES; 178 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 179 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 180 | COPY_PHASE_STRIP = NO; 181 | DEBUG_INFORMATION_FORMAT = dwarf; 182 | ENABLE_STRICT_OBJC_MSGSEND = YES; 183 | ENABLE_TESTABILITY = YES; 184 | FRAMEWORK_SEARCH_PATHS = ( 185 | "$(inherited)", 186 | "$(PROJECT_DIR)/RCTUmeng/UMAnalytics_Sdk", 187 | ); 188 | GCC_C_LANGUAGE_STANDARD = gnu99; 189 | GCC_DYNAMIC_NO_PIC = NO; 190 | GCC_NO_COMMON_BLOCKS = YES; 191 | GCC_OPTIMIZATION_LEVEL = 0; 192 | GCC_PREPROCESSOR_DEFINITIONS = ( 193 | "DEBUG=1", 194 | "$(inherited)", 195 | ); 196 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 197 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 198 | GCC_WARN_UNDECLARED_SELECTOR = YES; 199 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 200 | GCC_WARN_UNUSED_FUNCTION = YES; 201 | GCC_WARN_UNUSED_VARIABLE = YES; 202 | HEADER_SEARCH_PATHS = ( 203 | "$(inherited)", 204 | "$(SRCROOT)/../../react-native/React/**", 205 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 206 | ); 207 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 208 | MTL_ENABLE_DEBUG_INFO = YES; 209 | ONLY_ACTIVE_ARCH = YES; 210 | SDKROOT = iphoneos; 211 | }; 212 | name = Debug; 213 | }; 214 | E17579861F289A840053007F /* Release */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | ALWAYS_SEARCH_USER_PATHS = NO; 218 | CLANG_ANALYZER_NONNULL = YES; 219 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 220 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 221 | CLANG_CXX_LIBRARY = "libc++"; 222 | CLANG_ENABLE_MODULES = YES; 223 | CLANG_ENABLE_OBJC_ARC = YES; 224 | CLANG_WARN_BOOL_CONVERSION = YES; 225 | CLANG_WARN_CONSTANT_CONVERSION = YES; 226 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 227 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 228 | CLANG_WARN_EMPTY_BODY = YES; 229 | CLANG_WARN_ENUM_CONVERSION = YES; 230 | CLANG_WARN_INFINITE_RECURSION = YES; 231 | CLANG_WARN_INT_CONVERSION = YES; 232 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 233 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 234 | CLANG_WARN_UNREACHABLE_CODE = YES; 235 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 236 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 237 | COPY_PHASE_STRIP = NO; 238 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 239 | ENABLE_NS_ASSERTIONS = NO; 240 | ENABLE_STRICT_OBJC_MSGSEND = YES; 241 | FRAMEWORK_SEARCH_PATHS = ( 242 | "$(inherited)", 243 | "$(PROJECT_DIR)/RCTUmeng/UMAnalytics_Sdk", 244 | ); 245 | GCC_C_LANGUAGE_STANDARD = gnu99; 246 | GCC_NO_COMMON_BLOCKS = YES; 247 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 248 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 249 | GCC_WARN_UNDECLARED_SELECTOR = YES; 250 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 251 | GCC_WARN_UNUSED_FUNCTION = YES; 252 | GCC_WARN_UNUSED_VARIABLE = YES; 253 | HEADER_SEARCH_PATHS = ( 254 | "$(inherited)", 255 | "$(SRCROOT)/../../react-native/React/**", 256 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 257 | ); 258 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 259 | MTL_ENABLE_DEBUG_INFO = NO; 260 | SDKROOT = iphoneos; 261 | VALIDATE_PRODUCT = YES; 262 | }; 263 | name = Release; 264 | }; 265 | E17579881F289A840053007F /* Debug */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | FRAMEWORK_SEARCH_PATHS = ( 269 | "$(inherited)", 270 | "$(PROJECT_DIR)/RCTUmeng/UMAnalytics_Sdk", 271 | ); 272 | HEADER_SEARCH_PATHS = ( 273 | "$(inherited)", 274 | "$(SRCROOT)/../../react-native/React/**", 275 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 276 | ); 277 | OTHER_LDFLAGS = "-all_load"; 278 | PRODUCT_NAME = "$(TARGET_NAME)"; 279 | SKIP_INSTALL = YES; 280 | }; 281 | name = Debug; 282 | }; 283 | E17579891F289A840053007F /* Release */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ALWAYS_SEARCH_USER_PATHS = NO; 287 | FRAMEWORK_SEARCH_PATHS = ( 288 | "$(inherited)", 289 | "$(PROJECT_DIR)/RCTUmeng/UMAnalytics_Sdk", 290 | ); 291 | HEADER_SEARCH_PATHS = ( 292 | "$(inherited)", 293 | "$(SRCROOT)/../../react-native/React/**", 294 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 295 | ); 296 | OTHER_LDFLAGS = "-all_load"; 297 | PRODUCT_NAME = "$(TARGET_NAME)"; 298 | SKIP_INSTALL = YES; 299 | }; 300 | name = Release; 301 | }; 302 | /* End XCBuildConfiguration section */ 303 | 304 | /* Begin XCConfigurationList section */ 305 | E17579791F289A840053007F /* Build configuration list for PBXProject "RCTUmeng" */ = { 306 | isa = XCConfigurationList; 307 | buildConfigurations = ( 308 | E17579851F289A840053007F /* Debug */, 309 | E17579861F289A840053007F /* Release */, 310 | ); 311 | defaultConfigurationIsVisible = 0; 312 | defaultConfigurationName = Release; 313 | }; 314 | E17579871F289A840053007F /* Build configuration list for PBXNativeTarget "RCTUmeng" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | E17579881F289A840053007F /* Debug */, 318 | E17579891F289A840053007F /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | defaultConfigurationName = Release; 322 | }; 323 | /* End XCConfigurationList section */ 324 | }; 325 | rootObject = E17579761F289A840053007F /* Project object */; 326 | } 327 | --------------------------------------------------------------------------------