我正试图跨越Android屏幕保持React Native的功能。我想我可以用一个简单的模块做到这一点,但是我不知道如何从所述模块访问当前的Android Activity。
我需要Activity引用,因此我可以在其上调用((Activity)getReactApplicationContext().getBaseContext())
我尝试通过像{{1}}这样的转换来获取活动,但这会抛出“无法转换为Android.app.Activity”错误
答案 0 :(得分:34)
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
是我的原生UI组件。我定义了一个构造函数,以便我可以传入活动:
public LSPlayerManager(Activity activity) {
mActivity = activity;
}
最后在定义MainActivity.java
的{{1}}中,我们可以将活动传递给我们的自定义React包:
ReactInstanceManager
REACT NATIVE更新0.29.0
这不再是您在本机模块中访问活动的方式。有关迁移说明,请参阅https://github.com/facebook/react-native/releases/tag/v0.29.0
答案 1 :(得分:18)
我猜ReactContextBaseJavaModule的getCurrentActivity()
方法可能会被使用,就像下面的代码一样,它是从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;
}
}
}
答案 2 :(得分:6)
Editted:
问题是getReactApplicationContext()返回Application的上下文而不是Activity。您不能将Application上下文类型转换为Activity。
这是一个简单的解决方法
通常,反应原生中只有一个活动(主要活动),我们可以在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()
答案 3 :(得分:1)
在您的课程文件中,导入内容包括...
import android.view.WindowManager;
import android.view.Window;
import android.view.View;
在您的类构造函数中...
private static ReactApplicationContext reactContext;
MyModule(ReactApplicationContext context) {
super(context);
reactContext = context;
}
然后输入类方法...
@ReactMethod
public void doSomethingRequiringWindow() {
// get access to current UI thread first
reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Window window = reactContext
.getCurrentActivity().getWindow();
View decorView = reactContext
.getCurrentActivity().getWindow().getDecorView();
// you have access to main ui thread so you can effect
// immediate behavior on window and decorView
}
});
}
答案 4 :(得分:0)
对于0.28及之前,您可以使用同一字段从ReactInstanceManagerImpl
的{{1}},0.29 + private @Nullable Activity mCurrentActivity;
获取活动。
答案 5 :(得分:0)
如何将活动从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;
}
}
答案:您没有将活动从MainApplication传递到包。
从ReactContextBaseJavaModule中调用getCurrentActivity()
答案 6 :(得分:0)
对于自定义UI组件,您可以在构造函数中获取上下文,稍后可以通过context.getCurrentActivity()
答案 7 :(得分:0)
如果您想在 import xarray as xr
import numpy as np
# aggregation function
def aggregate_xr_dataset(ds, n_types = 2):
#prepare a resultant xr dataset
regions = ds['regions'].values
time_steps = ds['time'].values
types = [f'type_{i}' for i in range(n_types)]
data = np.zeros((len(time_steps), len(regions), n_types))
res_ts_var_da = xr.DataArray(data, [('time', time_steps),
('regions', regions),
('types', types)])
data = np.zeros((len(regions), len(types)))
res_values_var_da = xr.DataArray(data, [('regions', regions),
('types', types)])
# Aggregation in every region...
for region in regions:
# Get ts and values of current region
regional_ds = ds.sel(regions = region)
regional_ts_da = regional_ds['ts_var']
regional_value_da = regional_ds['values_var']
# Preprocess - stack and transpose dimensions
regional_ts_da = regional_ts_da.stack(x_y = ['x', 'y'])
regional_ts_da = regional_ts_da.transpose(transpose_coords= True)
regional_value_da = regional_value_da.stack(x_y = ['x', 'y'])
regional_value_da = regional_value_da.transpose(transpose_coords= True)
# Aggregation
## values
res_values_var_da.loc[region, types[0]] = regional_value_da[dict(x_y=slice(None, 3))].sum()
res_values_var_da.loc[region, types[1]] = regional_value_da[dict(x_y=slice(3, 9))].sum()
## ts
res_ts_var_da.loc[:, region, types[0]] = regional_ts_da[dict(x_y=slice(None, 3))].sum()
res_ts_var_da.loc[:, region, types[1]] = regional_ts_da[dict(x_y=slice(3, 9))].sum()
# Create resulting dataset
res_ds = xr.Dataset({"values": res_values_var_da,
"ts": res_ts_var_da})
return res_ds
# xarray dataset
regions = ['reg_1','reg_2']
x_locations = np.arange(3)
y_locations = np.arange(3)
time = np.arange(3)
## time series data
ts_var = np.array([ [[[1, 1, 1] for i in range(3)] for i in range(3)],
[[[1, 1, 1] for i in range(3)] for i in range(3)]
])
ts_var_da = xr.DataArray(ts_var,
coords=[regions, y_locations, x_locations, time],
dims=['regions', 'y', 'x','time'])
## values data
values_var = np.array([ [[1, 1, 1] for i in range(3)],
[[1, 1, 1] for i in range(3)]
])
values_var_da = xr.DataArray(values_var,
coords=[regions, y_locations, x_locations],
dims=['regions', 'y', 'x'])
ds = xr.Dataset({'ts_var': ts_var_da,
'values_var': values_var_da})
# Function call
aggregate_xr_dataset(ds)
子类中获取前台活动的当前实例,请使用:
ReactContextBaseJavaModule
它来自使用 // class MyReactModule extends ReactContextBaseJavaModule
Activity activity = getCurrentActivity();
ReactContextBaseJavaModule#getCurrentActivity
<块引用>
注意:reactContext.getCurrentActivity()
是包私有。所以你不能使用 ReactApplicationContext#getCurrentActivity
。
reactContext.getCurrentActivity()
的受保护。所以推导出它是可以实现的:ReactContextBaseJavaModule
protected @Nullable final Activity getCurrentActivity() {
return mReactApplicationContext.getCurrentActivity();
}
是包私有的(默认访问)。所以你无法得到它:ReactApplicationContext
<块引用>
布诺斯
由于它是 /* package */ @Nullable Activity getCurrentActivity() {
return mCurrentActivity;
}
,请确保检查它的可用性:
@Nullable
答案 8 :(得分:-1)
从https://github.com/facebook/react-native/blob/master/docs/NativeModulesAndroid.md开始并不是很清楚,但是您可以在react native分发中阅读ToastModule的源代码,看看他们是如何做到这一点github.com/facebook/react-native/blob /daba14264c9f0d29c0327440df25d81c2f58316c/ReactAndroid/src/main/java/com/facebook/react/modules/toast/ToastModule.java#L31-L33
我们的想法是,主要活动将作为反应器中的reactContext传递给调用来自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
答案 9 :(得分:-1)
我需要修改过时的模块(react-android-360-video)并发现这有用......
在android/app/src/main/java/com/webcdpmobiledemo/MainApplication.java
中,我使用 new 格式添加了一个包:
...
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);
}
...
}