2015-09-21 15 views
19

Ich versuche, die Android-Funktionalität zu überbrücken, den Bildschirm auf Native React zu halten. Ich dachte, ich könnte das mit einem einfachen Modul machen, aber ich weiß nicht, wie ich von diesem Modul auf die aktuelle Android-Aktivität zugreifen kann.Zugriff auf Aktivität von einem React Native Android-Modul?

Ich brauche die Aktivität Referenz so ich .getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); auf sie

Ich habe versucht, rufen Sie die Aktivität zu erhalten, wie so ((Activity)getReactApplicationContext().getBaseContext()) über Gießen, aber das wirft ein „nicht zu Android.app.Activity gegossen werden“ Fehler

+0

Beispiele für die Kommunikation zwischen Android und nativen Komponenten. [Repo Link] (http://github.com/amalChandran/ReactNative_Android_integration) – amalBit

Antwort

29

CustomReactPackage.java:

public class CustomReactPackage implements ReactPackage { 

    private Activity mActivity = null; 

    public CustomReactPackage(Activity activity) { 
     mActivity = activity; 
    } 

    @Override 
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { 
     List<NativeModule> modules = new ArrayList<>(); 
     // Add native modules here 
     return modules; 
    } 

    public List<Class<? extends JavaScriptModule>> createJSModules() { 
     return Collections.emptyList(); 
    } 

    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { 
     List<ViewManager> modules = new ArrayList<>(); 
     // Add native UI components here 
     modules.add(new LSPlayerManager(mActivity)); 
     return modules; 
    } 
} 

LSPlayerManager ist meine native UI-Komponente. Ich definiere einen Konstruktor, so dass ich in der Tätigkeit passieren kann:

public LSPlayerManager(Activity activity) { 
    mActivity = activity; 
} 

Und schließlich in MainActivity.java wo die ReactInstanceManager definiert ist, können wir die Aktivität unserer Gewohnheit passieren Reagieren Paket:

mReactInstanceManager = ReactInstanceManager.builder() 
     .setApplication(getApplication()) 
     .setBundleAssetName("index.android.bundle") 
     .setJSMainModuleName("src/index.android") 
     .addPackage(new MainReactPackage()) 
     .addPackage(new CustomReactPackage(this)) // <--- LIKE THIS! 
     .setUseDeveloperSupport(BuildConfig.DEBUG) 
     .setInitialLifecycleState(LifecycleState.RESUMED) 
     .build(); 

UPDATE FÜR REACT NATIVE 0.29.0

Dies ist nicht mehr wie Sie auf die Aktivität in einem nativen mo zugreifen Dule.Siehe https://github.com/facebook/react-native/releases/tag/v0.29.0 für Migration Anweisungen

+0

danke .. Das hat sehr geholfen –

+0

Dies ist definitiv die beste Antwort und genau das, was ich in meinem eigenen Projekt mache. In meinem Fall benutze ich den eingebetteten ZXing QR Code Scanner innerhalb von React Native und benötige sowohl den Scan starten als auch das Ergebnis lesen (onActivityResult). Hier ist der Kern meines Codes für den Fall, dass es jemand mit dem ähnlichen Problem hilft - https://gist.github.com/mdp/a501edd93632f13fd9f8 –

+0

Wie kann ich die aktuelle Aktivität an die neue Möglichkeit übergeben, Pakete hinzuzufügen. Arrays zurückgeben. asList ( neu MainReactPackage(), new ThePackageClass (this) <- das hier funktioniert nicht ); das funktioniert hier nicht. –

-1

Es ist nicht super klar von https://github.com/facebook/react-native/blob/master/docs/NativeModulesAndroid.md, aber Sie können den Quellcode des ToastModule in der reaktiven nativen Distribution lesen, um zu sehen, wie sie es tun github.com/facebook/react-native/blob/daba14264c9f0d29c0327440df25d81c2f58316c/ReactAndroid/src/main/ java/com/facebook/reagieren/Module/Toast/ToastModule.java # L31-L33

Die Idee ist, dass die Hauptaktivität als reactContext im Initialisierer für das von ReactInstanceManager.builder() aufgerufene Modul übergeben wird. Github.com/facebook/react-native/blob/3b4845f93c296ed93c348733809845d587227823/local-cli/generator- android/templates/package/MainActivity.java # L28 über die Instantiierung von MainReactPackage github.com/facebook/react-native/blob/daba14264c9f0d29c0327440df25d81c2f58316c/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java# L49

+0

Nicht erklärt, wie Sie die Aktivität erhalten. – marcshilling

3

Editted:

das Problem ist, dass getReactApplicationContext(), um den Kontext der Anwendung zurückgibt und nicht die Aktivität. Sie können einen Anwendungskontext nicht an eine Aktivität übergeben.

Dies ist eine einfache Abhilfe

Da in der Regel gibt es nur eine Aktivität (Hauptaktivität) in reagieren-native, können wir eine statische Funktion in MainActivity schreiben die Aktivität

private static Activity mCurrentActivity = null; 

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mCurrentActivity = this; 
    ... 
} 
... 
public static Activity getActivity(){ 
    Activity activity = new Activity(); 
    activity = mCurrentActivity; 
    return activity; 
} 

