Как получить доступ к действию с помощью Android-модуля React Native?
Я пытаюсь подключиться к функциям Android, чтобы сохранить экран в React Native. Я решил, что могу сделать это с помощью простого модуля, однако я не знаю, как получить доступ к текущей активности Android из указанного модуля.
Мне нужна ссылка Activity, поэтому я могу называть .getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
на ней
Я попытался получить активность с помощью каста таким образом ((Activity)getReactApplicationContext().getBaseContext())
, но это вызывает ошибку "не может быть перенесена в Android.app.Activity"
Ответы
Ответ 1
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
- это мой собственный компонент пользовательского интерфейса. Я определяю конструктор так, чтобы я мог передавать в действие:
public LSPlayerManager(Activity activity) {
mActivity = activity;
}
И наконец, в MainActivity.java
, где определен ReactInstanceManager
, мы можем передать активность в наш пользовательский пакет React:
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();
ОБНОВЛЕНИЕ ДЛЯ РЕАКТИВНОЙ ДЕЯТЕЛЬНОСТИ 0.29.0
Это уже не то, как вы получаете доступ к активности в собственном модуле. См. https://github.com/facebook/react-native/releases/tag/v0.29.0 для инструкций по миграции
Ответ 2
Я думаю, getCurrentActivity()
метод ReactContextBaseJavaModule может использоваться как следующий код, который был скопирован из 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;
}
}
}
Ответ 3
Editted:
Проблема заключается в том, что getReactApplicationContext() возвращает контекст приложения, а не Activity. Вы не можете привить контекст приложения к Activity.
Это простой способ
Как правило, в реакции-native есть только одно действие (основная активность). Мы можем записать статическую функцию в MainActivity, чтобы вернуть активность
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;
}
затем вызовите MainActivity.getActivity()
из мостовых модулей
Ответ 4
Для 0.28 и раньше вы можете получить активность от ReactInstanceManagerImpl
private @Nullable Activity mCurrentActivity;
, 0.29+ ReactContextBaseJavaModule
с использованием того же поля.
Ответ 5
Как передать активность в пакет из ReactApplication:: getPackages()?
Я не понимаю. Я не могу найти четких примеров
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;
}
}
Ответ: вы не передаете Activity из MainApplication в пакет.
Вы вызываете getCurrentActivity() из вашего ReactContextBaseJavaModule
Ответ 6
Мне нужно было изменить устаревший модуль (react-android-360-video) и нашел это полезным...
В android/app/src/main/java/com/webcdpmobiledemo/MainApplication.java
я использовал новый формат для добавления пакета:
...
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()
);
}
...
};
...
}
И android/app/src/main/java/com/webcdpmobiledemo/MainActivity.java
по существу пуст:
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";
}
}
Затем я изменил файл VrVideoViewPackage, который должен передать reactContext
в VrVideoViewManager
, который он вызывает:
...
public class VrVideoViewPackage implements ReactPackage {
...
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new VrVideoViewManager(reactContext)
);
}
}
И, наконец, в VrVideoViewManager
к активности можно обратиться так:
...
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);
}
...
}
Ответ 7
Это не очень ясно из https://github.com/facebook/react-native/blob/master/docs/NativeModulesAndroid.md, но вы можете прочитать исходный код ToastModule в ответном родном дистрибутиве, чтобы увидеть, как они сделайте это github.com/facebook/react-native/blob/daba14264c9f0d29c0327440df25d81c2f58316c/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.java#L31-L33
Идея состоит в том, что основное действие будет передано как responseContext в инициализаторе для модуля, вызванного вызовом ReactInstanceManager.builder() в github.com/facebook/react-native/blob/3b4845f93c296ed93c348733809845d587227823/local-cli/generator -android/templates/package/MainActivity.java # L28 через экземпляр MainReactPackage github.com/facebook/react-native/blob/daba14264c9f0d29c0327440df25d81c2f58316c/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java # L49