/* * Created by chenru on 2019/08/27. * Copyright 2015-2020 Sensors Data Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sensorsdata.analytics; import android.text.TextUtils; import android.util.Log; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableNativeMap; import com.sensorsdata.analytics.android.sdk.SensorsDataAPI; import com.sensorsdata.analytics.utils.RNUtils; import org.json.JSONObject; import java.util.HashSet; /** * Created by yang on 2017/4/5 * <p> * 参数类型在@ReactMethod注明的方法中,会被直接映射到它们对应的JavaScript类型 * String -> String * ReadableMap -> Object * Boolean -> Bool * Integer -> Number * Double -> Number * Float -> Number * Callback -> function * ReadableArray -> Array */ public class RNSensorsAnalyticsModule extends ReactContextBaseJavaModule { public RNSensorsAnalyticsModule(ReactApplicationContext reactContext) { super(reactContext); } private static final String MODULE_NAME = "RNSensorsAnalyticsModule"; private static final String LOGTAG = "SA.RN"; /** * 返回一个字符串名字,这个名字在 JavaScript (RN)端标记这个模块。 */ @Override public String getName() { return MODULE_NAME; } /** * 参数类型在@ReactMethod注明的方法中,会被直接映射到它们对应的JavaScript类型 * String -> String * ReadableMap -> Object * Boolean -> Bool * Integer -> Number * Double -> Number * Float -> Number * Callback -> function * ReadableArray -> Array * <p> * 导出 track 方法给 RN 使用. * * @param eventName 事件名称 * @param properties 事件的具体属性 * <p> * RN 中使用示例:(记录 RN_AddToFav 事件,事件属性 "ProductID":123456,"UserLevel":"VIP") * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.track("RN_AddToFav",{"ProductID":123456,"UserLevel":"VIP"})}> * </Button> */ @ReactMethod public void track(String eventName, ReadableMap properties) { try { SensorsDataAPI.sharedInstance().track(eventName, RNUtils.convertToJSONObject(properties)); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 trackTimerStart 方法给 RN 使用. * <p> * 初始化事件的计时器,默认计时单位为秒(计时开始). * * @param eventName 事件的名称. * <p> * RN 中使用示例:(计时器事件名称 viewTimer ) * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.trackTimerStart("viewTimer")}> * </Button> */ @ReactMethod public void trackTimerStart(String eventName) { try { SensorsDataAPI.sharedInstance().trackTimerStart(eventName); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 trackTimerBegin 方法给 RN 使用. * <p> * 初始化事件的计时器,默认计时单位为毫秒(计时开始). * * @param eventName 事件的名称. * <p> * RN 中使用示例:(计时器事件名称 viewTimer ) * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.trackTimerBegin("viewTimer")}> * </Button> */ @ReactMethod public void trackTimerBegin(String eventName) { try { SensorsDataAPI.sharedInstance().trackTimerBegin(eventName); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 trackTimerEnd 方法给 RN 使用. * <p> * 初始化事件的计时器,默认计时单位为毫秒(计时结束,并触发事件) * * @param eventName 事件的名称. * <p> * RN 中使用示例:(计时器事件名称 viewTimer ) * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.trackTimerEnd("viewTimer",{"ProductID":123456,"UserLevel":"VIP"})}> * </Button> */ @ReactMethod public void trackTimerEnd(String eventName, ReadableMap properties) { try { SensorsDataAPI.sharedInstance().trackTimerEnd(eventName, RNUtils.convertToJSONObject(properties)); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 clearTrackTimer 方法给 RN 使用. * <p> * 清除所有事件计时器 * <p> * RN 中使用示例:(保存用户的属性 "sex":"男") * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.clearTrackTimer()}> * </Button> */ @ReactMethod public void clearTrackTimer() { try { SensorsDataAPI.sharedInstance().clearTrackTimer(); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 login 方法给 RN 使用. * * @param loginId RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.login("[email protected]")}> * </Button> */ @ReactMethod public void login(String loginId) { try { SensorsDataAPI.sharedInstance().login(loginId); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 logout 方法给 RN 使用. * <p> * RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.logout()}> * </Button> */ @ReactMethod public void logout() { try { SensorsDataAPI.sharedInstance().logout(); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 trackInstallation 方法给 RN 使用. * <p> * 用于记录首次安装激活、渠道追踪的事件. * * @param eventName 事件名. * @param properties 事件属性. * <p> * RN 中使用示例:( 这里事件名为 AppInstall ,事件的渠道属性 "$utm_source":"渠道A","$utm_campaign":"广告A" ) * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.trackInstallation("AppInstall",{"$utm_source":"渠道A","$utm_campaign":"广告A"})}> * </Button> */ @ReactMethod public void trackInstallation(String eventName, ReadableMap properties) { try { SensorsDataAPI.sharedInstance().trackInstallation(eventName, RNUtils.convertToJSONObject(properties)); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 trackViewScreen 方法给 RN 使用. * <p> * 此方法用于 RN 中切换页面的时候调用,用于记录 $AppViewScreen 事件. * * @param url 页面的 url 记录到 $url 字段中. * @param properties 页面的属性. * <p> * 注:为保证记录到的 $AppViewScreen 事件和 Auto Track 采集的一致, * 需要传入 $title(页面的标题) 、$screen_name (页面的名称,即 包名.类名)字段. * <p> * RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.trackViewScreen(url, {"$title":"RN主页","$screen_name":"cn.sensorsdata.demo.RNHome"})}> * </Button> */ @ReactMethod public void trackViewScreen(String url, ReadableMap properties) { try { RNAgent.trackViewScreen(url, RNUtils.convertToJSONObject(properties), false); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 profileSet 方法给 RN 使用. * * @param properties 用户属性 * <p> * RN 中使用示例:(保存用户的属性 "sex":"男") * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.profileSet({"sex":"男"})}> * </Button> */ @ReactMethod public void profileSet(ReadableMap properties) { try { SensorsDataAPI.sharedInstance().profileSet(RNUtils.convertToJSONObject(properties)); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 profileSetOnce 方法给 RN 使用. * <p> * 首次设置用户的一个或多个 Profile. * 与profileSet接口不同的是,如果之前存在,则忽略,否则,新创建. * * @param properties 属性列表 * <p> * RN 中使用示例:(保存用户的属性 "sex":"男") * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.profileSetOnce({"sex":"男"})}> * </Button> */ @ReactMethod public void profileSetOnce(ReadableMap properties) { try { SensorsDataAPI.sharedInstance().profileSetOnce(RNUtils.convertToJSONObject(properties)); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 profileIncrement 方法给 RN 使用. * <p> * 给一个数值类型的Profile增加一个数值. 只能对数值型属性进行操作,若该属性 * 未设置,则添加属性并设置默认值为0. * * @param property 属性名称 * @param value 属性的值,值的类型只允许为 Number . * <p> * RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.profileIncrement("money",10)}> * </Button> */ @ReactMethod public void profileIncrement(String property, Double value) { try { SensorsDataAPI.sharedInstance().profileIncrement(property, value); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 profileAppend 方法给 RN 使用. * <p> * 给一个列表类型的 Profile 增加一个元素. * * @param property 属性名称. * @param strList 新增的元素. * <p> * RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.profileAppend("VIP",["Gold","Diamond"])}> * </Button> */ @ReactMethod public void profileAppend(String property, ReadableArray strList) { try { HashSet<String> strSet = new HashSet<>(); for (int i = 0; i < strList.size(); i++) { strSet.add(strList.getString(i)); } SensorsDataAPI.sharedInstance().profileAppend(property, strSet); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 profileUnset 方法给 RN 使用. * <p> * 删除用户的一个 Profile. * * @param property 属性名称. * <p> * RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.profileUnset("sex")}> * </Button> */ @ReactMethod public void profileUnset(String property) { try { SensorsDataAPI.sharedInstance().profileUnset(property); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 profileDelete 方法给 RN 使用. * <p> * 删除用户所有 Profile. * <p> * RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.profileDelete()}> * </Button> */ @ReactMethod public void profileDelete() { try { SensorsDataAPI.sharedInstance().profileDelete(); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 getDistinctId 方法给 RN 使用. * <p> * 获取当前的 DistinctId. * <p> * successCallback 优先返回 mLoginId ,否则返回 mAnonymousId * <p> * RN 中使用示例: * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.getDistinctId(success=>{ * console.log(success) * }, * error=>{ * console.log(error) * }) * }> * </Button> */ @ReactMethod public void getDistinctId(Callback successCallback, Callback errorCallback) { try { String mLoginId = SensorsDataAPI.sharedInstance().getLoginId(); if (!TextUtils.isEmpty(mLoginId)) { successCallback.invoke(mLoginId); } else { successCallback.invoke(SensorsDataAPI.sharedInstance().getAnonymousId()); } } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); errorCallback.invoke(e.getMessage()); } } /** * 导出 getDistinctIdPromise 方法给 RN 使用. * <p> * Promise 方式,获取 distinctId * <p> * RN 中使用示例: * async getDistinctIdPromise() { * var distinctId = await RNSensorsAnalyticsModule.getDistinctIdPromise() * }; */ @ReactMethod public void getDistinctIdPromise(Promise promise) { try { String mLoginId = SensorsDataAPI.sharedInstance().getLoginId(); if (!TextUtils.isEmpty(mLoginId)) { promise.resolve(mLoginId); } else { promise.resolve(SensorsDataAPI.sharedInstance().getAnonymousId()); } } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); promise.reject("getDistinctId fail", e); } } /** * 导出 getAnonymousIdPromise 方法给 RN 使用. * <p> * Promise 方式 getAnonymousId 获取匿名 ID. * <p> * RN 中使用示例: * async getAnonymousIdPromise() { * var anonymousId = await RNSensorsAnalyticsModule.getAnonymousIdPromise() * }; */ @ReactMethod public void getAnonymousIdPromise(Promise promise) { try { promise.resolve(SensorsDataAPI.sharedInstance().getAnonymousId()); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); promise.reject("getDistinctId fail", e); } } /** * 导出 registerSuperProperties 方法给 RN 使用. * * @param properties 要设置的公共属性 * <p> * RN 中使用示例:(设置公共属性 "Platform":"Android") * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.registerSuperProperties({"Platform":"Android"})}> * </Button> */ @ReactMethod public void registerSuperProperties(ReadableMap properties) { try { SensorsDataAPI.sharedInstance().registerSuperProperties(RNUtils.convertToJSONObject(properties)); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 unregisterSuperProperty 方法给 RN 使用. * * @param property 要删除的公共属性属性 * <p> * RN 中使用示例:(删除公共属性 "Platform") * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.unregisterSuperProperty("Platform")}> * </Button> */ @ReactMethod public void unregisterSuperProperty(String property) { try { SensorsDataAPI.sharedInstance().unregisterSuperProperty(property); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 clearSuperProperties 方法给 RN 使用. * <p> * RN 中使用示例:(删除所有已设置的公共属性) * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.clearSuperProperties()}> * </Button> */ @ReactMethod public void clearSuperProperties() { try { SensorsDataAPI.sharedInstance().clearSuperProperties(); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 flush 方法给 RN 使用. * <p> * RN 中使用示例:(强制发送数据到服务端) * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.flush()}> * </Button> */ @ReactMethod public void flush() { try { SensorsDataAPI.sharedInstance().flush(); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 deleteAll 方法给 RN 使用. * <p> * RN 中使用示例:(删除本地数据库的所有数据!!!请谨慎使用) * <Button * title="Button" * onPress={()=> * RNSensorsAnalyticsModule.deleteAll()}> * </Button> */ @ReactMethod public void deleteAll() { try { SensorsDataAPI.sharedInstance().deleteAll(); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 trackChannelEvent 方法给 RN 使用. * * @param eventName 事件名称 * @param properties 事件的具体属性 RN 中使用示例:(记录 RN_AddToFav 事件,事件属性 * "ProductID":123456,"UserLevel":"VIP") * <Button title="Button" onPress={()=> * RNSensorsAnalyticsModule.trackChannelEvent("RN_AddToFav",{"ProductID":123456,"UserLevel":"VIP"})}> * </Button> */ @ReactMethod public void trackChannelEvent(String eventName, ReadableMap properties) { try { SensorsDataAPI.sharedInstance().trackChannelEvent(eventName, RNUtils.convertToJSONObject(properties)); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } /** * 导出 identify 方法给 RN 使用. * <p> * RN 中使用示例: * <Button title="Button" onPress={()=> * RNSensorsAnalyticsModule.identify(anonymousId)}> * </Button> */ @ReactMethod public void identify(String anonymousId) { try { SensorsDataAPI.sharedInstance().identify(anonymousId); } catch (Exception e) { e.printStackTrace(); Log.e(LOGTAG, e.toString() + ""); } } }