dann zurückzukehren rufen MainActivity.getActivity() von den Brückenmodulen

+1

das funktioniert, aber ich nehme an, Sie haben den Kommentar zu GitHub gesehen: https://github.com/facebook/react-native/issues/2996#issuecomment-142913032. Ich benutze diese Methode und es funktioniert großartig. Wenn Sie Ihre Antwort bearbeiten, um diese Methode zu beschreiben, akzeptiere ich sie. – marcshilling

+0

Ich bin noch nicht in der Lage, meine eigene Implementierung von ReactPackage zu erstellen. Da Sie es bereits herausgefunden haben, wird es eine große Hilfe für die Gemeinschaft sein, wenn Sie Ihr Wissen weitergeben können –

+0

hat gerade meine eigene Antwort gepostet. Schau es dir an und probiere es aus. – marcshilling

11

I getCurrentActivity() Methode von ReactContextBaseJavaModule erraten könnte wie der folgende Code verwendet werden, die aus React-Native ursprünglichen Code kopiert worden ist;

import android.app.Activity; 
import com.facebook.react.bridge.ReactContextBaseJavaModule; 

public class AwesomeModule extends ReactContextBaseJavaModule { 

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

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

    private static final String ERROR_NO_ACTIVITY = "E_NO_ACTIVITY"; 
    private static final String ERROR_NO_ACTIVITY_MESSAGE = "Tried to do the something while not attached to an Activity"; 

    @ReactMethod 
    public void doSomething(successCallback, errorCallback) { 

    final Activity activity = getCurrentActivity(); 

    if (activity == null) { 
     errorCallback(ERROR_NO_ACTIVITY, ERROR_NO_ACTIVITY_MESSAGE); 
     return; 
    } 

    } 

} 
+0

Es funktioniert in meinem Fall – xwild

+2

Die Methode wurde entfernt. Gibt es einen neuen Weg dies zu tun? Danke .. –

+0

Der Link, den ich in Antwort geschrieben habe, gibt das Master-Repo von "react-native" an und es scheint lebendig zu sein. Auch ich habe versucht, irgendetwas über seine Entfernung zu finden, aber ich konnte nicht. Könnten Sie bitte mehr Informationen darüber geben? – efkan

0

Für 0.28 und zuvor können Sie Aktivität von ReactInstanceManagerImpl 's private @Nullable Activity mCurrentActivity;, 0.29+' s ReactContextBaseJavaModule mit dem gleichen Feld zu bekommen.

-1

Wie übergeben Sie die Aktivität an ein Paket von ReactApplication :: getPackages()?

Ich verstehe nicht. Ich kann keine klaren Beispiele finden

package com.bluetoothioexample; 

import android.app.Application; 
import android.util.Log; 

import com.facebook.react.bridge.ReactContextBaseJavaModule; 

import com.facebook.react.ReactApplication; 
import com.facebook.react.ReactInstanceManager; 
import com.facebook.react.ReactNativeHost; 
import com.facebook.react.ReactPackage; 
import com.facebook.react.shell.MainReactPackage; 

import java.util.Arrays; 
import java.util.List; 

import com.subsite.bluetoothio.BluetoothIOPackage; 
import com.oblador.vectoricons.VectorIconsPackage; 

