umeng / React_Native_Compent

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

React-Native 0.63.2 最新集成教程分享

liran opened this issue · comments

commented

官方原生版本的SDK是持续维护更新的,它里面的功能越来越多,该仓库教程中的一些文件都已经被包含,这使得ReactNative版本的集成变得更简单,只是文档没更新,很多同学都不知道。
写该教程时我的环境:

System:
    OS: macOS 10.15.7
    CPU: (4) x64 Intel(R) Core(TM) i3-6100 CPU @ 3.70GHz
    Memory: 1.31 GB / 8.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 15.1.0 - /var/folders/c1/hrxt7sw95ssgrn51ttsmbcfw0000gn/T/yarn--1611585176685-0.9769877579376194/node
    Yarn: 1.22.10 - /var/folders/c1/hrxt7sw95ssgrn51ttsmbcfw0000gn/T/yarn--1611585176685-0.9769877579376194/yarn
    npm: 7.0.8 - /usr/local/bin/npm
    Watchman: Not Found
  Managers:
    CocoaPods: 1.10.0 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 14.1, DriverKit 19.0, macOS 10.15, tvOS 14.0, watchOS 7.0
    Android SDK:
      API Levels: 29, 30
      Build Tools: 28.0.3, 29.0.2, 30.0.2
      System Images: android-29 | Google APIs Intel x86 Atom_64, android-30 | Google APIs Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 4.1 AI-201.8743.12.41.6858069
    Xcode: 12.1/12A7403 - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_275 - /usr/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.13.1 => 16.13.1 
    react-native: 0.63.2 => 0.63.2

iOS统计集成

  1. 按下面代码提示的地方编辑ios/Podfile,完成后在ios路径下运行:pod update。写该文档时使用的UMCCommon版本是7.2.2,可在ios/Podfile.lock中查看到,使用其它版本可能会与该教程有些差异。
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '10.0'

target 'YourAppName' do
  config = use_native_modules!

  use_react_native!(:path => config["reactNativePath"])


  target 'YourAppNameTests' do
    inherit! :complete
    # Pods for testing
  end

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  use_flipper!
  post_install do |installer|
    flipper_post_install(installer)
  end
  
  pod 'UMCCommon' // 增加这行
  
end

target 'YourAppName-tvOS' do
  # Pods for YourAppName-tvOS

  target 'YourAppName-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end
  1. 编辑 ios/[YourAppName]/AppDelegate.m
#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

// 友盟统计sdk
#import <UMCommon/UMConfigure.h>  // 增加这行

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"YourAppName"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  // 友盟sdk初始化
  [UMConfigure initWithAppkey:@"YourAppKey" channel:@"App Store"]; // 增加这行
  
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end

完成上面两步就可以实现基本的统计。如果还需要发送自定义事件,需要继续下面步骤:

  • 下载桥接文件 UMAnalyticsModule.hUMAnalyticsModule.m 放到ios/[YourAppName]下,确保在XCode中能显示,如果没显示还需要手动Add一下,否则XCode不会自动编译它们,这两个文件在该仓库可以找到。
  • 按下面指出的地方编辑 UMAnalyticsModule.m
//
//  analytics.m
//  analytics
//
//
//  Copyright (c) 2016年 tendcloud. All rights reserved.
//

#import <UMAnalytics/MobClick.h> // 删除这行
#import <UMCommon/MobClick.h> // 增加这行

#import "UMAnalyticsModule.h"
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>

@implementation UMAnalyticsModule

RCT_EXPORT_MODULE();
......
  • 创建一个js文件,方便引用UMAnalyticsModule.m中实现的方法
import { NativeModules } from 'react-native';

export default NativeModules.UMAnalyticsModule;

至此,iOS端的统计集成就完成了。
需要集成其他功能的可以照葫芦画瓢。

Android统计集成
安卓只需要按照 https://mobile.umeng.com/platform/config/apps/create 跑完流程就算已经集成了基本的统计功能。
如果需要发送自定义事件还需要处理桥接,具体流程如下:

  1. 下载桥接文件DplusReactPackage.javaAnalyticsModule.java放到android/app/src/main/java/com下;

  2. 按如下编辑 AnalyticsModule.java:

package com.umeng.soexample.invokenative; // 删掉这行
package com.umeng; // 增加这行

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
import org.json.JSONException;
import java.util.Iterator;

