解决!阅读我的回答。
我试图在原生React应用程序中显示Unity视图。 UnityPlayer使用Vuforia显示AR的摄像头源。我们需要在iOS和Android的React原生应用程序中包含此视图。
我关注了许多指南,但Android版本中有黑屏。 如果我在react-native(而不是ReactActivity)生成的Android项目中运行UnityPlayerActivity(来自Unity导出的Android项目),我会正确看到我的UnityPlayer。所以我想我的项目包含了所有必要的依赖项。
我的js代码的代码片段:
volumes:
- ./code:/home/app/code
遵循本指南https://facebook.github.io/react-native/docs/native-components-android.html 我有一个自定义包
const UnityIosContainerView = requireNativeComponent("UnityContainerView",
null);
const UnityAndroidContainerView = requireNativeComponent("RCT3DView", null);
class ArPage extends React.Component {
render() {
return (
<View style={{ flex: 1, backgroundColor: "red" }}>
{Platform.OS === "ios" ? (
<UnityIosContainerView style={{ flex: 1 }} />
) : (
<UnityAndroidContainerView style={{ flex: 1 }} />
)}
</View>
);
}
}
这是我的ViewManager连接到MainReactActivity的生命周期以正确管理UnityPlayer
public class CustomReactPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new React3DViewManager()
);
}
}
生成的屏幕截图:
验证点:
Unity 2017.2.0f3
React 16.0.0.0-alpha12
React-native 0.48.4
有没有人遇到过这个问题?
应用程序日志:
public class React3DViewManager extends SimpleViewManager<View> implements LifecycleEventListener {
public static final String REACT_CLASS = "RCT3DView";
private UnityPlayer mUnityPlayer;
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected View createViewInstance(ThemedReactContext reactContext) {
reactContext.addLifecycleEventListener(this);
mUnityPlayer = new UnityPlayer(reactContext);
int glesMode = mUnityPlayer.getSettings().getInt("gles_mode", 1);
boolean trueColor8888 = false;
mUnityPlayer.init(glesMode, trueColor8888);
mUnityPlayer.start();
mUnityPlayer.requestFocus();
return mUnityPlayer.getView();
}
@Override
public void onHostResume() {
mUnityPlayer.resume();
}
@Override
public void onHostPause() {
mUnityPlayer.pause();
}
@Override
public void onHostDestroy() {
mUnityPlayer.quit();
}
}
答案 0 :(得分:5)
好多次尝试后我找到了解决方案。 将UnityPlayer连接到MainActivity的所有生命周期非常重要。 ViewManager类不支持所有活动生命周期。您可以将管理器连接到Resume,暂停和销毁。但UnityPlayer需要onConfigurationChanged以确保布局正确。我直接从Unity生成的UnityPlayerActivity类中获取代码,并在UnityManager中公开UnityPlayer以供使用。
这是我使用UnityPlayer init的MainActivity。
public class MainActivity extends ReactActivity {
private UnityPlayer mUnityPlayer;
public UnityPlayer getUnityPlayer() {
return mUnityPlayer;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy
mUnityPlayer = new UnityPlayer(this);
}
public void onDestroy() {
super.onDestroy();
mUnityPlayer.quit();
}
public void onResume() {
super.onResume();
mUnityPlayer.resume();
}
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "protoreactnative";
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
以下是视图管理员:
public class React3DViewManager extends SimpleViewManager<UnityPlayer> {
public static final String REACT_CLASS = "RCT3DView";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected UnityPlayer createViewInstance(ThemedReactContext reactContext) {
MainActivity activity = (MainActivity)reactContext.getCurrentActivity();
return activity.getUnityPlayer();
}
}
我不知道这个解决方案是否是最佳解决方案,但此解决方案可以满足我的需求。
由于