当使用 React Native 开发 Android 应用时,你可能需要使用没有被 React Native 封装的模块。但你可以使用 Java 编写原生模块,然后选择性的暴露公共接口到 React Native。一起来试一下!
创新互联建站坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站制作、成都做网站、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的叶城网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
我们要写一个什么东西
在写这篇文章时,React Native 包含了 ImagePickerIOS 组件,但是在 Android 平台上却没有对应的 ImagePicker 组件。我们接下来就要为 Android 构建一个简单的、和 ImagePickerIOS 大致相仿的 ImagePicker。
编写一个 React Native 的 Android 原生模块需要以下步骤:
让我们一起实践一下。
创建一个 ReactPackage
启动 AndroidStudio 并且导航到 MyApp/android/app/src/main/java/com/myapp/MainActivity.java。它应该看起来像这样:
- package com.myapp;
- import com.facebook.react.ReactActivity;
- import com.facebook.react.ReactPackage;
- import com.facebook.react.shell.MainReactPackage;
- import java.util.Arrays;
- import java.util.List;
- public class MainActivity extends ReactActivity {
- @Override
- protected String getMainComponentName() {
- return "MyApp";
- }
- @Override
- protected boolean getUseDeveloperSupport() {
- return BuildConfig.DEBUG;
- }
- @Override
- protected List
getPackages() { - return Arrays.
asList( - new MainReactPackage()
- );
- }
- }
我们先来引入一个尚未定义的包:
- import com.myapp.imagepicker.*; // import the package
- public class MainActivity extends ReactActivity {
- @Override
- protected List
getPackages() { - return Arrays.
asList( - new MainReactPackage(),
- new ImagePickerPackage() // include it in getPackages
- );
- }
- }
现在我们来编写那个包。我们将会为它创建一个叫 imagepicker 的新目录并且写入 ImagePickerPackage:
- package com.myapp.imagepicker;
- 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 java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- public class ImagePickerPackage implements ReactPackage {
- @Override
- public List
createNativeModules(ReactApplicationContext reactContext) { - List
modules = new ArrayList<>(); - modules.add(new ImagePickerModule(reactContext));
- return modules;
- }
- @Override
- public List
> createJSModules() { - return Collections.emptyList();
- }
- @Override
- public List
createViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList();
- }
- }
现在我们已经创建了一个包并且包含进 MainActivity 中了。
创建一个 ReactContextBaseJavaModule
我们将会以创建 ImagePickerModule 开始,继承 ReactContextBaseJavaModule。
- package com.myapp.imagepicker;
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
- public class ImagePickerModule extends ReactContextBaseJavaModule {
- public ImagePickerModule(ReactApplicationContext reactContext) {
- super(reactContext);
- }
- }
这是一个好的开始,为了 React Native 能从 NativeModules 找到我们的模块,我们需要覆写 getName 方法。
- @Override
- public String getName() {
- return "ImagePicker";
- }
我们现在有了一个可以被 JavaScript 代码导入的 native 模块,让它做些有趣的事情吧。
暴露方法
ImagePickerIOS 定义了 openSelectDialog 方法,可以传递配置对象、失败、成功的回调。让我们在 ImagePickerModule 中定义一个相似的方法。
- import com.facebook.react.bridge.Callback;
- import com.facebook.react.bridge.ReadableMap;
- public class ImagePickerModule extends ReactContextBaseJavaModule {
- @ReactMethod
- public void openSelectDialog(ReadableMap config, Callback successCallback, Callback cancelCallback) {
- Activity currentActivity = getCurrentActivity();
- if (currentActivity == null) {
- cancelCallback.invoke("Activity doesn't exist");
- return;
- }
- }
- }
这里我们从 React Native 中导入了 Callback 和 ReadableMap 来对应 JavaScript 中的 function 和 object。我们为这个方法加上@ReactMethod 注解,从而使它作为 ImagePicker 的一部分被 JavaScript 引用。
在方法体中我们获取当前的 activity,如果没有获取到 activity,就调用 cancel 的回调方法。我们现在有了一个可以运行的方法,但是它还不能做任何有趣的事情。让我们用它打开相册。
- public class ImagePickerModule extends ReactContextBaseJavaModule {
- private static final int PICK_IMAGE = 1;
- private Callback pickerSuccessCallback;
- private Callback pickerCancelCallback;
- @ReactMethod
- public void openSelectDialog(ReadableMap config, Callback successCallback, Callback cancelCallback) {
- Activity currentActivity = getCurrentActivity();
- if (currentActivity == null) {
- cancelCallback.invoke("Activity doesn't exist");
- return;
- }
- pickerSuccessCallback = successCallback;
- pickerCancelCallback = cancelCallback;
- try {
- final Intent galleryIntent = new Intent();
- galleryIntent.setType("image/*");
- galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
- final Intent chooserIntent = Intent.createChooser(galleryIntent, "Pick an image");
- currentActivity.startActivityForResult(chooserIntent, PICK_IMAGE);
- } catch (Exception e) {
- cancelCallback.invoke(e);
- }
- }
- }
首先,我们设置了回调,然后,我们创建了一个 Intent 并把它传递给 startActivityForResult。***,我们把所有的东西都放在 try/catch 块中来处理可能发生的异常。
当你调用 openSelectDialog 时,你应该可以看到一个相册了。然而,当你选择一张图片时,相册并不做任何事情。为了能够处理图片数据,我们需要在模块中处理 activity 的返回值。
首先,我们需要在 react context 中添加 activity event listener:
- public class ImagePickerModule extends ReactContextBaseJavaModule implements ActivityEventListener {
- public ImagePickerModule(ReactApplicationContext reactContext) {
- super(reactContext);
- reactContext.addActivityEventListener(this);
- }
- }
现在我们可以获取到相册返回的数据了。
- @Override
- public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
- if (pickerSuccessCallback != null) {
- if (resultCode == Activity.RESULT_CANCELED) {
- pickerCancelCallback.invoke("ImagePicker was cancelled");
- } else if (resultCode == Activity.RESULT_OK) {
- Uri uri = intent.getData();
- if (uri == null) {
- pickerCancelCallback.invoke("No image data found");
- } else {
- try {
- pickerSuccessCallback.invoke(uri);
- } catch (Exception e) {
- pickerCancelCallback.invoke("No image data found");
- }
- }
- }
- }
- }
在这里我们应该可以通过 success callback 获取到图片 URI。
- NativeModules.ImagePicker.openSelectDialog(
- {}, // no config yet
- (uri) => { console.log(uri) },
- (error) => { console.log(error) }
- )
为了和 ImagePickerIOS 的表现大致相仿,我们可以允许用户选择图片、视频或者直接打开相机。这些功能的写法和上面基本一致,我们将会把它留给读者作为练习。
网站栏目:ReactNative中的Android原生模块
当前网址:http://www.shufengxianlan.com/qtweb/news1/489001.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联