2017-10-20 24 views
8

我發現了很多關於如何將反應本機集成到現有Android應用程序中的文章。但是他們都沒有解釋如何從反應原生代碼中得到結果以便直接在Java android源代碼中使用它。從反應本機應用程序集成到現有的Android應用程序中獲得結果

說明:我有一個反應本機應用程序,它正在執行特定作業並在彈出窗口中顯示結果。 我想整合這個應用程序(做必要的修改),以便能夠將此特定結果導入到我的Android Java源代碼中,而不是將其顯示到反應本機彈出窗口中。

我搜索了所有的互聯網,但沒有發現任何關於此。

+0

我不擅長本地代碼,但不能運行一個新的本地方法與所需的數據作爲參數? – bennygenel

+0

我認爲你應該引用'android intent'來達到你的目標,在你的java裏面使用intent來引起你的反應,然後用結果來回想https://facebook.github.io/react-native/releases/0.21/docs /intentandroid.html –

回答

3

爲了得到一個結果,從你開始將該活動,你的模塊需要訪問你的活動的參考。
這裏有兩種解決方案:
- 聲明模塊作爲一個內部類活動的
- 通過在模塊

中的構造您的活動的參考,但,請記住,你的模塊需要使用一個ReactPackageReactPackage是一個接口,所以如果你想讓你的ReactActivity實現接口(而不是創建一個新類)。

下面是使用inner class和一個完整的工作示例活動實施ReactPackage

public class MyReactActivity extends AppCompatActivity 
    implements DefaultHardwareBackBtnHandler, ReactPackage 
{ 
    private ReactRootView mReactRootView; 
    private ReactInstanceManager mReactInstanceManager; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     mReactRootView = new ReactRootView(this); 
     mReactInstanceManager = ReactInstanceManager.builder() 
       .setApplication(getApplication()) 
       .setBundleAssetName("index.android.bundle") 
       .setJSMainModuleName("index.android") 
       .addPackage(new MainReactPackage()) 
       // This activity is also a "ReactPackage" 
       .addPackage(this) 
       .setUseDeveloperSupport(BuildConfig.DEBUG) 
       .setInitialLifecycleState(LifecycleState.RESUMED) 
       .build(); 

     mReactRootView.startReactApplication(mReactInstanceManager, "MyReactComponent", null); 

     setContentView(mReactRootView); 
    } 

    @Override 
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { 
     List<NativeModule> modules = new ArrayList<>(); 
     // The module is added to the ReactPackage 
     modules.add(new TestModule(reactContext)); 
     return modules; 
    } 

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

    // Module definition as an inner class 
    public class TestModule extends ReactContextBaseJavaModule { 
     public TestModule(ReactApplicationContext reactContext) { 
      super(reactContext); 
     } 

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

     // The function you'll call from React Native 
     @ReactMethod 
     public void closewithresult(float datafromreact) { 
      // Set a result 
      Bundle bundle = new Bundle(); 
      bundle.putFloat("result", datafromreact); 
      setResult(Activity.RESULT_OK, (new Intent()).putExtras(bundle)); 

      // Close the activity 
      finish(); 
     } 
    } 

    /* 
    * Other overrided functions 
    * (not relevant for this question) 
    */ 
    @Override 
    public void invokeDefaultOnBackPressed() { 
     super.onBackPressed(); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 

     if (mReactInstanceManager != null) { 
      mReactInstanceManager.onHostPause(this); 
     } 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 

     if (mReactInstanceManager != null) { 
      mReactInstanceManager.onHostResume(this, this); 
     } 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 

     if (mReactInstanceManager != null) { 
      mReactInstanceManager.onHostDestroy(this); 
     } 
    } 

    @Override 
    public void onBackPressed() { 
     if (mReactInstanceManager != null) { 
      mReactInstanceManager.onBackPressed(); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

    @Override 
    public boolean onKeyUp(int keyCode, KeyEvent event) { 
     if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) { 
      mReactInstanceManager.showDevOptionsDialog(); 
      return true; 
     } 
     return super.onKeyUp(keyCode, event); 
    } 

} 

然後,你就可以開始你的ReactActivity這樣的:

Intent intent = new Intent(getApplicationContext(), MyReactActivity.class); 
startActivityForResult(intent, 123); 

得到這樣的結果:

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (requestCode == 123 && resultCode == Activity.RESULT_OK) { 
     float result = data.getExtras().getFloat("result"); 
     // Do whatever you want with "result" 
    } 
} 

And jus t在反應中使用它:

import { NativeModules } from 'react-native'; 
// [...] 
// Call the function 
NativeModules.TestModule.closewithresult(654.532); 
3

也許我不明白你想做什麼..但你不能只是建立一個本地模塊,並讓你的React Native應用程序在完成將數據傳遞到本地代碼時調用該函數?

比方說,您的應用的React Native部分將用戶的姓名和姓氏作爲輸入,並且他們會提交。

您可以將您的RN JavaScript編碼爲正常:將2個TextInput字段的值映射到您的狀態,並使用帶有onPress處理程序的Button。在onPress處理,你會打電話給你的本機模塊並通過參數

import { 
    NativeModules 
} from 'react-native'; 

const NativeNameSubmission = NativeModules.NameSubmission; 

... 

    <Button 
     onPress={() => NativeNameSubmission.submitName(this.state.firstName, this.state.lastName)} 
     title="Submit"/> 

你的本機模塊會是這個樣子:

public class RCTNameSubmission extends ReactContextBaseJavaModule { 

    public RCTNameSubmission(ReactApplicationContext reactContext) { 
     super(reactContext); 
    } 

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

    @ReactMethod 
    public void submitName(String firstName, String lastName) { 
     // save the name data for later use 
     ... 
     // Exit React App 
     getCurrentActivity().finish(); 
    } 
} 
+0

我認爲這是一個很好的部分,但我想在調用NativeNameSubmission時關閉React Native應用程序。submitName()'並直接在負責React Native應用程序活動的實例的活動中使用結果(在您的案例中爲'firstName'和'lastName')。 – Marc

+0

以意圖啓動RN活動,並讓啓動它的活動偵聽onActivityResult。我添加了代碼來關閉模塊中的RN應用程序(getCurrentActivity()。finish();)。在模塊中,您可以保存數據供以後使用原始活動,或者您可以將其傳回onActivityResult –

相關問題