web-dev-qa-db-fra.com

Comment accéder à Activity depuis un module Android React Native?

J'essaie de passer en revue la fonctionnalité Android permettant de garder l'écran allumé pour réagir à Native. Je pensais pouvoir le faire avec un module simple, mais je ne savais pas comment accéder à l'actuelle activité Android à 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, donc ((Activity)getReactApplicationContext().getBaseContext()), mais cela génère une erreur "ne peut pas être converti vers Android.app.Activity"

23
marcshilling

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 pour pouvoir passer à l'activité:

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

Et enfin dans MainActivity.Java où la ReactInstanceManager est définie, nous pouvons transmettre l'activité à notre package 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 LES RÉACTIFS NATIVE 0.29.0

Ce n'est plus ainsi que vous accédez à l'activité d'un module natif. Voir https://github.com/facebook/react-native/releases/tag/v0.29.0 pour les instructions de migration.

34
marcshilling

Je suppose que la méthode getCurrentActivity() de ReactContextBaseJavaModule pourrait être utilisée comme le code suivant, qui a été copié à partir du code React-Native d'origine;

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;
    }

  }

}
15
efkan

Édité:

Le problème est que getReactApplicationContext () renvoie le contexte de l'application et non l'activité. Vous ne pouvez pas transtyper un contexte d'application en activité. 

Ceci est une solution de contournement simple

Comme d'habitude, il n'y a qu'une 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 

4
Nishanth Shankar

Comment passez-vous l'activité à un paquet à partir de ReactApplication :: getPackages ()? 

Je ne comprends pas. Je ne trouve pas d'exemples clairs

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 transmettez PAS l'activité de MainApplication au package.

Vous appelez getCurrentActivity () depuis votre ReactContextBaseJavaModule 

0
Ed of the Mountain

Pour les versions 0.28 et antérieures, vous pouvez obtenir une activité à partir du private @Nullable Activity mCurrentActivity; de ReactInstanceManagerImpl, des ReactContextBaseJavaModule de 0.29+ en utilisant le même champ.

0
oscarthecat