React Native自定义插件,调用android原生代码

Hi,宝宝们,我又来了,16有你,17前行,18怎么办?18让我们一起学习RN吧,hybrid现在是一个前沿,虽然官网说Learn once, write anywhere~~~ 仅需学习一次,编写任何平台。但是你不能指望它干任何事啊,android原生的很多功能还是无法直接使用的,这个时候怎么办呢?不要怕哈宝宝,React Native给我提供的接口,我们可以自己定义插件,调用原生功能,下面跟着我一起学习怎么写吧,宝宝们~~~我要开始巴拉巴拉巴拉啦!!!

     首先说一下我的需求,自定义RN插件,判断网络状态,看是否链接VPN给予回调,在JS中获取链接状态。go~go~go~~~

一.新建NetworkModule类,继承ReactContextBaseJavaModule父类

      当你新建RN项目的时候,会默认有两个android和ios两个文件夹,我们用Android Studio打开android文件夹新建一个类,我定义为NetworkModule继承ReactContextBaseJavaModule后报红,Alt+Enter按提示重写getName和构造方法,getName的return值就是JS端的调用名,如下:
public class NetworkModule extends ReactContextBaseJavaModule {
    //构造方法
    public NetworkModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    //重写getName方法,暴露给JS端调用名NetworkModule
    @Override
    public String getName() {
        return "NetworkModule";
    }
}

二.暴露方法,加入@ReactMethod注解,让js端可以调用,注意方法返回值只能是void

      我们需要在NetworkModule里面暴露一个方法,让JS端可以调用,我以checkNet方法为例,记得加入注解@ReactMethod,返回值为void,好奇宝宝不要乱改哈。
successCallback.invoke();通过这个方法可以给JS一个回调,传入值可以是Object...args.
//RN调用的方法,给暴露给JS的方法添加 @ReactMethod 注解,且方法的返回值只能是void
    /*
    * checkType : 判断类型
    * successCallback : 成功的回调
    * errCallback : 失败的回调
    * */
    @ReactMethod
    public void checkNet(String checkType, Callback successCallback, Callback errCallback){

    }
你可以在这个方法里面写原生逻辑功能,实在不想写,那就打一个Toast吧。

三.实现ReactPackage接口
     再用Android Studio新建一个类,我定义为IntentNetPackage实现ReactPackage接口后报红,Alt+Enter按提示重写createViewManagers和createNativeModules方法,在createNativeModules中添加NetworkModule(就是第一步新建的类)并返回,如下:
public class IntentNetPackage implements ReactPackage {

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

    @Override
    public List<NativeModule> createNativeModules(
                                   ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new NetworkModule(reactContext));
        return modules;
    }

}

四.在MainApplication中注册IntentNetPackage

@Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new SQLitePluginPackage(),
          new IntentNetPackage()//注册自定义插件,检查网络类型
      );
    }

五.RN中用JS调用NetworkModule中的checkNet方法

NativeModules.NetworkModule.checkNet("NETWORK_VPN",
  (msg) => {
    //成功方法的回调
    alert("疯狂的东" + msg);
  },
  () => {
    //失败方法的回调
  }
);
这里我打了一个alert来看是不是成功了,很幸运运行结果如下:



我这里是返回了一个网络状态和判断了是否链接了VPN.

写到这里,一个RN插件就可以OK啦,可是作为细心并伟大的我(吹牛逼不犯法),决定把我的源码奉献出来

1.NetworkModule里面的源码
package com.myfirstrn;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.Enumeration;

/**
 * Created by CrazyDong on 2018/1/16.
 */
public class NetworkModule extends ReactContextBaseJavaModule {
    private static final String netVPNEnum = "NETWORK_VPN";//VPN链接的枚举

    //重写getName方法,暴露给JS端调用名NetworkModule
    @Override
    public String getName() {
        return "NetworkModule";
    }


    public NetworkModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    //RN调用的方法,给暴露给JS的方法添加 @ReactMethod 注解,且方法的返回值只能是void
    @ReactMethod
    public void checkNet(String checkType, Callback successCallback, Callback errCallback){
        if(netVPNEnum.equals(checkType)){
            //检查网络是否链接
            ConnectivityManager connectivityManager = (ConnectivityManager) getReactApplicationContext()
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
            //判断是否有网络
            if(networkInfo != null){
                //检查VPN是否链接
                try {
                    Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
                    if(niList != null){
                        //扫描所有网络接口,查看是否有使用VPN的(接口名为tun0或ppp0为VPN已经链接)
                        for(NetworkInterface intf : Collections.list(niList)){
                            if("tun0".equals(intf.getName()) || "ppp0".equals(intf.getName())){
                                //返回网络状态networkInfo.getTypeName()和VPN链接的标识
                                successCallback.invoke("VPN_OK" + networkInfo.getTypeName());
                            }
                        }
                    }
                } catch (SocketException e) {
                    //失败的回调
                    errCallback.invoke(e);
                }
            }else{
                errCallback.invoke("null_network");
            }

        }

    }

}
2.IntentNetPackage里面的源码
package com.myfirstrn;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by CrazyDong on 2018/1/16.
 */
public class IntentNetPackage implements ReactPackage {

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

    @Override
    public List<NativeModule> createNativeModules(
                                   ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new NetworkModule(reactContext));
        return modules;
    }

}


我是菜鸟东,要是有不足之处,希望各路大神给予指示,好让我飞的更远!!!










猜你喜欢

转载自blog.csdn.net/LjingDong/article/details/79076340