.
.
.

/********************************U-App统计*********************************/
    @ReactMethod
    public void onPageStart(String pageName) { // 删掉这行
    public void onPageBegin(String pageName) { // 增加这行   说明一下:需要和iOS的桥接文件里的函数名统一,这应该是官方的失误造成的
        //android.util.Log.e("xxxxxx","onPageStart="+mPageName);

        MobclickAgent.onPageStart(pageName);
    }

    @ReactMethod
    public void onPageEnd(String pageName) {
        //android.util.Log.e("xxxxxx","onPageEnd="+mPageName);

        MobclickAgent.onPageEnd(pageName);

    }
  1. 编辑DplusReactPackage.java:
package com.umeng.soexample.invokenative; // 删掉这行
package com.umeng; // 增加这行

import java.util.ArrayList;
import java.util.Arrays;  // 删掉这行
import java.util.Collections;
import java.util.List;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;  // 删掉这行
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.shell.MainReactPackage;  // 删掉这行
import com.facebook.react.uimanager.ViewManager;

/**
 * Created by wangfei on 17/8/28.
 */

public class DplusReactPackage implements ReactPackage {

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    /**
     * 如需要添加本地方法,只需在这里add
     *
     * @param reactContext
     * @return
     */
    @Override
    public List<NativeModule> createNativeModules(
        ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new ShareModule(reactContext));  // 删掉这行
        modules.add(new PushModule(reactContext));  // 删掉这行
        modules.add(new AnalyticsModule(reactContext));
        return modules;
    }
}
  1. 编辑 MainApplication.java,主要是初始化桥接文件:
mport com.brentvatne.react.ReactVideoPackage;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;

// umeng
import com.umeng.DplusReactPackage;  // 增加这行
import com.umeng.commonsdk.UMConfigure;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {
    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            @SuppressWarnings("UnnecessaryLocalVariable")
            List<ReactPackage> packages = new PackageList(this).getPackages();
            // Packages that cannot be autolinked yet can be added manually here, for example:
            // packages.add(new MyReactNativePackage());
            packages.add(new DplusReactPackage()); // 增加这行
            return packages;
        }

        @Override
        protected String getJSMainModuleName() {
            return "index";
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }
    .
    .
    .

至此,安卓的统计集成结束。通过集成iOS时创建的js文件就可以调用到桥接里面的函数。注意我们上面有把Android桥接文件里的onPageStart变成onPageBegin,这是因为在Android和iOS分别的桥接文件里函数名不统一,需要我们手动修复,这样方便在js调用时有统一的函数名onPageBegin

最后说明:
React Native iOS和Android的统计集成和原生的没太大差别,但React Native需要做额外的事情:

  1. 需要处理桥接,想要在js里调用友盟的原生函数就需要通过桥接来实现;
  2. page的跳转捕获,原生应用 友盟的SDK会自动采集原生的screen,但React Native只有一个原生的screen来渲染js所有 page,所以路由跳转时需要通过调用桥接文件里的函数来通知友盟页面发生了跳转。
    具体实现可以根据自己使用的navigation来做。
    例如:react-navigation:https://reactnavigation.org/docs/screen-tracking

Android的啥时候更新啊

commented

@wuxuejie
有需要就今天晚上找时间写一下

大佬有第三方登录分享的集成教程么

安卓没问题,IOS报错 UMCommon/MobClick.h' file not found

- #import <UMAnalytics/MobClick.h> // 删除这行
+ #import <UMCommon/MobClick.h> // 增加这行
commented

@XJLZ sorry,没做过类似的功能,没法提供帮助。

commented

@BAE86AEC1946B6AB60CCD7452DC811F0
这应该是版本更新导致的,我写文档时是UMCCommon (7.2.2)。
目前最新版本是7.2.5,所以会有些区别,一些小细节变化,可以参考下面文档进行修改。
https://developer.umeng.com/docs/119267/detail/119534
image

页面统计JS层一样的代码, JS调用没报错

但是 页面访问路径统计 友盟后台,IOS正常, 安卓只显示一个 MineActivity..

请问这个问题大家有遇到过吗? 安卓端反编译了友盟SDK,方法名也没有调用错

页面统计我是在 react-navigation 导航跳转的事件里面处理的