React Native從零單排6 原生交互

RN版本:0.64
系統(tǒng):Win10

前言

React Native應(yīng)用大部分操作都可以在JS端完成,但是也有一些復(fù)雜的功能是需要原生端來完成的,比如Apple 或 Android 支付、打開第三方App或者為圖像處理等內(nèi)容編寫一些高性能多線程代碼。
接下來我們以加入QQ群為例,分別從Android和Ios兩個方面看一下如何實現(xiàn)原生交互。

1.Android

創(chuàng)建一個繼承了ReactContextBaseJavaModule的 Java 類并命名為QQNativeApiModule.java,放置到android/app/src/main/java/com/your-app-name/目錄下:QQNativeApiModule.java,在它的內(nèi)部實現(xiàn)加入qq群的方法。

public class QQNativeApiModule extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;

    public QQNativeApiModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "QQNativeApi";
    }
    // 要導(dǎo)出一個方法給 JavaScript 使用,Java 方法需要使用注解@ReactMethod。方法的返回類型必須為void
    @ReactMethod
    public void joinQQGroup(String key, Promise promise) {
        boolean success;
        String msg = null;
        Intent intent = new Intent();
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + key));
        try {
            reactContext.startActivity(intent);
            success = true;
        } catch (Exception e) {
            // 未安裝手Q或安裝的版本不支持
            success = false;
        }

        WritableMap writableMap = new WritableNativeMap();
        writableMap.putBoolean("success", success);
        writableMap.putString("msg", msg);
        //返回給RN處
        promise.resolve(writableMap);
    }
}

創(chuàng)建一個新的 Java 類并命名為QQNativeApiPackage.java,放置到android/app/src/main/java/com/your-app-name/目錄下,其具體代碼如下:

public class QQNativeApiPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Arrays.<NativeModule>asList(new QQNativeApiModule(reactContext));
    }

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

這個 package 需要在MainApplication.java文件的getPackages方法中提供。這個文件位于你的 react-native 應(yīng)用文件夾的 android 目錄中。具體路徑是: android/app/src/main/java/com/your-app-name/MainApplication.java

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 QQNativeApiPackage());
          return packages;
        }

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

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

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

JS端調(diào)用:

// JoinQQGroup.js
import { NativeModules } from 'react-native';

const QQNativeApi = NativeModules.QQNativeApi;

const joinQQGroup = (key) =>{
    QQNativeApi.joinQQGroup(key).then(rst => {
        if (!rst.success) {
              global.Toast('沒有找到QQ。');
        }
    }
}

2.Ios

自定義接口類QQNativeApi.h,需要實現(xiàn)RCTBridgeModule協(xié)議,導(dǎo)入RCT_EXPORT_MODULE宏定義.

#import <Foundation/Foundation.h>
#import <React/RCTBridge.h>

@interface QQNativeApi:NSObject<RCTBridgeModule>

@end

新建QQNativeApi.m,實現(xiàn)加入QQ群方法

#import "QQNativeApi.h"

@implementation QQNativeApi

//  必須實現(xiàn)
RCT_EXPORT_MODULE();

RCT_REMAP_METHOD(joinQQGroup,
                 uin:(NSString *)uin
                 key:(NSString *)key
                 joinQQGroupResolve:(RCTPromiseResolveBlock)joinQQGroupResolve
                 joinQQGroupReject:(RCTPromiseRejectBlock)joinQQGroupReject) {
  NSString *urlStr = [NSString stringWithFormat:@"mqqapi://card/show_pslcard?src_type=internal&version=1&uin=%@&key=%@&card_type=group&source=external", uin, key];
  NSURL *url = [NSURL URLWithString:urlStr];
  dispatch_async(dispatch_get_main_queue(), ^{
    if([[UIApplication sharedApplication] canOpenURL:url]){
      [[UIApplication sharedApplication] openURL:url];
    }
  });
  joinQQGroupResolve([self Success:@YES]);
}

- (void)dealloc {
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

JS調(diào)用

// JoinQQGroup.js
import { NativeModules } from 'react-native';

const QQNativeApi = NativeModules.QQNativeApi;
const joinQQGroup = (key) =>{
    QQNativeApi.joinQQGroup(this.state.groupUin,this.state.groupKey,)
        .then(rst => {
            if (!rst.success) {
              global.Toast('沒有找到QQ。');
            }
    });
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容