Google VR Views实战(VR全景图播放器)

Google VR SDK 支持daydream和Cardboard。

环境搭建

  1. android studio 环境,2.2.2或者更高
  2. android sdk版本在25以上
  3. gradle 23.0.1或者更高
  4. 物理设备4.4以上

下载demo:

git clone https://github.com/googlevr/gvr-android-sdk.git

这个工程中有几个官方的例子,其中simplepanowidget就是全景图的例子。

在Android Studio中开始项目

  1. build.gradle文件中添加jcenter(),这样Gradle可以找到AAR文件。例如:
allprojects {

    repositories {

        // For GVR components, the official source of the .aars is JCenter.

        jcenter()
    }
}

2.添加依赖

dependencies {

    compile 'com.google.vr:sdk-audio:1.10.0'

compile 'com.google.vr:sdk-base:1.10.0'
}

1.10.0只是当前版本,后续可以修改。如果不想引用链接,可以直接在导入arr包,这个包在项目的library文件夹下。

VR view 示例代码

  • 支持平台:Android、IOS、WEB
  • 图像规格
VR查看图像可以保存为PNG,JPEG或GIF。Google建议使用JPEG改进压缩。  
为了获得最大的兼容性和性能,图像尺寸应该是2的倍数(例如,2048或4096)。
单个图像应为2:1纵横比(例如4096×2048)。  
立体图像应为1:1纵横比(例如4096×4096)。
  • 视频规格
VR view视频应该被存储为H264编码的mp4文件。
单个视频应是2:1纵横比。
立体视频应是1:1纵横比。
一些较旧的设备不能解码的视频最大不能超过超过1080(1920×1080)。最大的兼容性和质量是头等大事,Google建议用户同时提供平面视觉1920x1080的视频和2048×2048处以上的立体视频。

代码分析

注意点

  1. VrPanoramaView//Google提供给我们现实全景图片的View
  2. Options//VrPanoramaView 所需的设置
  3. VrPanoramaEventListener//为 VrPanoramaView 设置监听
  4. loadImageFromBitmap//加载图片的主要方法

AndroidManifest文件


    android:launchMode="singleTask" 

布局文件

<com.google.vr.sdk.widgets.pano.VrPanoramaView
        android:id="@+id/pano_view"
        android:layout_width="match_parent"
        android:layout_height="250dip"
        android:layout_margin="5dip"
        android:scrollbars="@null"/>

Activity

public class SimpleVrPanoramaActivity extends Activity {

    private static final String TAG = "VrPanorama";
    private VrPanoramaView panoWidgetView;//上面说的Google提供给我们现实全景图片的View
    private String fileUri = "first.jpg";//assets文件夹下的文件名

    private Options panoOptions = new Options();//VrPanoramaView需要的设置
    private ImageLoaderTask backgroundImageLoaderTask;//异步加载图片

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);//布局上面贴了

        panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);//初始化VrPanoramaView
        panoWidgetView.setEventListener(new ActivityEventListener());//为VrPanoramaView添加监听

        //如果有任务在执行则停止它
        if (backgroundImageLoaderTask != null) {
            backgroundImageLoaderTask.cancel(true);
        }
         //设置inputType 为TYPE_STEREO_OVER_UNDER. 在后面会介绍TYPE_STEREO_OVER_UNDER的,暂时当做一个图片的显示类型就行
        panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;
        //创建一个任务
        backgroundImageLoaderTask = new ImageLoaderTask();
        //执行任务。将图片名(根据项目实际情况传吧)和设置传入
        backgroundImageLoaderTask.execute(Pair.create(fileUri, panoOptions));
    }
        //异步任务
    class ImageLoaderTask extends AsyncTask, Void, Boolean> {
        @Override
        protected Boolean doInBackground(Pair... fileInformation) {//真正写项目根据情况添加条件判断吧

            InputStream istr = null;
            try {
                istr = getAssets().open(fileInformation[0].first);//获取图片的输入流
            } catch (IOException e) {
                Log.e(TAG, "Could not decode default bitmap: " + e);
                return false;
            }

            Bitmap bitmap = BitmapFactory.decodeStream(istr);//创建bitmap
            panoWidgetView.loadImageFromBitmap(bitmap, fileInformation[0].second);//参数一为图片的bitmap,参数二为 VrPanoramaView 所需要的设置

            try {
                istr.close();//关闭InputStream
            } catch (IOException e) {
                Log.e(TAG, "Could not close input stream: " + e);
            }

            return true;
        }
    }

    private class ActivityEventListener extends VrPanoramaEventListener {

        @Override
        public void onLoadSuccess() {//图片加载成功
            Log.e(TAG, "onLoadSuccess");
        }


        @Override
        public void onLoadError(String errorMessage) {//图片加载失败
            Log.e(TAG, "Error loading pano: " + errorMessage);
        }

        @Override
        public void onClick() {//当我们点击了VrPanoramaView 时候出发
            super.onClick();
            Log.e(TAG, "onClick");
        }

        @Override
        public void onDisplayModeChanged(int newDisplayMode) {//改变显示模式时候出发(全屏模式和纸板模式)
            super.onDisplayModeChanged(newDisplayMode);
            Log.e(TAG, "onDisplayModeChanged");
        }
    }


    @Override
    protected void onPause() {
        panoWidgetView.pauseRendering();//暂停3D渲染和跟踪
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        panoWidgetView.resumeRendering();//恢复3D渲染和跟踪
    }

    @Override
    protected void onDestroy() {
        panoWidgetView.shutdown();//关闭渲染下并释放相关的内存

        if (backgroundImageLoaderTask != null) {
            backgroundImageLoaderTask.cancel(true);//停止异步任务
        }
        super.onDestroy();
    }
}

