React Native與Android交互

  • author: ImL1s
  • email: iml1s@outlook.com
  • github: clickme

Android引用React Native Component

步驟

  1. 新建一個Android專案

  2. 在Android專案根目錄下執行以下指令,提示大部分按enter就好了

    npm init

  3. 繼續執行

    npm install react react-native --save

  4. 這時Android的目錄會是以下的樣子

     -YourProjectName |-.gradle |-.idea |-app |-build |-gradle |-node_modules |-.gitignore |-YourProjectName.iml |-build.gradle |-gradle.properties |-gradlew |-gradlew.bat |-local.properties |-npm-debug.log |-package.json |-settings.gradle |-yarn.lock
  5. package.json的內容應該為下,react和react-native版本會隨著時間推移改變

     {   "name": "YourProjectName",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "author": "",   "license": "ISC",   "dependencies": {     "react": "^16.2.0",     "react-native": "^0.52.2"   } }
  6. 接著開啟Android專案的root gradle,將剛剛npm下載的react native
    Android library放到repositories中

     allprojects {   repositories {       jcenter()       maven { url 'https://maven.google.com' }       // 將node_modules中Android相關的lib放到maven引用中       maven {           // All of React Native (JS, Android binaries) is installed from npm           url "$rootDir/node_modules/react-native/android"       }   } }
  7. 接著到app的gradle中,將react native相關的lib引入

     dependencies {     ... ...     compile "com.facebook.react:react-native:+" // From node_modules. }
  8. 配置完成,打開MainActivity,在onCraete中

      //檢查權限:讓使用者打開懸浮視窗權限以便開發中的紅屏錯誤能正確顯示     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {         if (!Settings.canDrawOverlays(this)) {             Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,                     Uri.parse("package:" + getPackageName()));             startActivityForResult(intent, 154);         }     }
  9. Android端的作業做得差不多了,現在來寫一下react native的部分吧,在Android專案根目錄新增一個目錄js,在裡面新增一個index.js,這個就是等等Activity要用來顯示的react native component

     import React from 'react'; import {   AppRegistry,   StyleSheet,   Text,   View } from 'react-native';  class HelloWorld extends React.Component {   render() {     return (                I'm React Native Text            )   } } var styles = StyleSheet.create({   container: {     flex: 1,     justifyContent: 'center',   },   text: {     fontSize: 20,     textAlign: 'center',     margin: 10,   }, });  AppRegistry.registerComponent('MyReactNativeApp', () => HelloWorld);
  10. 接下來在Activity中

     class MainActivity extends AppCompatActivity {     private ReactRootView mReactRootView;     private ReactInstanceManager mReactInstanceManager;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         mReactRootView = new ReactRootView(this);         mReactInstanceManager = ReactInstanceManager.builder()                 .setApplication(getApplication())                 // 在asset文件夾中,打包過的react native js文件名稱                 .setBundleAssetName("index.android.bundle")                 .addPackage(new MainReactPackage())                 .setUseDeveloperSupport(BuildConfig.DEBUG)                 .setInitialLifecycleState(LifecycleState.RESUMED)                 .build();         // 第二個參數"MyReactNativeApp"為React Native中的AppRegistry.registerComponent的第一個參數         mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);         setContentView(mReactRootView);     } }
  11. 將剛剛寫好的react native component打包成bundle,給ReactInstanceManager使用,bundle會放在Android的asset下

    react-native bundle --platform {{平台}} --entry-file {{入口文件,一般命名index.js}} --bundle-output {{打包好的bundle存放路徑}} --assets-dest {{react native引用的資源文件置放路徑}}react-native bundle --platform android --entry-file ./app/js/index.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/
  12. 恭喜!執行App,看到React Native的介面

Android 呼叫 React Native Component

  1. 新增一個implement ReactContextBaseJavaModule的class,這個class是最終與react native通信的類

     class ToastAndroidModule(private val reactContext: ReactApplicationContext) :     ReactContextBaseJavaModule(reactContext) {     /**      * react native call android時的模組名稱      */     override fun getName(): String {         return "ToastAndroidModule"     }      /**      * react native call(->) android      */     @ReactMethod // 此註解代表要expose給react native的方法     fun HandleMessage(message: String) {         Toast.makeText(reactContext, message, Toast.LENGTH_LONG).show()     }      /**      * android call(->) react native      */     fun sendMessage(params: String) {         reactContext                 .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)                 .emit("mEventName", params)     } }
  2. 新增一個implement ReactPackage的Package,此類底下會有許多NativeModule(就是第一步驟寫的),必須將此類放入react native API,才能進行溝通

     class AndroidWidgetPackage : ReactPackage {     private var nativeModules: MutableList? = null      override fun createNativeModules(reactContext: ReactApplicationContext): List {         // 在這裡將需要溝通原生模組放入list並回傳,這樣就等於將原生註冊到react native         nativeModules = ArrayList()         nativeModules!!.add(0, ToastAndroidModule(reactContext))         return nativeModules as ArrayList     }      override fun createViewManagers(reactContext: ReactApplicationContext): List> {         return Collections.emptyList()     }      /**      * 方便取得AndroidModule的方法      */     fun getModule(index: Int): NativeModule? {         return if (nativeModules == null) null else nativeModules!![index]     }      fun getToastModule(): ToastAndroidModule {         return getModule(0) as ToastAndroidModule     } }
  3. 撰寫React Native的Component,此Component功能很簡單,點擊按鈕呼叫第一部撰寫的ToastAndroidModule中的HandleMessage,然後就會看到Toast出現

      import React from 'react';  import {    AppRegistry,    StyleSheet,    Text,    View,    TouchableOpacity,    Dimensions,    NativeModules,    ToastAndroid,    DeviceEventEmitter  } from 'react-native';  export default class Communication3 extends React.Component {        constructor(){         super();         this.state = {             info : "我是React Native寫的內容"         }       }      componentWillMount(){       DeviceEventEmitter.addListener('mEventName',                            this.rnMethod.bind(this));     }      rnMethod(params){       this.setState({info:params});     }     render() {      return (                                    {this.state.info}                         )    }  }  var styles = StyleSheet.create({    container: {      flex: 1,      justifyContent: 'center',    } });
  4. 將剛剛寫好的react native component打包成bundle,給ReactInstanceManager使用,bundle會放在Android的asset下

     react-native bundle --platform {{平台}} --entry-file {{入口文件,一般命名index.js}} --bundle-output {{打包好的bundle存放路徑}} --assets-dest {{react native引用的資源文件置放路徑}}  react-native bundle --platform android --entry-file ./app/js/index.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/
  5. 接下來撰寫Activity的View

     <?xml version="1.0" encoding="utf-8"?>      
  6. 最後就是要將ReactPackage註冊到React Native API中了

     class ReactCommunicationActivity : AppCompatActivity() {          private var mReactRootView: ReactRootView? = null     private var mReactInstanceManager: ReactInstanceManager? = null     private var reactPackage: AndroidWidgetPackage? = null     private var mClickTime = 0      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_react_comunucatuin)                  mReactRootView = ReactRootView(this)         reactPackage = AndroidWidgetPackage()         mReactInstanceManager = ReactInstanceManager.builder()                 .setApplication(application)                 .setBundleAssetName("index.android.bundle")                 .setJSMainModulePath("index")                 .addPackage(MainReactPackage())                 .addPackage(reactPackage)   //加入AndroidModule                 .setUseDeveloperSupport(BuildConfig.DEBUG)                 .setInitialLifecycleState(LifecycleState.RESUMED)                 .build()          // 注意這裡的MyReactNativeApp必須對應“index.android.js”中的         // “AppRegistry.registerComponent()”的第一個參數         react_root_view1.startReactApplication(mReactInstanceManager, "Communication2", null)           //添加本地按鈕的點擊事件         native_btn.setOnClickListener {             reactPackage!!.getToastModule().sendMessage("這是一條Android發送給React的消息${mClickTime++}")         }     } }
  7. 點擊按鈕,成功調用原生的Toast方法

React Native Component 呼叫 Activity

  1. 在上一部的基礎上,在View加上

     <?xml version="1.0" encoding="utf-8"?>  
  2. 新增一個Component,此Componenet目的為顯示Android端點擊後,反應點擊

     import React from 'react'; import {    AppRegistry,    StyleSheet,    Text,    View,    TouchableOpacity,    Dimensions,    NativeModules,    ToastAndroid } from 'react-native';  export default class Communication extends React.Component {    onPress = ()=> {       // 這樣調用原生端方法,show出吐司       NativeModules.ToastAndroidModule       .HandleMessage("React Native 呼叫Native来吐司!!");   }     render() {      return (                                             這是一個React Native按鈕,點擊調用原生Toast方法                                      )    }  }  var styles = StyleSheet.create({    container: {      flex: 1,      justifyContent: 'center',    },    text:{        fontSize: 20    } });
  3. 打包js

     # react-native bundle --platform {{平台}} --entry-file {{入口文件,一般命名index.js}} --bundle-output {{打包好的bundle存放路徑}} --assets-dest {{react native引用的資源文件置放路徑}}  react-native bundle --platform android --entry-file ./app/js/index.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/
  4. 在Activity中,啟動該React Native Component的生命週期

     class ReactCommunicationActivity : AppCompatActivity() {         private var mReactRootView: ReactRootView? = null     private var mReactInstanceManager: ReactInstanceManager? = null     private var reactPackage: AndroidWidgetPackage? = null     private var mClickTime = 0      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_react_comunucatuin)          mReactRootView = ReactRootView(this)         reactPackage = AndroidWidgetPackage()         mReactInstanceManager = ReactInstanceManager.builder()                 .setApplication(application)                 .setBundleAssetName("index.android.bundle")                 .setJSMainModulePath("index")                 .addPackage(MainReactPackage())                 .addPackage(reactPackage)   //加入AndroidModule                 .setUseDeveloperSupport(BuildConfig.DEBUG)                 .setInitialLifecycleState(LifecycleState.RESUMED)                 .build()          // 注意這裡的MyReactNativeApp必須對應“index.android.js”中的         // “AppRegistry.registerComponent()”的第一個參數 //        mReactRootView!!.startReactApplication(mReactInstanceManager, "Communication3", null)         react_root_view1.startReactApplication(mReactInstanceManager, "Communication2", null)         react_root_view2.startReactApplication(mReactInstanceManager, "Communication3", null)           //添加本地按鈕的點擊事件         native_btn.setOnClickListener {             reactPackage!!.getToastModule().sendMessage("這是一條Android發送給React的消息${mClickTime++}")         }     } }
  5. 測試,完工!

將現有的Android專案整React Native

// TODO

更多相关文章

  1. Android拷贝图片到指定文件路径
  2. Android P(api28) 不支持 http 协议解决方法
  3. android 安卓创建文件夹
  4. Android 解析excel文件
  5. 三步搞定:Vue.js调用Android原生方法
  6. AndroidManifest.xml 系统找不到指定的文件
  7. android 防止键盘弹出的简单方法
  8. Smail反汇编文件语句说明
  9. Android 复制单个文件到指定目录,Android copy file

随机推荐

  1. android模拟器大幅优化_android开发者的
  2. android 扫描SDCard.
  3. android图片转换代码
  4. android开发2:eclipse 开发 Android(安卓)
  5. ListView设置没有头部和底部分割线
  6. Android7.0中文文档(API)-- AutoCompleteTe
  7. flutter技术栈!字节跳动Android研发岗这些
  8. android:configChanges screen
  9. Android(安卓)Bitmap移动游戏背景
  10. android 菜单实例