(八)React Native实现调用android原生java方法并实现广播的发送和接受

接触到混合应用开发提议后,首先想到了之前学的ionic,其次便是这两年火遍全球的RN,由于ionic框架用的angular.js,而且angular1和angular2写法区别很大,angular2对于初学者还是比较好接受的,但是angular1写的很乱,代码很难维护,便放弃了。决定用RN后觉得还是蛮顺手的,跟angular2很相似,又是ES6,很快便能入手,框架的选择还需要考虑的是插件的支持,尤其是:推送,广播,二维码扫描,服务,本地数据存储这些功能能否实现,由于要与硬件厂商对接,用到广播,就研究了一下如何用RN实现广播。

百度了所有的资料就是找不到如何RN实现原生广播,没有一篇类似的,于是查看一下RN项目结构,看了安卓后决定用AS加载一下看看能不能在里边编辑一下,发现MainApplication能够在应用启动时执行onCreate方法,那么我就一定能在onCreate时Toast一段话或发送一个广播的动作,那么接受发送广播基本实现了,果不其然广播真的接受到了。那么下面我要解决的问题便是RN事件如何触发android原生java代码中的方法,如果这个问题解决了,我就能通过点击事件发送一个广播。

一、RN项目添加广播,跟原生添加广播一样,两种方法,我们采用其中一种常驻广播:

<receiver android:name=".MyBroadcastReceiver">
            <intent-filter>
                <action android:name="com.example.broadcastreceiverdemo.BROADCAST"></action>
            </intent-filter>
        </receiver>

广播要处理的就是toast一段话:

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context arg0, Intent arg1) {
        // TODO Auto-generated method stub
        String string=arg1.getStringExtra("data");
        Toast.makeText(arg0, "received:"+string, Toast.LENGTH_SHORT).show();

    }

}

二、React Native 调用原生Android模块
该方法参考:http://www.cnblogs.com/lgp142332/p/6024280.html
我们首先来创建一个原生模块。一个原生模块是一个继承了ReactContextBaseJavaModule的Java类,它可以实现一些JavaScript所需的功能。我们这里的目标是可以在JavaScript里写ToastAndroid.show(‘Awesome’, ToastAndroid.SHORT);,来调起一个Toast通知。

package com.testproject.module;

import android.content.Intent;
import android.widget.Toast;

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

/**
 * Created by Administrator on 2017/4/15.
 */

public class SendBroadcastModule extends ReactContextBaseJavaModule {

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

    @Override
    public String getName() {
        return "SendBroadcast";
    }

    @ReactMethod
    public void sendBroadcast(){
        //发送广播
        Toast.makeText(getReactApplicationContext(),"开始发送...", Toast.LENGTH_SHORT).show();
        Intent intent=new Intent("com.example.broadcastreceiverdemo.BROADCAST");
        intent.putExtra("data", "hello");
        getReactApplicationContext().sendBroadcast(intent);
    }

    @Override
    public boolean canOverrideExistingModule() {
        return true;
    }
}

ReactContextBaseJavaModule要求派生类实现getName方法。这个函数用于返回一个字符串名字,这个名字在JavaScript端标记这个模块。这里我们把这个模块叫做SendBroadcast,这样就可以在JavaScript中通过React.NativeModules.SendBroadcast访问到这个模块。

注意:模块名前的RCT前缀会被自动移除。所以如果返回的字符串为”RCTSendBroadcast”,在JavaScript端依然通过React.NativeModules.SendBroadcast访问到这个模块。

要导出一个方法给JavaScript使用,Java方法需要使用注解@ReactMethod。方法的返回类型必须为void。React Native的跨语言访问是异步进行的,所以想要给JavaScript返回一个值的唯一办法是使用回调函数或者发送事件。

注册模块

在Java这边要做的最后一件事就是注册这个模块。我们需要在应用的Package类的createNativeModules方法中添加这个模块。如果模块没有被注册,它也无法在JavaScript中被访问到。

package com.testproject.module;

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.uimanager.ViewManager;
import com.testproject.module.SendBroadcastModule;

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

/**
 * Created by Administrator on 2017/4/15.
 */

public class SendBroadcastPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules=new ArrayList<>();
        modules.add(new SendBroadcastModule(reactContext));
        return modules;
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

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

注意:重写的两个方法createJSModules和createViewManagers不能return null,否则运行会报红屏AddAll的错误,一定要return Collections.emptyList();

接着我们需要在MainApplication中的getPackages方法中注册:

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
              new BarcodeScannerPackage(),
              new RealmReactPackage(),
              new SendBroadcastPackage()//注册广播模块
      );
    }

接下来便是RN的js代码了:

为了让你的功能从JavaScript端访问起来更为方便,通常我们都会把原生模块封装成一个JavaScript模块。这不是必须的,但省下了每次都从NativeModules中获取对应模块的步骤。这个JS文件也可以用于添加一些其他JavaScript端实现的功能。

var { NativeModules } = require('react-native');

export { NativeModules as default } 

然后在你需要调用的componet中引入NativeModules并调用发送广播的方法:

<Text onPress={ () => {
              ToastAndroid.show("。。。",ToastAndroid.SHORT);
              NativeModules.SendBroadcast.sendBroadcast();
            }}>发送广播</Text>
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值