VrPanoramaView方法

显示模式默认情况下都是显示的有三个值

 1. embedded vr视图显示d为非全屏,嵌入客户端布局–1

 2. fullscreen_mono vr视图全屏显示为一个窗口–2

 3. fullscreen_stereo 以立体声模式全屏显示,每只眼睛有一个窗口–3

panoWidgetView.setDisplayMode(3);

是否显示全屏幕按钮
panoWidgetView.setFullscreenButtonEnabled(false);
是否显示信息按钮
panoWidgetView.setInfoButtonEnabled(false);
显示或隐藏按钮转换到立体声模式
panoWidgetView.setStereoModeButtonEnabled(false);
触摸平移是否启动
panoWidgetView.setTouchTrackingEnabled(false);

显示或隐藏用于提示用户将手机放入GVR查看器的过渡视图
panoWidgetView.setTransitionViewEnabled(false);

options


panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;

那么为什么要这样设置呢?先看官方对Options中标签的介绍:

public static final int TYPE_MONO = 1;

    图像被预期以覆盖沿着其水平轴360度,而垂直范围是根据图像的宽高比来计算。例如,如果一个1000x250像素的图像,给出所述全景将覆盖360x90度与垂直范围是-45至+45度。  

public static final int TYPE_STEREO_OVER_UNDER = 2;
    包含两个大小相等的投影 全景图垂直叠加。顶部图像被显示给左眼、底部图像被显示给右眼。//看下图你就懂了   

    图像将覆盖沿水平轴360度,而垂直范围是根据图像的宽高比来计算。例如,如果一个1000x500像素的图像中给出(即1000x250像素每个眼睛),全景将覆盖360x90度与垂直范围是-45至+45度。

Google VR Views实战(VR全景图播放器)_第1张图片

要显示的图片是下图这样的,所以就要设置为 ‘TYPE_STEREO_OVER_UNDER’

Google VR Views实战(VR全景图播放器)_第2张图片

那么什么样的图片设置为 ‘TYPE_MONO’ 呢?

Google VR Views实战(VR全景图播放器)_第3张图片

TYPE_STEREO_OVER_UNDER类型的图片每次切换模式时候 图片中间都会有一条垂直于水平线的分割线(很浅 很浅 然后逐渐消失),TYPE_MONO 就没有。

Options类中的代码也十分简单

public static class Options {
        private static final int TYPE_START_MARKER = 0;//起始标记
        public static final int TYPE_MONO = 1;
        public static final int TYPE_STEREO_OVER_UNDER = 2;
        private static final int TYPE_END_MARKER = 3;//结束标记
        public int inputType = 1;//默认为一

        public Options() {
        }

        void validate() {
            if(this.inputType <= 0 || this.inputType >= 3) {//标记错误处理
                String var10000 = VrPanoramaView.TAG;
                int var1 = this.inputType;
                Log.e(var10000, (new StringBuilder(38)).append("Invalid Options.inputType: ").append(var1).toString());
                this.inputType = 1;
            }

        }
    }

调皮的你如果在loadImageFromBitmap(bitmap,options)方法中 将options不小心设置为 null 了,也没关系。我在源码中我发现下面的代码,感觉挺温馨的

public void loadImageFromBitmap(Bitmap bitmap, VrPanoramaView.Options options) {
        //有木有那里暖暖的 ^_^
        if(options == null) {
            options = new VrPanoramaView.Options();
        } else {
            options.validate();
        }
    //重点不在这里 可以无视它
        this.renderer.loadImageFromBitmap(bitmap, options, this.eventListener);
    }

总结

  1. 导入google的库\
  2. 在相应的布局文件中引入控件 com.google.vr.sdk.widgets.pano.VrPanoramaView
  3. 初始化控件
  4. 为VrPanoramaView设置options
  5. 找到图片的Bitmap
  6. 调用VrPanoramaView
  7. loadImageFromBitmap方法
  8. 在onPause、onResume、onDestroy中做出相应处理

参考:
http://www.qingpingshan.com/rjbc/az/119129.html。
制作VR全景图播放器:(Google VR for Android)

https://developers.google.com/vr/android/samples/vrview

官方文档

你可能感兴趣的:(Android学习笔记)