轉載請注明原文地址:http://www.cnblogs.com/ygj0930/p/7275897.html
ReactNative可以用來進行一些嵌入式設備的操作終端開發,比如:ATM機、自動售賣機等。其中,最重要的一步是,怎樣在ReactNative所在設備,進行一系列硬件上的操作,比如:售賣機出貨、ATM機吐錢?
一:底層操作串口包裝
對於機器的控制,ReactNative本身當然不可能做到。這些底層的操作一般都是用C/C++來實現的。而我們要做的,是把這些C/C++函數,包裝成java接口,導出為aar文件。(注意:*.jar:只包含了class文件與清單文件,不包含資源文件,如圖片等所有res中的文件。*.aar:包含所有資源,class以及res資源文件全部包含)
對於底層的操作,我們不需要關心,由廠商提供或者負責嵌入式開發的人來定義。
在ReactNative中調用aar分為兩部分:首先是通過原生Android代碼調用aar中的接口,包裝成為可供ReactNative調用的方法;然后在ReactNative代碼中調用Android代碼中的對應方法。
二:Android調用aar
1:首先,我們把aar文件放到項目的android目錄的一個文件夾中,比如:新建一個libs文件夾。
2:然后,在android目錄下的build.gradle文件中添加這個aar包路徑:
allprojects {
repositories {
mavenLocal()
flatDir{
dirs "$rootDir/libs" //在這里加上這句
} ...... } }
3:在android/app目錄下的build.gradle文件中依賴這個aar包
dependencies { ...... compile(name:'aar包名', ext:'aar')//加上這句 }
4:然后,就可以在android/app/src/main/java/com/xx目錄下新建java類,在類中 import aar包名.類名 即可使用aar包中的各種接口。
附:如何打開、查看aar文件內容,獲取其中類、接口的信息?
修改aar文件后綴為 zip ,然后解壓它,可以得到一個classes.jar文件。
使用java反編譯工具即可查看classes.jar包中的內容,獲取供我們調用的接口信息。
三:ReactNative中的原生Android開發
1:定義原生模塊,調用aar文件
在android/app/src/main/java/com/xx目錄下,新建一個類文件。
定義繼承ReactContextBaseJavaModule的Java類
import aar包名.aar中類名 import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Promise; public class 模塊類 extends ReactContextBaseJavaModule { public 模塊類(ReactApplicationContext reactContext) { super(reactContext); } // 要求重寫getName方法,返回一個字符串作為這個原生模塊名,用於在JavaScript端標記、使用這個模塊 @Override public String getName() { return "模塊名"; } // 定義供JavaScript調用的方法,需要使用注解@ReactMethod,返回值是void! @ReactMethod public void 方法名() { 通過 aar中類名.方法名() 調用aar中接口。 } 。。。。。。 }
2:注冊模塊
在模塊類文件同級目錄下,新建一個 模塊名Package.java 的類文件,重寫幾個方法:
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 模塊名Package implements ReactPackage { public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new 模塊類(reactContext));/添加模塊 return modules; } }
3:在IDE自動創建好的android/app/src/main/java/com/項目名 目錄下的MainApplication.java中添加Package實例
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new 模塊名Package() //在這里添加package實例 ); }
4:另外,也可以在android/app/src/main/java/com/項目名 目錄下自動創建的MainActivity類中定義一些隨着app生命周期而觸發的方法。比如:onCreate()等等Android原生Activity生命周期函數。
四:在ReactNative的js文件中調用原生Android模塊內方法
1:導入本地模塊庫
在js文件頭導入本地模塊庫
import { NativeModules } from 'react-native';
2:通過 NativeModules.模塊名.方法名() 進行本地模塊內函數的調用
3:獲取調用結果
提供給js調用的原生android方法的返回類型必須是void,所以想要給JavaScript返回一個值的唯一辦法是使用回調函數或者發送事件。
使用回調函數:
1)android代碼中定義的方法,傳進回調函數作為參數
// android端代碼 @ReactMethod public void 方法名(...參數,Callback callback){ ...... callback(...);//調用回調函數 }
2)js端調用方法時,除了傳遞數據參數,還傳遞回調函數獲取調用結果
// RN端調用代碼 NativeModules.模塊名.方法名(...參數,(回調函數參數)=>{回調函數體)});
使用Promise發送異步任務狀態進行回調:
向模塊方法傳遞數據一個promise對象,模塊方法中通過promise返回執行狀態以達到反饋執行結果的目的:
1)android端
// android端代碼 @ReactMethod public void 方法名(數據參數, Promise promise){ try{ if(...){ promise.resolve(map);//正常返回,並且攜帶返回結果 }else{ promise.reject(結果信息);//返回另一種結果 } }catch(IllegalViewOperationException e){ promise.reject(異常信息);//異常退出 } }
2)js端:傳遞一個匿名promise對象參數,使用 then(resolveCallBack,rejectCallBack) 來接受返回結果並執行相應回調函數
NativeModules.模塊名.方法名(數據參數,new Promise().then((resolve狀態返回值)=> {提取結果}, (reject狀態返回值)=> {提取結果});
