├── .gitignore ├── .npmignore ├── AUTHORS ├── LICENSE ├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── yandex │ └── metrica │ └── plugin │ └── reactnative │ ├── AppMetricaModule.java │ ├── AppMetricaPackage.java │ ├── ReactNativeAppMetricaDeviceIDListener.java │ └── Utils.java ├── index.js ├── ios ├── AppMetrica.h ├── AppMetrica.m ├── AppMetrica.xcodeproj │ └── project.pbxproj ├── AppMetrica.xcworkspace │ └── contents.xcworkspacedata ├── AppMetricaUtils.h └── AppMetricaUtils.m ├── package.json └── react-native-appmetrica-next.podspec /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # node.js 6 | # 7 | node_modules 8 | npm-debug.log 9 | yarn-error.log 10 | 11 | # Xcode 12 | # 13 | build 14 | *.pbxuser 15 | !default.pbxuser 16 | *.mode1v3 17 | !default.mode1v3 18 | *.mode2v3 19 | !default.mode2v3 20 | *.perspectivev3 21 | !default.perspectivev3 22 | xcuserdata 23 | *.xccheckout 24 | *.moved-aside 25 | DerivedData 26 | *.hmap 27 | *.ipa 28 | *.xcuserstate 29 | project.xcworkspace 30 | 31 | # Android/IntelliJ 32 | # 33 | build 34 | .idea 35 | .gradle 36 | local.properties 37 | *.iml 38 | 39 | # BUCK 40 | buck-out 41 | \.buckd 42 | *.keystore -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # node.js 6 | # 7 | node_modules 8 | npm-debug.log 9 | yarn-error.log 10 | 11 | # Xcode 12 | # 13 | build 14 | *.pbxuser 15 | !default.pbxuser 16 | *.mode1v3 17 | !default.mode1v3 18 | *.mode2v3 19 | !default.mode2v3 20 | *.perspectivev3 21 | !default.perspectivev3 22 | xcuserdata 23 | *.xccheckout 24 | *.moved-aside 25 | DerivedData 26 | *.hmap 27 | *.ipa 28 | *.xcuserstate 29 | project.xcworkspace 30 | 31 | # Android/IntelliJ 32 | # 33 | build 34 | .idea 35 | .gradle 36 | local.properties 37 | *.iml 38 | 39 | # BUCK 40 | buck-out 41 | \.buckd 42 | *.keystore 43 | 44 | .arcignore 45 | update-libs.sh 46 | update-version.sh 47 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | The following authors have created the source code of "react-native-appmetrica-next" published and distributed by YANDEX LLC as the owner: 2 | 3 | AndreyBondarenko -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 YANDEX LLC 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-appmetrica-next 2 | 3 | WARNING!!! 4 | ver 2.0 RN68 >= 5 | ver 1.0.17 RN67 <= 6 | 7 | React Native bridge to the [AppMetrica](https://appmetrica.yandex.com/) on both iOS and Android. 8 | react-native-push-next library functionality is expanded [react-native-appmetrica](https://github.com/yandexmobile/react-native-appmetrica) 9 | 10 | ## Installation 11 | 12 | `npm install react-native-appmetrica-next --save` 13 | or 14 | `yearn add react-native-appmetrica-next` 15 | 16 | ## Usage 17 | 18 | ```js 19 | import AppMetrica from "react-native-appmetrica-next"; 20 | 21 | // Starts the statistics collection process. 22 | AppMetrica.activate({ 23 | apiKey: "...KEY...", 24 | sessionTimeout: 120, 25 | firstActivationAsUpdate: true, 26 | }); 27 | 28 | // Sends a custom event message and additional parameters (optional). 29 | AppMetrica.reportEvent("My event"); 30 | AppMetrica.reportEvent("My event", { foo: "bar" }); 31 | 32 | // Send a custom error event. 33 | AppMetrica.reportError("My error"); 34 | 35 | // reportUserProfile 36 | AppMetrica.activate({ 37 | apiKey: "...KEY...", 38 | sessionTimeout: 120, 39 | firstActivationAsUpdate: true, 40 | }); 41 | RNAppMetrica.setUserProfileID("id"); 42 | RNAppMetrica.reportUserProfile({ 43 | name: "Andrey Bondarenko", 44 | floor: "male", 45 | age: 34, 46 | isNotification: true, 47 | }); 48 | ``` 49 | 50 | # SETTING PUSH SDK 51 | 52 | ## NEXT for Android 53 | 54 | ## create file FirebaseMessagingMasterService.java in you project 55 | 56 | ```js 57 | import com.google.firebase.messaging.FirebaseMessagingService; 58 | import com.google.firebase.messaging.RemoteMessage; 59 | import com.yandex.metrica.push.firebase.MetricaMessagingService; 60 | 61 | public class FirebaseMessagingMasterService extends FirebaseMessagingService { 62 | @Override 63 | public void onMessageReceived(RemoteMessage message) { 64 | super.onMessageReceived(message); 65 | // AppMetrica automatically recognizes its messages and processes them only. 66 | new MetricaMessagingService().processPush(this, message); 67 | 68 | // Implement the logic for sending messages to other SDKs. 69 | } 70 | 71 | } 72 | ``` 73 | 74 | ## Your files to Android manifest 75 | 76 | ```js 77 | 78 | ... 79 | 84 | 85 | 86 | 87 | 88 | 92 | ... 93 | 94 | ``` 95 | 96 | ## Silent Push Notifications for Android 97 | 98 | ## create file BroadcastReceiver in you project 99 | 100 | ```js 101 | import android.content.BroadcastReceiver; 102 | import android.content.Context; 103 | import android.content.Intent; 104 | import com.yandex.metrica.push.YandexMetricaPush; 105 | 106 | 107 | public class SilentPushReceiver extends BroadcastReceiver { 108 | 109 | @Override 110 | public void onReceive(Context context, Intent intent) { 111 | // TODO: This method is called when the BroadcastReceiver is receiving 112 | // an Intent broadcast. 113 | String payload = intent.getStringExtra(YandexMetricaPush.EXTRA_PAYLOAD); 114 | 115 | throw new UnsupportedOperationException("Not yet implemented"); 116 | } 117 | } 118 | ``` 119 | 120 | ## Your files to Android manifest 121 | 122 | ```js 123 | 124 | ... 125 | 126 | 127 | 128 | 129 | 130 | 131 | ``` 132 | 133 | # NEXT for iOS 134 | 135 | ### file AppDelegate.m add 136 | 137 | ```js 138 | // Add import 139 | #import 140 | 141 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 142 | { 143 | ... 144 | ... 145 | // Enable in-app push notifications handling in iOS 10 146 | if ([UNUserNotificationCenter class] != nil) { 147 | id delegate = [YMPYandexMetricaPush userNotificationCenterDelegate]; 148 | delegate.nextDelegate = [UNUserNotificationCenter currentNotificationCenter].delegate; 149 | [UNUserNotificationCenter currentNotificationCenter].delegate = delegate; 150 | } 151 | 152 | [YMPYandexMetricaPush handleApplicationDidFinishLaunchingWithOptions:launchOptions]; 153 | ... 154 | ... 155 | } 156 | 157 | // and ADD 158 | - (void)application:(UIApplication *)application 159 | didReceiveRemoteNotification:(NSDictionary *)userInfo 160 | { 161 | [YMPYandexMetricaPush handleRemoteNotification:userInfo]; 162 | } 163 | - (void)application:(UIApplication *)application 164 | didReceiveRemoteNotification:(NSDictionary *)userInfo 165 | fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler 166 | { 167 | [YMPYandexMetricaPush handleRemoteNotification:userInfo]; 168 | } 169 | 170 | ... 171 | ... 172 | @end 173 | ``` 174 | 175 | ## Usage (FIREBASE CLOUD MESSAGE) 176 | 177 | ```js 178 | import AppMetrica from "react-native-appmetrica-next"; 179 | 180 | // init Push SDK example for iOS 181 | checkPermission = async () => { 182 | const authorizationStatus = await messaging().requestPermission(); 183 | 184 | if (authorizationStatus === messaging.AuthorizationStatus.AUTHORIZED) { 185 | const deviceToken = await messaging().getToken(); 186 | 187 | RNAppMetrica.initPush(); 188 | 189 | ``` 190 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | if (project == rootProject) { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | jcenter() 7 | } 8 | 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.5.3' 11 | } 12 | } 13 | } 14 | 15 | apply plugin: 'com.android.library' 16 | 17 | def safeExtGet(prop, fallback) { 18 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 19 | } 20 | 21 | android { 22 | compileSdkVersion safeExtGet('AwesomeModule_compileSdkVersion', 31) 23 | defaultConfig { 24 | minSdkVersion safeExtGet('AwesomeModule_minSdkVersion', 16) 25 | targetSdkVersion safeExtGet('AwesomeModule_targetSdkVersion', 31) 26 | versionCode 1 27 | versionName "1.0" 28 | 29 | } 30 | 31 | buildTypes { 32 | release { 33 | minifyEnabled false 34 | } 35 | } 36 | lintOptions { 37 | disable 'GradleCompatible' 38 | } 39 | compileOptions { 40 | sourceCompatibility JavaVersion.VERSION_1_8 41 | targetCompatibility JavaVersion.VERSION_1_8 42 | } 43 | } 44 | 45 | repositories { 46 | mavenLocal() 47 | maven { 48 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 49 | url("$rootDir/../node_modules/react-native/android") 50 | } 51 | google() 52 | mavenCentral() 53 | jcenter() 54 | } 55 | 56 | dependencies { 57 | //noinspection GradleDynamicVersion 58 | implementation "com.facebook.react:react-native:+" // From node_modules 59 | implementation 'com.yandex.android:mobmetricalib:5.3.0' 60 | implementation "com.yandex.android:mobmetricapushlib:2.3.2" 61 | implementation "androidx.legacy:legacy-support-v4:1.0.0" 62 | implementation "com.android.support:support-compat:28.0.0" 63 | implementation 'com.android.installreferrer:installreferrer:1.1.2' 64 | implementation "com.google.firebase:firebase-messaging:22.0.0" 65 | implementation "com.google.android.gms:play-services-base:17.5.0" 66 | } 67 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /android/src/main/java/com/yandex/metrica/plugin/reactnative/AppMetricaModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | package com.yandex.metrica.plugin.reactnative; 10 | 11 | import android.app.Activity; 12 | import android.util.Log; 13 | 14 | import com.facebook.react.bridge.Callback; 15 | import com.facebook.react.bridge.Promise; 16 | import com.facebook.react.bridge.ReactApplicationContext; 17 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 18 | import com.facebook.react.bridge.ReactMethod; 19 | import com.facebook.react.bridge.ReadableMap; 20 | import com.yandex.metrica.YandexMetrica; 21 | import com.yandex.metrica.push.YandexMetricaPush; 22 | 23 | 24 | public class AppMetricaModule extends ReactContextBaseJavaModule { 25 | 26 | private static final String TAG = "AppMetricaModule"; 27 | 28 | private final ReactApplicationContext reactContext; 29 | 30 | public AppMetricaModule(ReactApplicationContext reactContext) { 31 | super(reactContext); 32 | this.reactContext = reactContext; 33 | } 34 | 35 | @Override 36 | public String getName() { 37 | return "AppMetrica"; 38 | } 39 | 40 | @ReactMethod 41 | public void activate(ReadableMap configMap) { 42 | YandexMetrica.activate(reactContext, Utils.toYandexMetricaConfig(configMap)); 43 | enableActivityAutoTracking(); 44 | } 45 | 46 | private void enableActivityAutoTracking() { 47 | Activity activity = getCurrentActivity(); 48 | if (activity != null) { // TODO: check 49 | YandexMetrica.enableActivityAutoTracking(activity.getApplication()); 50 | } else { 51 | Log.w(TAG, "Activity is not attached"); 52 | } 53 | } 54 | 55 | @ReactMethod 56 | public void initPush() { 57 | YandexMetricaPush.init(reactContext); 58 | } 59 | 60 | @ReactMethod 61 | public void getToken(Promise promise) { 62 | promise.resolve(YandexMetricaPush.getToken()); 63 | } 64 | 65 | @ReactMethod 66 | public void reportUserProfile(ReadableMap configAttributes) { 67 | YandexMetrica.reportUserProfile(Utils.toYandexProfileConfig(configAttributes)); 68 | } 69 | 70 | @ReactMethod 71 | public void getLibraryApiLevel(Promise promise) { 72 | promise.resolve(YandexMetrica.getLibraryApiLevel()); 73 | } 74 | 75 | @ReactMethod 76 | public void getLibraryVersion(Promise promise) { 77 | promise.resolve(YandexMetrica.getLibraryVersion()); 78 | } 79 | 80 | @ReactMethod 81 | public void pauseSession() { 82 | YandexMetrica.pauseSession(getCurrentActivity()); 83 | } 84 | 85 | @ReactMethod 86 | public void reportAppOpen(String deeplink) { 87 | YandexMetrica.reportAppOpen(deeplink); 88 | } 89 | 90 | @ReactMethod 91 | public void reportError(String message) { 92 | try { 93 | Integer.valueOf("00xffWr0ng"); 94 | } catch (Throwable error) { 95 | YandexMetrica.reportError(message, error); 96 | } 97 | } 98 | 99 | @ReactMethod 100 | public void reportEvent(String eventName, ReadableMap attributes) { 101 | if (attributes == null) { 102 | YandexMetrica.reportEvent(eventName); 103 | } else { 104 | YandexMetrica.reportEvent(eventName, attributes.toHashMap()); 105 | } 106 | } 107 | 108 | @ReactMethod 109 | public void reportReferralUrl(String referralUrl) { 110 | YandexMetrica.reportReferralUrl(referralUrl); 111 | } 112 | 113 | @ReactMethod 114 | public void requestAppMetricaDeviceID(Callback listener) { 115 | YandexMetrica.requestAppMetricaDeviceID(new ReactNativeAppMetricaDeviceIDListener(listener)); 116 | } 117 | 118 | @ReactMethod 119 | public void resumeSession() { 120 | YandexMetrica.resumeSession(getCurrentActivity()); 121 | } 122 | 123 | @ReactMethod 124 | public void sendEventsBuffer() { 125 | YandexMetrica.sendEventsBuffer(); 126 | } 127 | 128 | @ReactMethod 129 | public void setLocation(ReadableMap locationMap) { 130 | YandexMetrica.setLocation(Utils.toLocation(locationMap)); 131 | } 132 | 133 | @ReactMethod 134 | public void setLocationTracking(boolean enabled) { 135 | YandexMetrica.setLocationTracking(enabled); 136 | } 137 | 138 | @ReactMethod 139 | public void setStatisticsSending(boolean enabled) { 140 | YandexMetrica.setStatisticsSending(reactContext, enabled); 141 | } 142 | 143 | @ReactMethod 144 | public void setUserProfileID(String userProfileID) { 145 | YandexMetrica.setUserProfileID(userProfileID); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /android/src/main/java/com/yandex/metrica/plugin/reactnative/AppMetricaPackage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | package com.yandex.metrica.plugin.reactnative; 10 | 11 | import java.util.Arrays; 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | import com.facebook.react.ReactPackage; 16 | import com.facebook.react.bridge.NativeModule; 17 | import com.facebook.react.bridge.ReactApplicationContext; 18 | import com.facebook.react.uimanager.ViewManager; 19 | import com.facebook.react.bridge.JavaScriptModule; 20 | 21 | public class AppMetricaPackage implements ReactPackage { 22 | @Override 23 | public List createNativeModules(ReactApplicationContext reactContext) { 24 | return Arrays.asList(new AppMetricaModule(reactContext)); 25 | } 26 | 27 | @Override 28 | public List createViewManagers(ReactApplicationContext reactContext) { 29 | return Collections.emptyList(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /android/src/main/java/com/yandex/metrica/plugin/reactnative/ReactNativeAppMetricaDeviceIDListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | package com.yandex.metrica.plugin.reactnative; 10 | 11 | import com.facebook.react.bridge.Callback; 12 | import com.yandex.metrica.AppMetricaDeviceIDListener; 13 | 14 | public class ReactNativeAppMetricaDeviceIDListener implements AppMetricaDeviceIDListener { 15 | 16 | private final Callback listener; 17 | 18 | ReactNativeAppMetricaDeviceIDListener(Callback listener) { 19 | this.listener = listener; 20 | } 21 | 22 | @Override 23 | public void onLoaded(/* Nullable */ String deviceId) { 24 | listener.invoke(deviceId, null); 25 | } 26 | 27 | @Override 28 | public void onError(/* NonNull */ Reason reason) { 29 | listener.invoke(null, reason.toString()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /android/src/main/java/com/yandex/metrica/plugin/reactnative/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | package com.yandex.metrica.plugin.reactnative; 10 | 11 | import android.location.Location; 12 | import android.util.Log; 13 | 14 | import com.facebook.react.bridge.ReadableMap; 15 | import com.yandex.metrica.PreloadInfo; 16 | import com.yandex.metrica.YandexMetricaConfig; 17 | import com.yandex.metrica.profile.GenderAttribute; 18 | import com.yandex.metrica.profile.UserProfile; 19 | import com.yandex.metrica.profile.Attribute; 20 | 21 | import java.util.Iterator; 22 | import java.util.Map; 23 | 24 | abstract class Utils { 25 | 26 | static UserProfile toYandexProfileConfig(ReadableMap configMap) { 27 | UserProfile.Builder userProfile = UserProfile.newBuilder(); 28 | if (configMap.hasKey("name")) { 29 | userProfile.apply(Attribute.name().withValue(configMap.getString("name"))); 30 | } 31 | String floor = configMap.getString("floor"); 32 | Log.w("TAG", floor); 33 | if (configMap.hasKey("floor") && "male".equals(configMap.getString("floor"))) { 34 | userProfile.apply(Attribute.gender().withValue(GenderAttribute.Gender.MALE)); 35 | } else if(configMap.hasKey("floor") && "female".equals(configMap.getString("floor"))) { 36 | userProfile.apply(Attribute.gender().withValue(GenderAttribute.Gender.FEMALE)); 37 | } 38 | if (configMap.hasKey("age")) { 39 | userProfile.apply(Attribute.birthDate().withAge(configMap.getInt("age"))); 40 | } 41 | if (configMap.hasKey("isNotification")) { 42 | userProfile.apply(Attribute.notificationsEnabled().withValue(configMap.getBoolean("isNotification"))); 43 | } 44 | if (configMap.hasKey("isUsedHousingSearch")) { 45 | userProfile.apply(Attribute.customBoolean("Воспользовался поиском жилья").withValue(configMap.getBoolean("isUsedHousingSearch"))); 46 | } 47 | if (configMap.hasKey("isAddObjectFavorites")) { 48 | userProfile.apply(Attribute.customBoolean("Добавил объект в «Избранное»").withValue(configMap.getBoolean("isAddObjectFavorites"))); 49 | } 50 | if (configMap.hasKey("isStartedBookingProcess")) { 51 | userProfile.apply(Attribute.customBoolean("Начал процесс бронирования").withValue(configMap.getBoolean("isStartedBookingProcess"))); 52 | } 53 | if (configMap.hasKey("isSuccessBooking")) { 54 | userProfile.apply(Attribute.customBoolean("Успешная бронь").withValue(configMap.getBoolean("isSuccessBooking"))); 55 | } 56 | if (configMap.hasKey("isSuccessRegistered")) { 57 | userProfile.apply(Attribute.customBoolean("Успешно зарегистрировался").withValue(configMap.getBoolean("isSuccessRegistered"))); 58 | } 59 | return userProfile.build(); 60 | } 61 | 62 | static YandexMetricaConfig toYandexMetricaConfig(ReadableMap configMap) { 63 | YandexMetricaConfig.Builder builder = YandexMetricaConfig.newConfigBuilder(configMap.getString("apiKey")); 64 | 65 | if (configMap.hasKey("appVersion")) { 66 | builder.withAppVersion(configMap.getString("appVersion")); 67 | } 68 | if (configMap.hasKey("crashReporting")) { 69 | builder.withCrashReporting(configMap.getBoolean("crashReporting")); 70 | } 71 | if (configMap.hasKey("firstActivationAsUpdate")) { 72 | builder.handleFirstActivationAsUpdate(configMap.getBoolean("firstActivationAsUpdate")); 73 | } 74 | // if (configMap.hasKey("installedAppCollecting")) { 75 | // builder.withInstalledAppCollecting(configMap.getBoolean("installedAppCollecting")); 76 | // } 77 | if (configMap.hasKey("location")) { 78 | builder.withLocation(toLocation(configMap.getMap("location"))); 79 | } 80 | if (configMap.hasKey("locationTracking")) { 81 | builder.withLocationTracking(configMap.getBoolean("locationTracking")); 82 | } 83 | if (configMap.hasKey("logs") && configMap.getBoolean("logs")) { 84 | builder.withLogs(); 85 | } 86 | if (configMap.hasKey("maxReportsInDatabaseCount")) { 87 | builder.withMaxReportsInDatabaseCount(configMap.getInt("maxReportsInDatabaseCount")); 88 | } 89 | if (configMap.hasKey("nativeCrashReporting")) { 90 | builder.withNativeCrashReporting(configMap.getBoolean("nativeCrashReporting")); 91 | } 92 | if (configMap.hasKey("preloadInfo")) { 93 | builder.withPreloadInfo(toPreloadInfo(configMap.getMap("preloadInfo"))); 94 | } 95 | if (configMap.hasKey("sessionTimeout")) { 96 | builder.withSessionTimeout(configMap.getInt("sessionTimeout")); 97 | } 98 | if (configMap.hasKey("statisticsSending")) { 99 | builder.withStatisticsSending(configMap.getBoolean("statisticsSending")); 100 | } 101 | 102 | return builder.build(); 103 | } 104 | 105 | static Location toLocation(ReadableMap locationMap) { 106 | if (locationMap == null) { 107 | return null; 108 | } 109 | 110 | Location location = new Location("Custom"); 111 | 112 | if (locationMap.hasKey("latitude")) { 113 | location.setLatitude(locationMap.getDouble("latitude")); 114 | } 115 | if (locationMap.hasKey("longitude")) { 116 | location.setLongitude(locationMap.getDouble("longitude")); 117 | } 118 | if (locationMap.hasKey("altitude")) { 119 | location.setAltitude(locationMap.getDouble("altitude")); 120 | } 121 | if (locationMap.hasKey("accuracy")) { 122 | location.setAccuracy((float) locationMap.getDouble("accuracy")); 123 | } 124 | if (locationMap.hasKey("course")) { 125 | location.setBearing((float) locationMap.getDouble("course")); 126 | } 127 | if (locationMap.hasKey("speed")) { 128 | location.setSpeed((float) locationMap.getDouble("speed")); 129 | } 130 | if (locationMap.hasKey("timestamp")) { 131 | location.setTime((long) locationMap.getDouble("timestamp")); 132 | } 133 | 134 | return location; 135 | } 136 | 137 | private static PreloadInfo toPreloadInfo(ReadableMap preloadInfoMap) { 138 | if (preloadInfoMap == null) { 139 | return null; 140 | } 141 | 142 | PreloadInfo.Builder builder = PreloadInfo.newBuilder(preloadInfoMap.getString("trackingId")); 143 | 144 | if (preloadInfoMap.hasKey("additionalInfo")) { 145 | ReadableMap additionalInfo = preloadInfoMap.getMap("additionalInfo"); 146 | if (additionalInfo != null) { 147 | for (Map.Entry entry : additionalInfo.toHashMap().entrySet()) { 148 | Object value = entry.getValue(); 149 | builder.setAdditionalParams(entry.getKey(), value == null ? null : value.toString()); 150 | } 151 | } 152 | } 153 | 154 | return builder.build(); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | import { NativeModules, Platform } from "react-native"; 10 | 11 | const { AppMetrica } = NativeModules; 12 | 13 | type AppMetricaConfig = { 14 | apiKey: string, 15 | appVersion?: string, 16 | crashReporting?: boolean, 17 | firstActivationAsUpdate?: boolean, 18 | location: Location, 19 | locationTracking?: boolean, 20 | logs?: boolean, 21 | sessionTimeout?: number, 22 | statisticsSending?: boolean, 23 | preloadInfo?: PreloadInfo, 24 | // Only Android 25 | installedAppCollecting?: boolean, 26 | maxReportsInDatabaseCount?: number, 27 | nativeCrashReporting?: boolean, 28 | // Only iOS 29 | activationAsSessionStart?: boolean, 30 | sessionsAutoTracking?: boolean, 31 | }; 32 | 33 | type FloorType = "male" | "female"; 34 | 35 | type UserProfileConfig = { 36 | name: string, 37 | floor?: FloorType, 38 | age: number, 39 | isNotification?: boolean, 40 | isUsedHousingSearch?: boolean, 41 | isAddObjectFavorites?: boolean, 42 | isStartedBookingProcess?: boolean, 43 | isSuccessBooking?: boolean, 44 | isSuccessRegistered?: boolean, 45 | }; 46 | 47 | type PreloadInfo = { 48 | trackingId: string, 49 | additionalInfo?: Object, 50 | }; 51 | 52 | type Location = { 53 | latitude: number, 54 | longitude: number, 55 | altitude?: number, 56 | accuracy?: number, 57 | course?: number, 58 | speed?: number, 59 | timestamp?: number, 60 | }; 61 | 62 | type AppMetricaDeviceIdReason = "UNKNOWN" | "NETWORK" | "INVALID_RESPONSE"; 63 | 64 | export default { 65 | activate(config: AppMetricaConfig) { 66 | AppMetrica.activate(config); 67 | }, 68 | 69 | initPush(token = "") { 70 | if (Platform.OS === "android") { 71 | AppMetrica.initPush(); 72 | } else { 73 | AppMetrica.initPush(token); 74 | } 75 | }, 76 | 77 | getToken() { 78 | return AppMetrica.getToken(); 79 | }, 80 | 81 | reportUserProfile(config: UserProfileConfig) { 82 | AppMetrica.reportUserProfile(config); 83 | }, 84 | 85 | // Android 86 | async getLibraryApiLevel(): number { 87 | return AppMetrica.getLibraryApiLevel(); 88 | }, 89 | 90 | async getLibraryVersion(): string { 91 | return AppMetrica.getLibraryVersion(); 92 | }, 93 | 94 | pauseSession() { 95 | AppMetrica.pauseSession(); 96 | }, 97 | 98 | reportAppOpen(deeplink: ?string = null) { 99 | AppMetrica.reportAppOpen(deeplink); 100 | }, 101 | 102 | reportError(error: string, reason: Object) { 103 | AppMetrica.reportError(error); 104 | }, 105 | 106 | reportEvent(eventName: string, attributes: ?Object = null) { 107 | AppMetrica.reportEvent(eventName, attributes); 108 | }, 109 | 110 | reportReferralUrl(referralUrl: string) { 111 | AppMetrica.reportReferralUrl(referralUrl); 112 | }, 113 | 114 | requestAppMetricaDeviceID( 115 | listener: (deviceId?: String, reason?: AppMetricaDeviceIdReason) => void 116 | ) { 117 | AppMetrica.requestAppMetricaDeviceID(listener); 118 | }, 119 | 120 | resumeSession() { 121 | AppMetrica.resumeSession(); 122 | }, 123 | 124 | sendEventsBuffer() { 125 | AppMetrica.sendEventsBuffer(); 126 | }, 127 | 128 | setLocation(location: ?Location) { 129 | AppMetrica.setLocation(location); 130 | }, 131 | 132 | setLocationTracking(enabled: boolean) { 133 | AppMetrica.setLocationTracking(enabled); 134 | }, 135 | 136 | setStatisticsSending(enabled: boolean) { 137 | AppMetrica.setStatisticsSending(enabled); 138 | }, 139 | 140 | setUserProfileID(userProfileID?: string) { 141 | AppMetrica.setUserProfileID(userProfileID); 142 | }, 143 | }; 144 | -------------------------------------------------------------------------------- /ios/AppMetrica.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | #import 9 | #import 10 | 11 | 12 | @interface AppMetrica : NSObject 13 | + (NSDictionary *)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps withLaunchOptions:(NSDictionary *_Nullable)launchOptions; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/AppMetrica.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | #import 10 | #import "AppMetrica.h" 11 | #import 12 | #import "AppMetricaUtils.h" 13 | #import 14 | 15 | 16 | static NSString *const kYMMReactNativeExceptionName = @"ReactNativeException"; 17 | 18 | @implementation AppMetrica 19 | 20 | @synthesize methodQueue = _methodQueue; 21 | 22 | RCT_EXPORT_MODULE(); 23 | 24 | 25 | - (dispatch_queue_t)methodQueue { 26 | return dispatch_get_main_queue(); 27 | } 28 | 29 | + (BOOL)requiresMainQueueSetup { 30 | return YES; 31 | } 32 | 33 | 34 | + (NSDictionary *)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps withLaunchOptions:(NSDictionary *_Nullable)launchOptions { 35 | NSMutableDictionary *appProperties = userProps != nil ? [userProps mutableCopy] : [NSMutableDictionary dictionary]; 36 | appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(NO)]); 37 | 38 | if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { 39 | if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { 40 | appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(YES)]); 41 | } 42 | } 43 | 44 | return [NSDictionary dictionaryWithDictionary:appProperties]; 45 | } 46 | 47 | 48 | RCT_EXPORT_METHOD(activate:(NSDictionary *)configDict) 49 | { 50 | [YMMYandexMetrica activateWithConfiguration:[AppMetricaUtils configurationForDictionary:configDict]]; 51 | } 52 | 53 | RCT_EXPORT_METHOD(reportUserProfile:(NSDictionary *)configDict) 54 | { 55 | [YMMYandexMetrica reportUserProfile:[AppMetricaUtils configurationForUserProfile:configDict] onFailure:^(NSError *error) { 56 | NSLog(@"Error: %@", error); 57 | }]; 58 | } 59 | 60 | 61 | 62 | RCT_EXPORT_METHOD(initPush:(NSData *)deviceToken) 63 | { 64 | 65 | #ifdef DEBUG 66 | YMPYandexMetricaPushEnvironment pushEnvironment = YMPYandexMetricaPushEnvironmentDevelopment; 67 | #else 68 | YMPYandexMetricaPushEnvironment pushEnvironment = YMPYandexMetricaPushEnvironmentProduction; 69 | #endif 70 | [YMPYandexMetricaPush setDeviceTokenFromData:[FIRMessaging messaging].APNSToken pushEnvironment:pushEnvironment]; 71 | 72 | } 73 | 74 | RCT_EXPORT_METHOD(getLibraryApiLevel) 75 | { 76 | // It does nothing for iOS 77 | } 78 | 79 | RCT_EXPORT_METHOD(getLibraryVersion:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) 80 | { 81 | resolve([YMMYandexMetrica libraryVersion]); 82 | } 83 | 84 | RCT_EXPORT_METHOD(pauseSession) 85 | { 86 | [YMMYandexMetrica pauseSession]; 87 | } 88 | 89 | RCT_EXPORT_METHOD(reportAppOpen:(NSString *)deeplink) 90 | { 91 | [YMMYandexMetrica handleOpenURL:[NSURL URLWithString:deeplink]]; 92 | } 93 | 94 | 95 | 96 | 97 | RCT_EXPORT_METHOD(reportError:(NSString *)message) { 98 | NSException *exception = [[NSException alloc] initWithName:message reason:nil userInfo:nil]; 99 | [YMMYandexMetrica reportError:message exception:exception onFailure:NULL]; 100 | } 101 | 102 | RCT_EXPORT_METHOD(reportEvent:(NSString *)eventName:(NSDictionary *)attributes) 103 | { 104 | if (attributes == nil) { 105 | [YMMYandexMetrica reportEvent:eventName onFailure:^(NSError *error) { 106 | NSLog(@"error: %@", [error localizedDescription]); 107 | }]; 108 | } else { 109 | [YMMYandexMetrica reportEvent:eventName parameters:attributes onFailure:^(NSError *error) { 110 | NSLog(@"error: %@", [error localizedDescription]); 111 | }]; 112 | } 113 | } 114 | 115 | RCT_EXPORT_METHOD(reportReferralUrl:(NSString *)referralUrl) 116 | { 117 | [YMMYandexMetrica reportReferralUrl:[NSURL URLWithString:referralUrl]]; 118 | } 119 | 120 | RCT_EXPORT_METHOD(requestAppMetricaDeviceID:(RCTResponseSenderBlock)listener) 121 | { 122 | YMMAppMetricaDeviceIDRetrievingBlock completionBlock = ^(NSString *_Nullable appMetricaDeviceID, NSError *_Nullable error) { 123 | listener(@[[self wrap:appMetricaDeviceID], [self wrap:[AppMetricaUtils stringFromRequestDeviceIDError:error]]]); 124 | }; 125 | [YMMYandexMetrica requestAppMetricaDeviceIDWithCompletionQueue:nil completionBlock:completionBlock]; 126 | } 127 | 128 | RCT_EXPORT_METHOD(resumeSession) 129 | { 130 | [YMMYandexMetrica resumeSession]; 131 | } 132 | 133 | RCT_EXPORT_METHOD(sendEventsBuffer) 134 | { 135 | [YMMYandexMetrica sendEventsBuffer]; 136 | } 137 | 138 | RCT_EXPORT_METHOD(setLocation:(NSDictionary *)locationDict) 139 | { 140 | [YMMYandexMetrica setLocation:[AppMetricaUtils locationForDictionary:locationDict]]; 141 | } 142 | 143 | RCT_EXPORT_METHOD(setLocationTracking:(BOOL)enabled) 144 | { 145 | [YMMYandexMetrica setLocationTracking:enabled]; 146 | } 147 | 148 | RCT_EXPORT_METHOD(setStatisticsSending:(BOOL)enabled) 149 | { 150 | [YMMYandexMetrica setStatisticsSending:enabled]; 151 | } 152 | 153 | RCT_EXPORT_METHOD(setUserProfileID:(NSString *)userProfileID) 154 | { 155 | [YMMYandexMetrica setUserProfileID:userProfileID]; 156 | } 157 | 158 | - (NSObject *)wrap:(NSObject *)value 159 | { 160 | if (value == nil) { 161 | return [NSNull null]; 162 | } 163 | return value; 164 | } 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /ios/AppMetrica.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 216E37E423ABB07000694F71 /* AppMetricaUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 216E37E323ABB07000694F71 /* AppMetricaUtils.m */; }; 11 | B3E7B58A1CC2AC0600A0062D /* AppMetrica.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* AppMetrica.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = "include/$(PRODUCT_NAME)"; 19 | dstSubfolderSpec = 16; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 0; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 134814201AA4EA6300B7C361 /* libAppMetrica.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAppMetrica.a; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 216E37E223ABAFE400694F71 /* AppMetricaUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppMetricaUtils.h; sourceTree = ""; }; 29 | 216E37E323ABB07000694F71 /* AppMetricaUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppMetricaUtils.m; sourceTree = ""; }; 30 | B3E7B5881CC2AC0600A0062D /* AppMetrica.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppMetrica.h; sourceTree = ""; }; 31 | B3E7B5891CC2AC0600A0062D /* AppMetrica.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppMetrica.m; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 134814211AA4EA7D00B7C361 /* Products */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | 134814201AA4EA6300B7C361 /* libAppMetrica.a */, 49 | ); 50 | name = Products; 51 | sourceTree = ""; 52 | }; 53 | 58B511D21A9E6C8500147676 = { 54 | isa = PBXGroup; 55 | children = ( 56 | 216E37E323ABB07000694F71 /* AppMetricaUtils.m */, 57 | 216E37E223ABAFE400694F71 /* AppMetricaUtils.h */, 58 | B3E7B5881CC2AC0600A0062D /* AppMetrica.h */, 59 | B3E7B5891CC2AC0600A0062D /* AppMetrica.m */, 60 | 134814211AA4EA7D00B7C361 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | /* End PBXGroup section */ 65 | 66 | /* Begin PBXNativeTarget section */ 67 | 58B511DA1A9E6C8500147676 /* AppMetrica */ = { 68 | isa = PBXNativeTarget; 69 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "AppMetrica" */; 70 | buildPhases = ( 71 | 58B511D71A9E6C8500147676 /* Sources */, 72 | 58B511D81A9E6C8500147676 /* Frameworks */, 73 | 58B511D91A9E6C8500147676 /* CopyFiles */, 74 | ); 75 | buildRules = ( 76 | ); 77 | dependencies = ( 78 | ); 79 | name = AppMetrica; 80 | productName = RCTDataManager; 81 | productReference = 134814201AA4EA6300B7C361 /* libAppMetrica.a */; 82 | productType = "com.apple.product-type.library.static"; 83 | }; 84 | /* End PBXNativeTarget section */ 85 | 86 | /* Begin PBXProject section */ 87 | 58B511D31A9E6C8500147676 /* Project object */ = { 88 | isa = PBXProject; 89 | attributes = { 90 | LastUpgradeCheck = 0920; 91 | ORGANIZATIONNAME = Facebook; 92 | TargetAttributes = { 93 | 58B511DA1A9E6C8500147676 = { 94 | CreatedOnToolsVersion = 6.1.1; 95 | }; 96 | }; 97 | }; 98 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "AppMetrica" */; 99 | compatibilityVersion = "Xcode 3.2"; 100 | developmentRegion = English; 101 | hasScannedForEncodings = 0; 102 | knownRegions = ( 103 | English, 104 | en, 105 | ); 106 | mainGroup = 58B511D21A9E6C8500147676; 107 | productRefGroup = 58B511D21A9E6C8500147676; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | 58B511DA1A9E6C8500147676 /* AppMetrica */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | 58B511D71A9E6C8500147676 /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | B3E7B58A1CC2AC0600A0062D /* AppMetrica.m in Sources */, 122 | 216E37E423ABB07000694F71 /* AppMetricaUtils.m in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | 58B511ED1A9E6C8500147676 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 134 | CLANG_CXX_LIBRARY = "libc++"; 135 | CLANG_ENABLE_MODULES = YES; 136 | CLANG_ENABLE_OBJC_ARC = YES; 137 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 138 | CLANG_WARN_BOOL_CONVERSION = YES; 139 | CLANG_WARN_COMMA = YES; 140 | CLANG_WARN_CONSTANT_CONVERSION = YES; 141 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 142 | CLANG_WARN_EMPTY_BODY = YES; 143 | CLANG_WARN_ENUM_CONVERSION = YES; 144 | CLANG_WARN_INFINITE_RECURSION = YES; 145 | CLANG_WARN_INT_CONVERSION = YES; 146 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 147 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 148 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 149 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 150 | CLANG_WARN_STRICT_PROTOTYPES = YES; 151 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 152 | CLANG_WARN_UNREACHABLE_CODE = YES; 153 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 154 | COPY_PHASE_STRIP = NO; 155 | ENABLE_STRICT_OBJC_MSGSEND = YES; 156 | ENABLE_TESTABILITY = YES; 157 | GCC_C_LANGUAGE_STANDARD = gnu99; 158 | GCC_DYNAMIC_NO_PIC = NO; 159 | GCC_NO_COMMON_BLOCKS = YES; 160 | GCC_OPTIMIZATION_LEVEL = 0; 161 | GCC_PREPROCESSOR_DEFINITIONS = ( 162 | "DEBUG=1", 163 | "$(inherited)", 164 | ); 165 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 166 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 167 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 168 | GCC_WARN_UNDECLARED_SELECTOR = YES; 169 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 170 | GCC_WARN_UNUSED_FUNCTION = YES; 171 | GCC_WARN_UNUSED_VARIABLE = YES; 172 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 173 | MTL_ENABLE_DEBUG_INFO = YES; 174 | ONLY_ACTIVE_ARCH = YES; 175 | SDKROOT = iphoneos; 176 | }; 177 | name = Debug; 178 | }; 179 | 58B511EE1A9E6C8500147676 /* Release */ = { 180 | isa = XCBuildConfiguration; 181 | buildSettings = { 182 | ALWAYS_SEARCH_USER_PATHS = NO; 183 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 184 | CLANG_CXX_LIBRARY = "libc++"; 185 | CLANG_ENABLE_MODULES = YES; 186 | CLANG_ENABLE_OBJC_ARC = YES; 187 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 188 | CLANG_WARN_BOOL_CONVERSION = YES; 189 | CLANG_WARN_COMMA = YES; 190 | CLANG_WARN_CONSTANT_CONVERSION = YES; 191 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 192 | CLANG_WARN_EMPTY_BODY = YES; 193 | CLANG_WARN_ENUM_CONVERSION = YES; 194 | CLANG_WARN_INFINITE_RECURSION = YES; 195 | CLANG_WARN_INT_CONVERSION = YES; 196 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 197 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 198 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 199 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 200 | CLANG_WARN_STRICT_PROTOTYPES = YES; 201 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 202 | CLANG_WARN_UNREACHABLE_CODE = YES; 203 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 204 | COPY_PHASE_STRIP = YES; 205 | ENABLE_NS_ASSERTIONS = NO; 206 | ENABLE_STRICT_OBJC_MSGSEND = YES; 207 | GCC_C_LANGUAGE_STANDARD = gnu99; 208 | GCC_NO_COMMON_BLOCKS = YES; 209 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 210 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 211 | GCC_WARN_UNDECLARED_SELECTOR = YES; 212 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 213 | GCC_WARN_UNUSED_FUNCTION = YES; 214 | GCC_WARN_UNUSED_VARIABLE = YES; 215 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 216 | MTL_ENABLE_DEBUG_INFO = NO; 217 | SDKROOT = iphoneos; 218 | VALIDATE_PRODUCT = YES; 219 | }; 220 | name = Release; 221 | }; 222 | 58B511F01A9E6C8500147676 /* Debug */ = { 223 | isa = XCBuildConfiguration; 224 | buildSettings = { 225 | FRAMEWORK_SEARCH_PATHS = ( 226 | "$(PROJECT_DIR)/../../../ios/Frameworks", 227 | "$(PROJECT_DIR)/../../../ios", 228 | ); 229 | HEADER_SEARCH_PATHS = ( 230 | "$(inherited)", 231 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 232 | "$(SRCROOT)/../../../React/**", 233 | "$(SRCROOT)/../../react-native/React/**", 234 | ); 235 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 236 | OTHER_LDFLAGS = "-ObjC"; 237 | PRODUCT_NAME = AppMetrica; 238 | SKIP_INSTALL = YES; 239 | }; 240 | name = Debug; 241 | }; 242 | 58B511F11A9E6C8500147676 /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | FRAMEWORK_SEARCH_PATHS = ( 246 | "$(PROJECT_DIR)/../../../ios/Frameworks", 247 | "$(PROJECT_DIR)/../../../ios", 248 | ); 249 | HEADER_SEARCH_PATHS = ( 250 | "$(inherited)", 251 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 252 | "$(SRCROOT)/../../../React/**", 253 | "$(SRCROOT)/../../react-native/React/**", 254 | ); 255 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 256 | OTHER_LDFLAGS = "-ObjC"; 257 | PRODUCT_NAME = AppMetrica; 258 | SKIP_INSTALL = YES; 259 | }; 260 | name = Release; 261 | }; 262 | /* End XCBuildConfiguration section */ 263 | 264 | /* Begin XCConfigurationList section */ 265 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "AppMetrica" */ = { 266 | isa = XCConfigurationList; 267 | buildConfigurations = ( 268 | 58B511ED1A9E6C8500147676 /* Debug */, 269 | 58B511EE1A9E6C8500147676 /* Release */, 270 | ); 271 | defaultConfigurationIsVisible = 0; 272 | defaultConfigurationName = Release; 273 | }; 274 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "AppMetrica" */ = { 275 | isa = XCConfigurationList; 276 | buildConfigurations = ( 277 | 58B511F01A9E6C8500147676 /* Debug */, 278 | 58B511F11A9E6C8500147676 /* Release */, 279 | ); 280 | defaultConfigurationIsVisible = 0; 281 | defaultConfigurationName = Release; 282 | }; 283 | /* End XCConfigurationList section */ 284 | }; 285 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 286 | } 287 | -------------------------------------------------------------------------------- /ios/AppMetrica.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/AppMetricaUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface AppMetricaUtils : NSObject 14 | 15 | + (YMMYandexMetricaConfiguration *)configurationForDictionary:(NSDictionary *)configDict; 16 | + (YMMYandexMetricaConfiguration *)configurationForUserProfile:(NSDictionary *)configDict; 17 | + (CLLocation *)locationForDictionary:(NSDictionary *)locationDict; 18 | + (NSString *)stringFromRequestDeviceIDError:(NSError *)error; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ios/AppMetricaUtils.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Version for React Native 3 | * © 2020 YANDEX 4 | * You may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * https://yandex.com/legal/appmetrica_sdk_agreement/ 7 | */ 8 | 9 | #import "AppMetricaUtils.h" 10 | 11 | @implementation AppMetricaUtils 12 | 13 | + (YMMYandexMetricaConfiguration *)configurationForDictionary:(NSDictionary *)configDict 14 | { 15 | NSString *apiKey = configDict[@"apiKey"]; 16 | YMMYandexMetricaConfiguration *configuration = [[YMMYandexMetricaConfiguration alloc] initWithApiKey:apiKey]; 17 | 18 | if (configDict[@"appVersion"] != nil) { 19 | configuration.appVersion = configDict[@"appVersion"]; 20 | } 21 | if (configDict[@"crashReporting"] != nil) { 22 | configuration.crashReporting = [configDict[@"crashReporting"] boolValue]; 23 | } 24 | if (configDict[@"activationAsSessionStart"] != nil) { 25 | configuration.handleActivationAsSessionStart = [configDict[@"activationAsSessionStart"] boolValue]; 26 | } 27 | if (configDict[@"firstActivationAsUpdate"] != nil) { 28 | configuration.handleFirstActivationAsUpdate = [configDict[@"firstActivationAsUpdate"] boolValue]; 29 | } 30 | if (configDict[@"location"] != nil) { 31 | configuration.location = [self locationForDictionary:configDict[@"location"]]; 32 | } 33 | if (configDict[@"locationTracking"] != nil) { 34 | configuration.locationTracking = [configDict[@"locationTracking"] boolValue]; 35 | } 36 | if (configDict[@"logs"] != nil) { 37 | configuration.logs = [configDict[@"logs"] boolValue]; 38 | } 39 | if (configDict[@"preloadInfo"] != nil) { 40 | configuration.preloadInfo = [[self class] preloadInfoForDictionary:configDict[@"preloadInfo"]]; 41 | } 42 | if (configDict[@"sessionsAutoTracking"] != nil) { 43 | configuration.sessionsAutoTracking = [configDict[@"sessionsAutoTracking"] boolValue]; 44 | } 45 | if (configDict[@"sessionTimeout"] != nil) { 46 | configuration.sessionTimeout = [configDict[@"sessionTimeout"] unsignedIntegerValue]; 47 | } 48 | if (configDict[@"statisticsSending"] != nil) { 49 | configuration.statisticsSending = [configDict[@"statisticsSending"] boolValue]; 50 | } 51 | 52 | return configuration; 53 | } 54 | 55 | 56 | + (YMMMutableUserProfile *)configurationForUserProfile:(NSDictionary *)configDict 57 | { 58 | YMMMutableUserProfile *profile = [[YMMMutableUserProfile alloc] init]; 59 | 60 | id timeLeftAttribute = [YMMProfileAttribute customCounter:@"time_left"]; 61 | [profile apply:[timeLeftAttribute withDelta:-4.42]]; 62 | 63 | if (configDict[@"name"] != nil) { 64 | id nameAttribute = [YMMProfileAttribute name]; 65 | [profile apply:[nameAttribute withValue:configDict[@"name"]]]; 66 | } 67 | if (configDict[@"floor"] != nil && [configDict[@"floor"] isEqualToString:@"male"]) { 68 | id genderAttribute = [YMMProfileAttribute gender]; 69 | [profile apply:[genderAttribute withValue:YMMGenderTypeMale]]; 70 | } 71 | if (configDict[@"floor"] != nil && [configDict[@"floor"] isEqualToString:@"female"]) { 72 | id genderAttribute = [YMMProfileAttribute gender]; 73 | [profile apply:[genderAttribute withValue:YMMGenderTypeFemale]]; 74 | } 75 | if (configDict[@"age"] != nil) { 76 | NSNumber *age = configDict[@"age"]; 77 | id birthDateAttribute = [YMMProfileAttribute birthDate]; 78 | [profile apply:[birthDateAttribute withAge:[age unsignedIntegerValue]]]; 79 | } 80 | if (configDict[@"isNotification"] != nil) { 81 | id isNotificationAttribute = [YMMProfileAttribute notificationsEnabled]; 82 | [profile apply:[isNotificationAttribute withValue:configDict[@"isNotification"]]]; 83 | } 84 | if (configDict[@"isUsedHousingSearch"] != nil) { 85 | id isUsedHousingSearch = [YMMProfileAttribute customBool:@"Воспользовался поиском жилья"]; 86 | [profile apply:[isUsedHousingSearch withValue:configDict[@"isUsedHousingSearch"]]]; 87 | } 88 | if (configDict[@"isAddObjectFavorites"] != nil) { 89 | id isAddObjectFavorites = [YMMProfileAttribute customBool:@"Добавил объект в «Избранное»"]; 90 | [profile apply:[isAddObjectFavorites withValue:configDict[@"isAddObjectFavorites"]]]; 91 | } 92 | if (configDict[@"isStartedBookingProcess"] != nil) { 93 | id isStartedBookingProcess = [YMMProfileAttribute customBool:@"Начал процесс бронирования"]; 94 | [profile apply:[isStartedBookingProcess withValue:configDict[@"isStartedBookingProcess"]]]; 95 | } 96 | if (configDict[@"isSuccessBooking"] != nil) { 97 | id isSuccessBooking = [YMMProfileAttribute customBool:@"Успешная бронь"]; 98 | [profile apply:[isSuccessBooking withValue:configDict[@"isSuccessBooking"]]]; 99 | } 100 | if (configDict[@"isSuccessRegistered"] != nil) { 101 | id isSuccessRegistered = [YMMProfileAttribute customBool:@"Успешно зарегистрировался"]; 102 | [profile apply:[isSuccessRegistered withValue:configDict[@"isSuccessRegistered"]]]; 103 | } 104 | 105 | return profile; 106 | } 107 | 108 | + (CLLocation *)locationForDictionary:(NSDictionary *)locationDict 109 | { 110 | if (locationDict == nil) { 111 | return nil; 112 | } 113 | 114 | NSNumber *latitude = locationDict[@"latitude"]; 115 | NSNumber *longitude = locationDict[@"longitude"]; 116 | NSNumber *altitude = locationDict[@"altitude"]; 117 | NSNumber *horizontalAccuracy = locationDict[@"accuracy"]; 118 | NSNumber *verticalAccuracy = locationDict[@"verticalAccuracy"]; 119 | NSNumber *course = locationDict[@"course"]; 120 | NSNumber *speed = locationDict[@"speed"]; 121 | NSNumber *timestamp = locationDict[@"timestamp"]; 122 | 123 | NSDate *locationDate = timestamp != nil ? [NSDate dateWithTimeIntervalSince1970:timestamp.doubleValue] : [NSDate date]; 124 | CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude.doubleValue, longitude.doubleValue); 125 | CLLocation *location = [[CLLocation alloc] initWithCoordinate:coordinate 126 | altitude:altitude.doubleValue 127 | horizontalAccuracy:horizontalAccuracy.doubleValue 128 | verticalAccuracy:verticalAccuracy.doubleValue 129 | course:course.doubleValue 130 | speed:speed.doubleValue 131 | timestamp:locationDate]; 132 | 133 | return location; 134 | } 135 | 136 | + (YMMYandexMetricaPreloadInfo *)preloadInfoForDictionary:(NSDictionary *)preloadInfoDict 137 | { 138 | if (preloadInfoDict == nil) { 139 | return nil; 140 | } 141 | 142 | NSString *trackingId = preloadInfoDict[@"trackingId"]; 143 | YMMYandexMetricaPreloadInfo *preloadInfo = [[YMMYandexMetricaPreloadInfo alloc] initWithTrackingIdentifier:trackingId]; 144 | 145 | NSDictionary *additionalInfo = preloadInfoDict[@"additionalInfo"]; 146 | if (additionalInfo != nil) { 147 | for (NSString *key in additionalInfo) { 148 | [preloadInfo setAdditionalInfo:additionalInfo[key] forKey:key]; 149 | } 150 | } 151 | 152 | return preloadInfo; 153 | } 154 | 155 | + (NSString *)stringFromRequestDeviceIDError:(NSError *)error 156 | { 157 | if (error == nil) { 158 | return nil; 159 | } 160 | if ([error.domain isEqualToString:NSURLErrorDomain]) { 161 | return @"NETWORK"; 162 | } 163 | return @"UNKNOWN"; 164 | } 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-appmetrica-next", 3 | "title": "Yandex AppMetrica React Native Plugin && AppMetricaPushSDK (fireBase CloudMessage)", 4 | "version": "2.8.0", 5 | "description": "React Native plugin for AppMetrica analytics tool", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/aspidvip/react-native-appmetrica-next.git" 13 | }, 14 | "keywords": [ 15 | "yandex", 16 | "appmetrica", 17 | "metrica", 18 | "pushSDK", 19 | "push", 20 | "sdk", 21 | "analytics", 22 | "tracking", 23 | "react-native", 24 | "ecosystem:react-native", 25 | "react-native-ios", 26 | "react-native-android" 27 | ], 28 | "author": { 29 | "name": "YANDEX LLC && Andrey Bondarenko" 30 | }, 31 | "license": "MIT", 32 | "homepage": "https://appmetrica.yandex.com/docs", 33 | "peerDependencies": { 34 | "react-native": ">=0.68.0 <1.0.x" 35 | }, 36 | "devDependencies": {} 37 | } 38 | -------------------------------------------------------------------------------- /react-native-appmetrica-next.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = "react-native-appmetrica-next" 7 | s.version = package["version"] 8 | s.summary = package["description"] 9 | s.homepage = package["homepage"] 10 | s.license = package["license"] 11 | s.authors = { "Yandex LLC" => "appmetrica@yandex-team.com" } 12 | s.platforms = { :ios => "9.0" } 13 | s.source = { :git => "https://github.com/yandexmobile/react-native-appmetrica-next.git", :tag => "#{s.version}" } 14 | 15 | s.source_files = "ios/**/*.{h,m,swift}" 16 | s.requires_arc = true 17 | 18 | s.dependency "React" 19 | s.dependency 'YandexMobileMetrica', '4.5.2' 20 | s.dependency 'YandexMobileMetricaPush', '1.3.0' 21 | end 22 | --------------------------------------------------------------------------------