Google VR Android开发(二)-Simplevideowidget分析

来源:互联网 发布:unity3d人才过剩 编辑:程序博客网 时间:2024/06/04 01:34
Simplevideowidget这个Demo运行起来的效果如下:

单击视频显示区域可以暂停/继续播放。
点击眼镜按钮可以进入到双眼VR模式:

现在分析下代码实现:
只有一个Activity文件:

主要是显示了一个SDK中的VrVideoView控件
进入VR双眼模式和全屏显示的切换按钮都在这个控件里面。所以要分析下这个控件的实现。
模式切换的实现是在VrVideoView的父类VrWidgetView中。如下:

private void initializeUiButtons() {
    this.enterFullscreenButton = (ImageButton)this.uiView.findViewById(id.fullscreen_button);
    this.enterFullscreenButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            VrWidgetView.this.setDisplayMode(2);
        }
    });
    this.enterStereoModeButton = (ImageButton)this.uiView.findViewById(id.vr_mode_button);
    this.enterStereoModeButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            VrWidgetView.this.setDisplayMode(3);
        }
    });
    this.fullscreenBackButton = (ImageButton)this.uiView.findViewById(id.fullscreen_back_button);
    this.fullscreenBackButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            VrWidgetView.this.setDisplayMode(1);
        }
    });
    this.infoButton = (ImageButton)this.uiView.findViewById(id.info_button);
    this.infoButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            VrWidgetView.this.activity.startActivity(VrWidgetView.getInfoButtonIntent());
        }
    });
    this.updateButtonVisibility();
}


可以知道DisplayMode 3为VR模式。
现在看下setDisplayMode3的背后发生了什么。

public void setDisplayMode(int newDisplayMode) {
    if(newDisplayMode != this.displayMode) {
        this.renderer.updateCurrentYaw();
        if(newDisplayMode <= 0 || newDisplayMode >= 4) {
            Log.e(TAG, (new StringBuilder(38)).append("Invalid DisplayMode value: ").append(newDisplayMode).toString());
            newDisplayMode = 1;
        }

        this.displayMode = newDisplayMode;
        this.updateStereoMode();
        if(this.isFullScreen()) {
            this.orientationHelper.lockOrientation();
            this.fullScreenDialog.show();
        } else {
            this.fullScreenDialog.dismiss();
            this.orientationHelper.restoreOriginalOrientation();
        }

        this.updateControlsLayout();
        this.updateTouchTracker();
        this.eventListener.onDisplayModeChanged(this.displayMode);
    }
}


这里可以知道,首先更新了Yaw(偏航角),然后调用了updateStereoMode(),之后关闭fullScreenDialog,并重新装载了原始四元素。
最后更新布局等。
这里看下updateStereoMode这个函数:

private void updateStereoMode() {
    this.renderer.setStereoMode(this.displayMode == 3);
    AndroidNCompat.setVrModeEnabled(this.activity, this.displayMode == 3, 0);
    if(this.displayMode == 3) {
        this.screenOnFlagHelper.start();
    } else {
        this.screenOnFlagHelper.stop();
    }

    this.updateButtonVisibility();
    this.updateViewerName();
}


其调用到了AndroidNCompat.setVrModeEnabled以及ScreenOnFlagHelper类型成员screenOnFlagHelper的start函数。
跟踪AndroidNCompat可以发现:

public static boolean setVrModeEnabled(Activity var0, boolean var1, int var2) {
    if(!isVrModeSupported(var0)) {
        if(isAtLeastN()) {
            Log.d(TAG, "VR mode is not supported on this N device.");
        }

        return false;
    } else {
        ComponentName var3 = new ComponentName("com.google.vr.vrcore", "com.google.vr.vrcore.common.VrCoreListenerService");

        String var10000;
        String var5;
        try {
            var0.setVrModeEnabled(var1, var3);
            return true;
        } catch (NameNotFoundException var6) {
            var10000 = TAG;
            var5 = String.valueOf(var6);
            Log.w(var10000, (new StringBuilder(25 + String.valueOf(var5).length())).append("No VR service component: ").append(var5).toString());
            if((var2 & 1) != 0 && handleVrCoreAbsence(var0, checkForVrCorePresence(var0))) {
                Log.w(TAG, "Failed to handle missing VrCore package.");
            }
        } catch (UnsupportedOperationException var7) {
            var10000 = TAG;
            var5 = String.valueOf(var7);
            Log.w(var10000, (new StringBuilder(23 + String.valueOf(var5).length())).append("Failed to set VR mode: ").append(var5).toString());
        }

        return false;
    }
}

核心在var0.setVrModeEnabled(var1,var3)这一句
查看AndroidN最新的Activity.java代码,有新增接口setVrModeEnabled

    public void setVrModeEnabled(boolean enabled, @NonNull ComponentName requestedComponent)
          throws PackageManager.NameNotFoundException {
        try {
            if (ActivityManagerNative.getDefault().setVrMode(mToken, enabled, requestedComponent)
                    != 0) {
                throw new PackageManager.NameNotFoundException(
                        requestedComponent.flattenToString());
            }
        } catch (RemoteException e) {
            // pass
        }
    }
而screenOnFlagHelper的start函数主要是开启了传感器数据的发送,1为 Sensor.TYPE_ACCELEROMETER 1 加速度传感器 

public void start() {
    if(this.sensorManager == null) {
        this.sensorManager = (SensorManager)this.activity.getSystemService("sensor");
    }

    if(this.sensor == null) {
        this.sensor = this.sensorManager.getDefaultSensor(1);
    }

    this.isFlagSet = false;
    this.setKeepScreenOnFlag(true);
    this.sensorStats.reset();
    this.sensorManager.registerListener(this, this.sensor, 250000);
}

所以,很好理解了。SDK中的这个控件封装了AndroidN中新增的Activity.setVrModeEnabled和加速度传感器的启用来实现了具备VR功能的video控件

阅读全文
0 0