Comment accéder à L'activité à partir D'un module Android React Native?
J'essaie de combler la fonctionnalité Android de garder l'écran allumé pour réagir natif. J'ai pensé que je pourrais le faire avec un module simple, mais je ne sais pas comment accéder à l'Activité Android actuelle à partir dudit module.
J'ai besoin de la référence D'activité pour pouvoir appeler .getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
dessus
J'ai essayé d'obtenir l'activité via le casting comme ceci ((Activity)getReactApplicationContext().getBaseContext())
, mais cela lance un " Impossible à lancer sur Android.App.Activité " erreur
7 réponses
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
est mon composant D'interface utilisateur natif. Je définis un constructeur afin que je puisse passer dans l'activité:
public LSPlayerManager(Activity activity) {
mActivity = activity;
}
Et enfin dans MainActivity.java
où le ReactInstanceManager
est défini, nous pouvons passer l'activité à notre paquet React personnalisé:
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();
MISE À JOUR POUR REACT NATIVE 0.29.0
Ce n'est plus la façon dont vous accédez à l'activité dans un module natif. Voir https://github.com/facebook/react-native/releases/tag/v0.29.0 pour les instructions de migration
Je suppose que getCurrentActivity()
Méthode de ReactContextBaseJavaModule pourrait être utilisé comme le code suivant qui a été copié à partir du code d'origine React-Native
;
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;
}
}
}
Édité:
Le problème est que getReactApplicationContext() renvoie le contexte de l'Application et non l'activité. Vous ne pouvez pas convertir un contexte D'Application en une activité.
C'est une solution de contournement simple
Comme il n'y a généralement qu'une seule activité (activité principale) dans react-native, nous pouvons écrire une fonction statique dans MainActivity pour renvoyer l'activité
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;
}
Puis appelez MainActivity.getActivity()
à partir des modules de Pont
Pour 0.28 et avant, vous pouvez obtenir l'activité de ReactInstanceManagerImpl
s private @Nullable Activity mCurrentActivity;
, 0.29 + ' s ReactContextBaseJavaModule
en utilisant le même champ.
Comment passez-vous l'activité à un paquet à partir de ReactApplication:: getPackages ()?
Je ne comprends pas. Je ne trouve aucun exemple clair
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;
}
}
Réponse: vous ne passez pas L'activité de MainApplication au paquet.
Vous appelez getCurrentActivity () depuis votre ReactContextBaseJavaModule
Ce n'est pas super clair de https://github.com/facebook/react-native/blob/master/docs/NativeModulesAndroid.md , mais vous pouvez lire le code source du ToastModule dans la distribution native react pour voir comment ils le font github.com/facebook/react-native/blob/daba14264c9f0d29c0327440df25d81c2f58316c/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.java#L31-L33
L'idée est que l'activité principale sera passée en tant que reactContext dans l'initialiseur pour le module appelé à partir de ReactInstanceManager.builder () appeler github.com/facebook/react-native/blob/3b4845f93c296ed93c348733809845d587227823/local-cli/generator-android/templates/package/MainActivity.java#L28 via l'instanciation de MainReactPackage github.com/facebook/react-native/blob/daba14264c9f0d29c0327440df25d81c2f58316c/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java#L49
J'avais besoin de modifier un module obsolète ( react-android-360-video) et j'ai trouvé cela utile...
Dans android/app/src/main/java/com/webcdpmobiledemo/MainApplication.java
, j'ai utilisé le nouveau format pour ajouter un paquet:
...
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()
);
}
...
};
...
}
Et {[5] } sont essentiellement vides:
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";
}
}
Ensuite, j'ai modifié le fichier VrVideoViewPackage, qui doit passer le reactContext
au VrVideoViewManager
qu'il appelle:
...
public class VrVideoViewPackage implements ReactPackage {
...
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new VrVideoViewManager(reactContext)
);
}
}
Et enfin, dans le VrVideoViewManager
l'activité est accessible comme ceci:
...
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);
}
...
}