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;
}
}
我是菜鸟东,要是有不足之处,希望各路大神给予指示,好让我飞的更远!!!