新聞中心
當(dāng)使用 React Native 開發(fā) Android 應(yīng)用時(shí),你可能需要使用沒有被 React Native 封裝的模塊。但你可以使用 Java 編寫原生模塊,然后選擇性的暴露公共接口到 React Native。一起來試一下!

創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站制作、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的葉城網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
我們要寫一個(gè)什么東西
在寫這篇文章時(shí),React Native 包含了 ImagePickerIOS 組件,但是在 Android 平臺(tái)上卻沒有對應(yīng)的 ImagePicker 組件。我們接下來就要為 Android 構(gòu)建一個(gè)簡單的、和 ImagePickerIOS 大致相仿的 ImagePicker。
編寫一個(gè) React Native 的 Android 原生模塊需要以下步驟:
- 創(chuàng)建一個(gè) ReactPackage,把很多模塊(Native 和 JavaScript)包含在一起,然后在 MainActivity 中的 getPackages 方法引用。
- 創(chuàng)建一個(gè) Java 類,繼承 ReactContextBaseJavaModule 并實(shí)現(xiàn)需要的接口,然后注冊到我們的 ReactPackage。
- 覆寫上述類的 getName 方法,這個(gè)方法會(huì)作為 Javascript 的調(diào)用方法名。
- 使用 @ReactMethod 注解把需要的公共方法暴露給 Javascript。
- ***,在 Javascript 中通過 NativeModules 導(dǎo)入你的模塊。
讓我們一起實(shí)踐一下。
創(chuàng)建一個(gè) ReactPackage
啟動(dòng) AndroidStudio 并且導(dǎo)航到 MyApp/android/app/src/main/java/com/myapp/MainActivity.java。它應(yīng)該看起來像這樣:
- 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()
- );
- }
- }
我們先來引入一個(gè)尚未定義的包:
- 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
- );
- }
- }
現(xiàn)在我們來編寫那個(gè)包。我們將會(huì)為它創(chuàng)建一個(gè)叫 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();
- }
- }
現(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè)包并且包含進(jìn) MainActivity 中了。
創(chuàng)建一個(gè) ReactContextBaseJavaModule
我們將會(huì)以創(chuàng)建 ImagePickerModule 開始,繼承 ReactContextBaseJavaModule。
- package com.myapp.imagepicker;
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
- public class ImagePickerModule extends ReactContextBaseJavaModule {
- public ImagePickerModule(ReactApplicationContext reactContext) {
- super(reactContext);
- }
- }
這是一個(gè)好的開始,為了 React Native 能從 NativeModules 找到我們的模塊,我們需要覆寫 getName 方法。
- @Override
- public String getName() {
- return "ImagePicker";
- }
我們現(xiàn)在有了一個(gè)可以被 JavaScript 代碼導(dǎo)入的 native 模塊,讓它做些有趣的事情吧。
暴露方法
ImagePickerIOS 定義了 openSelectDialog 方法,可以傳遞配置對象、失敗、成功的回調(diào)。讓我們在 ImagePickerModule 中定義一個(gè)相似的方法。
- 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 中導(dǎo)入了 Callback 和 ReadableMap 來對應(yīng) JavaScript 中的 function 和 object。我們?yōu)檫@個(gè)方法加上@ReactMethod 注解,從而使它作為 ImagePicker 的一部分被 JavaScript 引用。
在方法體中我們獲取當(dāng)前的 activity,如果沒有獲取到 activity,就調(diào)用 cancel 的回調(diào)方法。我們現(xiàn)在有了一個(gè)可以運(yùn)行的方法,但是它還不能做任何有趣的事情。讓我們用它打開相冊。
- 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);
- }
- }
- }
首先,我們設(shè)置了回調(diào),然后,我們創(chuàng)建了一個(gè) Intent 并把它傳遞給 startActivityForResult。***,我們把所有的東西都放在 try/catch 塊中來處理可能發(fā)生的異常。
當(dāng)你調(diào)用 openSelectDialog 時(shí),你應(yīng)該可以看到一個(gè)相冊了。然而,當(dāng)你選擇一張圖片時(shí),相冊并不做任何事情。為了能夠處理圖片數(shù)據(jù),我們需要在模塊中處理 activity 的返回值。
首先,我們需要在 react context 中添加 activity event listener:
- public class ImagePickerModule extends ReactContextBaseJavaModule implements ActivityEventListener {
- public ImagePickerModule(ReactApplicationContext reactContext) {
- super(reactContext);
- reactContext.addActivityEventListener(this);
- }
- }
現(xiàn)在我們可以獲取到相冊返回的數(shù)據(jù)了。
- @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");
- }
- }
- }
- }
- }
在這里我們應(yīng)該可以通過 success callback 獲取到圖片 URI。
- NativeModules.ImagePicker.openSelectDialog(
- {}, // no config yet
- (uri) => { console.log(uri) },
- (error) => { console.log(error) }
- )
為了和 ImagePickerIOS 的表現(xiàn)大致相仿,我們可以允許用戶選擇圖片、視頻或者直接打開相機(jī)。這些功能的寫法和上面基本一致,我們將會(huì)把它留給讀者作為練習(xí)。
網(wǎng)站欄目:ReactNative中的Android原生模塊
文章轉(zhuǎn)載:http://m.fisionsoft.com.cn/article/coshohs.html


咨詢
建站咨詢
