1. 程式人生 > >React-native呼叫Android原生模組

React-native呼叫Android原生模組

準備工作:具體詳情參考React-Native官方文件

IDE: WebStorm 和Android Studio(webstorm不支援java高亮,所以用AS輔助下)

demo放到github上了,有需要的可以參考一下.  下載demo

1.為什麼呼叫原生的一些東西? 

   有時候應用程式需要訪問平臺API,React Native目前還沒有相應的模組。也許你想重用一些現有的Java程式碼,而不必用JavaScript重新實現它,或者編寫一些高效能,多執行緒的程式碼,例如影象處理,資料庫或任何數量的高階擴充套件。

我們設計了React Native,因此您可以編寫真實的本機程式碼並訪問平臺的全部功能。這是一個更高階的功能,我們不希望它成為通常開發過程的一部分,但它存在必不可少。如果React Native不支援您需要的本機功能,您應該能夠自己構建它。

2.建立個Toast模組做為示例:

 

我們首先建立一個本地模組。本地模組是一個Java類,通常擴充套件ReactContextBaseJavaModule該類並實現JavaScript所需的功能。我們的目標是能夠使用ToastExample.show('Awesome', ToastExample.SHORT);JavaScript 編寫在螢幕上顯示簡短toast。

2.1:建立一個名為ToastModule.java,其內容如下:

 

import android.widget.Toast;

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

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;

/**
 * Description:
 * Created by song on 2018/7/3.
 * email:
[email protected]
*/ public class ToastModule extends ReactContextBaseJavaModule { private static final String DURATION_SHORT_KEY="SHORT"; private static final String DURATION_LONG_KEY="LONG"; public ToastModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "ToastExample"; } @Nullable @Override public Map<String, Object> getConstants() { final Map<String,Object> constants=new HashMap<>(); constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT); constants.put(DURATION_LONG_KEY,Toast.LENGTH_LONG); return constants; } @ReactMethod public void show(String message,int duration){ Toast.makeText(getReactApplicationContext(),message,duration).show(); }

ReactContextBaseJavaModule要求實現一個被呼叫的方法getName。此方法的目的是NativeModule在JavaScript中返回表示該類的字串名稱。所以在這裡我們將呼叫它,ToastExample以便我們可以通過React.NativeModules.ToastExampleJavaScript 訪問它。

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

一個可選的方法呼叫getConstants返回暴露給JavaScript的常量值。它的實現不是必需的,但對於需要同步從JavaScript到Java進行通訊的關鍵預定義值非常有用。

  @Override
  public Map<String, Object> getConstants() {
    final Map<String, Object> constants = new HashMap<>();
    constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
    constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
    return constants;
  }

要向JavaScript公開方法,必須使用Java方法註釋Java方法@ReactMethod。橋接方法的返回型別總是如此void。React Native橋是非同步的,因此將結果傳遞給JavaScript的唯一方法是使用回撥或發射事件(請參見下文)。

  @ReactMethod
  public void show(String message, int duration) {
    Toast.makeText(getReactApplicationContext(), message, duration).show();
  }

 

3.註冊模組

Java中的最後一步是註冊模組; 這發生在createNativeModules你的應用程式包中。如果模組未註冊,則無法從JavaScript獲得。

建立一個名為CustomToastPackage.javainside android/app/src/main/java/com/your-app-name/folder 的新Java類,其內容如下:

 
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;

/**
 * Description:
 * Created by song on 2018/7/3.
 * email:[email protected]
 */
public class CustomToastPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules=new ArrayList<>();
        modules.add(new ToastModule(reactContext));
        return modules;
    }

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

該包需要getPackagesMainApplication.java檔案的方法中提供。該檔案存在於react-native應用程式目錄中的android資料夾下。該檔案的路徑是:android/app/src/main/java/com/your-app-name/MainApplication.java

 

@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
      new CustomToastPackage()
  );
}

4.把原生模組包裝到js模組中:

在react-native工程下,建立一個js檔案;

檔案中新增:

 

import {NativeModules} from 'react-native';
module.exports = NativeModules.ToastExample;

5.在App.js中呼叫原生模組:

 

//從android.js中匯入
import ToastExample from './android';

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        //呼叫
        <Text style={styles.welcome} onPress={()=>ToastExample.show("js中點的啊",ToastExample.SHORT)}>
         呼叫原生Toast!
        </Text>
      </View>
    );
  }

}