2017-10-20 17 views
8

Znalazłem wiele artykułów mówiących o tym, jak zintegrować reagowanie natywne z istniejącymi aplikacjami na Androida. Ale żaden z nich nie wyjaśnia, w jaki sposób uzyskać zwrot z reakcji na kod natywny, aby użyć go bezpośrednio w kodzie źródłowym Java na Androida.Uzyskaj wynik z natywnej aplikacji reagującej zintegrowanej z istniejącą aplikacją na Androida

Objaśnienia: Mam aplikację macierzystą reagującą, która wykonuje określone zadanie i wyświetla wynik w wyskakującym okienku. Chcę zintegrować tę aplikację (wykonując niezbędne modyfikacje), aby móc uzyskać ten konkretny wynik w moim kodu źródłowym Java systemu Android, zamiast wyświetlać go w rodzimym wyskakującym okienku.

Przeszukałem cały Internet, ale nic nie znalazłem.

+0

Nie jestem dobry z natywnym kodem, ale czy nie możesz uruchomić nowej natywnej metody z żądanymi danymi jako parametrem? – bennygenel

+0

Myślę, że powinieneś odnieść się do 'zamiaru androida ', aby osiągnąć swój cel, użyć intencji wewnątrz twojej java, aby przyciągnąć twoją reakcję, a następnie powrócić z wynikiem https://facebook.github.io/react-native/releases/0.21/docs /intentandroid.html –

Odpowiedz

3

Aby uzyskać wynik z powrotem z działalności uruchomiłeś Twój moduł musi mieć dostęp do referencji twojej aktywności.
Oto dwa rozwiązania:
- stwierdzenie moduł jako wewnętrzna klasy aktywności
- Pass odniesienie swojej działalności w konstruktorze modułu

Ale należy pamiętać, że moduł musi być używany w a ReactPackage i ReactPackage to interfejs, więc jeśli chcesz, możesz mieć ReactActivity implementującą interfejs (zamiast tworzyć nową klasę).

Oto pełny przykład roboczych za pomocą inner class oraz działalność realizacji 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); 
    } 

} 

Następnie można rozpocząć swój ReactActivity tak:

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

uzyskać wynik takiego:

@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" 
    } 
} 

I sus t używaj go w React:

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

Może nie rozumiem, co chcesz zrobić ... ale nie możesz po prostu zbudować modułu natywnego, a aplikacja React Native wywołaj tę funkcję, gdy zostanie wykonana, aby przekazać dane do kodu natywnego ?

Załóżmy, że masz aplikację React Native w swojej aplikacji, która pobiera imię i nazwisko użytkownika jako dane wejściowe i trafiają one do przesyłania.

Kodować javascript RN normalnie: mieć 2 pola TextInput z ich wartościami zmapowanymi do twojego stanu i przycisk z handlersem onPress. W obsługi onPress, należy skontaktować się z Native moduł i przekazać parametry

import { 
    NativeModules 
} from 'react-native'; 

const NativeNameSubmission = NativeModules.NameSubmission; 

... 

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

ojczystym Moduł byłoby coś jak to wygląda:

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

Myślę, że to jest dobra część, ale chcę zamknąć aplikację React Native, gdy wywołasz "NativeNameSubmission".submitName() 'i użyj wyniku (' firstName' i 'lastName' w twoim przypadku) bezpośrednio w działaniu, które jest odpowiedzialne za instancję działania Native Native app. – Marc

+0

Uruchom aktywność RN z zamiarem i uruchom Aktywność, która nasłuchuje w trybie onActivityResult. Dodałem kod, aby zamknąć aplikację RN z modułu (getCurrentActivity(). Finish();). W module możesz zapisać dane do późniejszego użycia przez pierwotną aktywność lub możesz je przekazać z powrotem w onActivityResult –

Powiązane problemy