react native 和原生平臺 android的互動

tankII發表於2021-09-09

慣例這是寫在前面的話,週五的時候和同事朋友聊起來寫部落格這件事,自己在朋友圈吹下的牛逼,無論如何都是要完成的啊,等把部落格寫完了,獎勵自己玩一會兒魔獸,我的小號獸人戰士已經10級了,聯盟,你們顫抖吧。


圖片描述

圖片發自簡書App

我們這裡從react-natvie 呼叫原生android的方法,獲取原生android的資料部分開始講,其中還包括androidreact-native的回撥。

這就是說的互相互動的事,那麼我們開始吧!

react-natvie 呼叫原生android的方法,獲取原生android的資料

react-native和原生平臺API之間,有一個JavaScript的橋接層,react-native就是透過橋接層來和原生的平臺進行互動的,其中,這涉及到了兩個模組NativeModuleNativeEventEmitter

1.NativeModule:用於JavaScript程式碼呼叫原生的程式碼。
2.NativeEventEmitter:用於原生程式碼傳送訊息到JavaScript程式碼。

我們可以看一下Animated下的原始碼實現:

目錄在這裡

node_modulesreact-nativeLibrariesAnimatedsrcNativeAnimatedHelper.js

它的第一行就是

const NativeAnimatedModule = require('NativeModules').NativeAnimatedModule;const NativeEventEmitter = require('NativeEventEmitter');

引用了這兩個模組,我們再看一下下面是怎麼呼叫的呢?

 createAnimatedNode: function(tag: ?number, config: Object): void {
    assertNativeAnimatedModule();
    NativeAnimatedModule.createAnimatedNode(tag, config);
  },

建立一個Animated動畫,是透過呼叫NativeAnimatedModule.createAnimatedNode(tag, config);來實現的。

而在android這裡的程式碼,如果想要能夠讓react-native呼叫到,需要實現三個步驟:

1.寫出你想要呼叫的模組(繼承ReactContextBaseJavaModule)
2.把這個模組匯出(實現匯出介面ReactPackage)
3.把這個模組註冊釋出(在MainApplication中註冊)

那麼我們開始吧:

1.寫出你想要呼叫的模組(繼承ReactContextBaseJavaModule)

//.../**
 * Created by feiyu on 2018/5/12.
 */public class CommunicationModule extends ReactContextBaseJavaModule {    private final ReactApplicationContext mReactContext;    public CommunicationModule(ReactApplicationContext reactContext) {        super(reactContext);        this.mReactContext = reactContext;
    }    @Override
    public String getName() {        //你想要呼叫的那個模組的名稱,實際上就是當前的這個物件
        return "Communication";
    }    @Nullable
    @Override
    public Map getConstants() {
        HashMap constants = new HashMap();
        constants.put("systemName","android");        return constants;
    }       //我們想要呼叫的原生的android方法,這個方法可以開啟一個activity,同時還可以傳遞引數過來
    @ReactMethod
    public void StartActivityFromReactNative(String activityName, String data, Promise promise, Callback callback){
        Activity currentActivity = getCurrentActivity();        try{            if(currentActivity != null){
               Class> toActivity = Class.forName("yourPackageName" +"." +activityName);
                Intent intent = new Intent(currentActivity,toActivity);
                intent.putExtra("params",data);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//在react native 開啟activity
                currentActivity.startActivity(intent);
            }
            promise.resolve(true);
            callback.invoke(true);
        }catch(ClassNotFoundException e){            throw new JSApplicationIllegalArgumentException("開啟activity失敗"+e.getMessage());
        }

    }
}

在這裡我們實現了一個必須的方法就是getName這個方法返回的是我們想要呼叫的那個模組的名稱,也就是當前物件。同時我們想要給react-native傳遞一些引數,就實現了getConstants方法,在這個方法中我們設定了當前平臺的名稱。我們想要呼叫一個android本地的方法,所以我們實現了StartActivityFromReactNative方法,重要的是我們需要設定@ReactMethod註解。呼叫完StartActivityFromReactNative方法後我們想要知道呼叫結果呢?我們有兩種方式PromiseCallback都可以,例如上面的程式碼。

2.把這個模組匯出(實現匯出介面ReactPackage)

//.../**
 * Created by feiyu on 2018/5/12.
 */public class Communication implements ReactPackage {    @Override
    public List createNativeModules(ReactApplicationContext reactContext) {
        List modules = new ArrayList();
        modules.add(new CommunicationModule(reactContext));        return modules;
    }    @Override
    public List createViewManagers(ReactApplicationContext reactContext) {        return Collections.emptyList();
    }    public List> createJSModules(){        return Collections.emptyList();
    }
}

上面的這個就是固定模式了,你在實現任意的模組時都可以複製上面的程式碼,然後把CommunicationModule換成你的。

3.把這個模組註冊釋出(在MainApplication中註冊)

第三步就非常簡單了!

//...public class MainApplication extends Application implements ReactApplication {  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {    @Override
    public boolean getUseDeveloperSupport() {      return BuildConfig.DEBUG;
    }    @Override
    protected List getPackages() {      return Arrays.asList(          new MainReactPackage(),              new Communication()
      );
    }    @Override
    protected String getJSMainModuleName() {      return "index";
    }
  };    //...}

最後我們在getPackages中返回我們的物件就可以了new Communication().

react-native 呼叫android原生

react-native呼叫原生平臺是基於NativeModules,呼叫的方法是NativeModules.模組名稱.介面名稱。
原生平臺返回資料到react-native平臺是基於回撥,回撥的原型定義是RCTRResponseSenderBlock(IOS)平臺com.facebook.react.bridge.CallBack(Android平臺)

我們想要獲取android平臺定義的那個systemName的話只需要這樣:

if(Platform.OS === "android"){    let systemName = NativeModule.Communction.systemName;
}

呼叫我們定義的那個開啟activity的方法也是同上:

if(Platform.OS === "android"){
    NativeModule.Communction.StartActivityFromReactNative("CommunicationActivity",123456);
}

這樣就可以了。然後怎麼獲取到react-native給傳過來的資料呢?在androidactivity中:

public class CommunicationActivity extends AppCompatActivity {    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_communication);
        
        Intent intent = getIntent();        if(intent != null){
            String params = intent.getStringExtra("'params");
            Toast.makeText(this,"從react-native中傳遞過來的資料"+params,Toast.LENGTH_LONG).show();
        }
    }
}

需要注意的地方:

1.react native呼叫android進行介面跳轉時,需要設定FLAG_ACTIVITY_NEW_TASK標誌
2.我們在呼叫android的模組時,名稱要和getName的方法一樣:

 NativeModule.Communction.systemName;

就是Communction...

到這裡react-nativeandroid的就Over了。祝大家週末愉快!

參考書籍:《React Native 實戰》



作者:雨飛飛雨
連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1795/viewspace-2810117/,如需轉載,請註明出處,否則將追究法律責任。

相關文章