public class MainApplication extends Application implements ReactApplication { 

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 
    @Override 
    protected boolean getUseDeveloperSupport() { 
     return BuildConfig.DEBUG; 
    } 

    @Override 
    protected List<ReactPackage> getPackages() { 
     return Arrays.<ReactPackage>asList(
      new MainReactPackage(), 
      new BluetoothIOPackage(this), //<- How pass the activity 
             // from ReactApplication ? 
      new VectorIconsPackage() 
    ); 
    } 
    }; 

    @Override 
    public ReactNativeHost getReactNativeHost() { 
     return mReactNativeHost; 
    } 
} 

Antwort: Sie übergeben keine Aktivität von MainApplication an das Paket.

Sie rufen getCurrentActivity() aus Ihrem ReactContextBaseJavaModule

+0

Macht nichts. Die ReactContextBaseJavaModule-Klasse verfügt über eine getCurrentActivity() -Methode. –

-1

ich eine veraltete Modul ändern benötigt (react-android-360-video) und fanden diese Informationen hilfreich ...

In android/app/src/main/java/com/webcdpmobiledemo/MainApplication.java, nutzte ich die neue Format für das Hinzufügen ein Paket:

... 
import com.vrvideocomponent.VrVideoViewPackage; 

public class MainApplication extends Application implements ReactApplication { 

    ... 

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 
     ... 

     @Override 
     protected List<ReactPackage> getPackages() { 
     return Arrays.<ReactPackage>asList(
      new MainReactPackage(), 
      new VrVideoViewPackage() 
     ); 
     } 

     ... 
    }; 

    ... 
} 

Und android/app/src/main/java/com/webcdpmobiledemo/MainActivity.java ist im wesentlichen leer:

package com.yourproject; 

import com.facebook.react.ReactActivity; 

public class MainActivity extends ReactActivity { 

    /** 
    * Returns the name of the main component registered from JavaScript. 
    * This is used to schedule rendering of the component. 
    */ 
    @Override 
    protected String getMainComponentName() { 
     return "YourProject"; 
    } 
} 

Dann habe ich die VrVideoViewPackage Datei geändert, die die reactContext zum VrVideoViewManager passieren muss es nennt:

... 

public class VrVideoViewPackage implements ReactPackage { 
    ... 

    @Override 
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { 
     return Arrays.<ViewManager>asList(
       new VrVideoViewManager(reactContext) 
     ); 
    } 

} 

Und schließlich in der VrVideoViewManager die Aktivität kann wie so zugegriffen werden:

... 

import android.app.Activity; 
import com.facebook.react.uimanager.ThemedReactContext; 
import com.facebook.react.bridge.ReactContext; 

... 

public class VrVideoViewManager extends SimpleViewManager<VrVideoView> { 
    ... 

    public VrVideoViewManager(ReactContext reactContext) { 
     // Do not store mActivity, always getCurrentActivity when needed 
     Activity mActivity = mContext.getCurrentActivity(); 
    } 

    @Override 
    protected VrVideoView createViewInstance(ThemedReactContext reactContext) { 

     // You can also activity from ThemedReactContext 
     Activity mActivity = reactContext.getCurrentActivity(); 

     VrVideoView vrView = new VrVideoView(mActivity); 
     vrView.setEventListener(new ActivityEventListener(vrView)); 
     vrView.pauseVideo(); 
     return new VrVideoView(mActivity); 
    } 

    ... 
} 
+0

Bis zum Paket ist ok, danach? Ich muss DeviceToken von Modul bekommen 'öffentliche Klasse DeviceModule erweitert ReactContextBaseJavaModule' eine Zeichenfolge Wert als "PackageReference.ReactOverridemethod.StringValue" von .js ???? – Ramaraju

+0

@Ramaraju Ich bin mir nicht sicher, ob ich deine Frage verstehe, kannst du das anders formulieren? Die von mir bereitgestellte Lösung dient zum Extrahieren von Aktivitäten innerhalb einer ReactPackage-Klasse und einer SimpleViewManager-Klasse. Wenn Sie aus der Klasse ReactContextBaseJavaModule extrahieren möchten, können Sie sich die Antwort von efkan ansehen –