G
Q
Q
and
M
E

React Native和android原生端通信

React Native和android原生端通信

更为详细的请参考React Native官方网站,此文章只介绍从React Native 到Android端通信的基本示例。
 

在新建好的React Native项目中都会存在一个名为android的文件夹,使用 Android Studio来打开这文件夹

 

1. 在android/app/src/main/java/com/your-app-name/文件夹中新建Kontlin文件:CalendarModule.kt

写入如下内容:

package com.your-apps-package-name; // replace your-apps-package-name with your app’s package name
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod

class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {...}

CalendarModule类继承了ReactContextBaseJavaModule,对于安卓系统,要使得这个类能够被React Native端调用,继承这个类是必不可少的。

从技术上讲,Java/Kotlin 类只需要扩展BaseJavaModule类或实现NativeModule接口,才能被 React Native 视为原生模块,然而官方更推荐使用上面所示的ReactContextBaseJavaModule。ReactContextBaseJavaModule提供了ReactApplicationContext(RAC)的访问权限,这对于需要挂钩到活动生命周期方法的原生模块非常有用。使用ReactContextBaseJavaModule也将使您更容易在将来实现原生模块的类型安全性。为了实现原生模块类型安全性(将在未来版本中推出),React Native 会查看每个原生模块的 JavaScript 规范,并生成一个抽象基类,该基类扩展自ReactContextBaseJavaModule

 

2.确定模块名称

所有原生Android平台上的原生模块都需要实现getName()方法,该方法返回一个字符串,代表了原生模块的名称,我们在JavaScript中调用时,就是通过getName()中返回的字符串来确定调用的是哪个类

// add to CalendarModule.kt
override fun getName() = "CalendarModule"

对应的在JavaScript中调用的方法如下:

const {CalendarModule} = ReactNative.NativeModules;

3. 添加可调用方法

接下来,我们在原生模块中添加一个方法,该方法可以创建日历时间,并可以在JavaScript中调用,所有打算从JavaScript中调用的原生模块方法都必须使用@ReactMethod进行注解

import android.util.Log

@ReactMethod
fun createCalendarEvent(name: String, location: String) {
    Log.d("CalendarModule", "Create event called with name: $name and location: $location")
}

该方法也可以标记为同步执行,@ReactMethod(isBlockingSynchronousMethod = true)但是官方并不建议,因为可能会带来严重的性能损耗,而且无法使用调试模式

 

4. 在Android上注册模块

一旦编写完成原生模块(即上文的CalendarModule.kt),就需要将其注册到React Native中。
为此,你需要将你的原生模块添加到一个ReactPackage中,并将该ReactPackage注册到React Native。在初始化中,React Native会遍历所有包,并对于每个ReactPackage注册其中的每个原生模块

React Native会调用ReactPackagecreateNativeModules()方法,以获取要注册的原生模块列表,对于Android而言,如果一个模块未在createNativeModules中实例化并返回,那么在JavaScript中就不可用

要将你的原生模块添加到 ReactPackage 中,首先在 android/app/src/main/java/com/your-app-name/ 文件夹中创建一个新的 Kotlin 类MyAppPackage.kt,并实现 ReactPackage 接口

package com.your-app-name // replace your-app-name with your app’s name

import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager

class MyAppPackage : ReactPackage {

    override fun createViewManagers(
        reactContext: ReactApplicationContext
    ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()

    override fun createNativeModules(
        reactContext: ReactApplicationContext
    ): MutableList<NativeModule> = listOf(CalendarModule(reactContext)).toMutableList()
}

这个文件导入和创建的原生模块CalendarModule,然后在createNativeModules函数中实例化了CalendarModule并将其作为NativeModules列表返回以便注册,如果将来添加更多原生模块,也可以在这里实例化他们并添加到返回的列表中

要注册CalendarModule包,你必须将MyAppPackage添加到 ReactNativeHost 的getPackages()方法返回的包列表中。打开ainApplication.kt文件,位于如下路径:android/app/src/main/java/com/your-app-name/
找到 ReactNativeHost 的getPackages()方法,并将你的包添加到getPackages()返回的包列表中。

override fun getPackages(): List<ReactPackage> =
    PackageList(this).packages.apply {
        // Packages that cannot be autolinked yet can be added manually here, for example:
        // packages.add(new MyReactNativePackage());
        add(MyAppPackage())
    }

 

5. 测试运行

在React Native中测试一下:

import React from 'react';
import {NativeModules, Button} from 'react-native';

const {CalendarModule} = NativeModules;
const NewModuleButton = () => {
  const onPress = () => {
   CalendarModule.createCalendarEvent('testName', 'testLocation');
    console.log('We will invoke the native module here!');
  };

  return (
    <Button
      title="Click to invoke your native module!"
      color="#841584"
      onPress={onPress}
    />
  );
};

export default NewModuleButton;

重新构建一下应用程序,此时应该可以正确调用android中的方法:

npm run android

注意如果你打印NativeModules,你会发现始终是{},这是由于异步导致的,React Native 在GitHub的Open Issues中承认此Bug,但是修复时间尚不确定

附加:

在上面代码的基础上,添加React Native按钮点击调用Android中的代码来显示一个简单的通知栏消息:

新建文件:NotificationHelper.kt

package com.haha_react_native

// 在你的项目中创建一个新的 Kotlin 文件,例如 NotificationHelper.kt

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.BitmapFactory
import android.os.Build
import androidx.core.app.NotificationCompat

class NotificationHelper(private val context: Context) {

    private val channelId = "my_channel_id" // 设置通知通道 ID

    fun showNotification(notificationId: Int, title: String, content: String) {
        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // 创建通知通道(仅适用于 Android 8 及更高版本)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(channelId, "My Channel", NotificationManager.IMPORTANCE_DEFAULT)
            notificationManager.createNotificationChannel(channel)
        }

        // 创建通知
        val builder = NotificationCompat.Builder(context, channelId)
                .setSmallIcon(R.drawable.ic_notification) // 设置通知栏小图标
                .setContentTitle(title) // 设置通知标题
                .setContentText(content) // 设置通知内容
                .setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher)) // 设置通知栏大图标
                .setAutoCancel(true) // 点击通知后自动取消

        // 发送通知
        notificationManager.notify(notificationId, builder.build())
    }
}

在上边的createCalendarEvent方法中新增调用:

val notificationHelper = NotificationHelper(this.reactApplicationContext)
val notificationId = 1;
val title = "新消息"
val content = "你有一条新消息"
notificationHelper.showNotification(notificationId,title,content);

重新运行React Native程序,单击按钮时会在通知栏显示一条通知。

 

React Native中很多开发包已经很久没有更新,在新版本的React Native中会有各式各样的奇怪问题,如果开始一个新的项目,并不推荐使用。

posted @ 2024-05-14 10:49  sy0313  阅读(48)  评论(0编辑  收藏  举报