Google VR for Android 开发入门

iwitcy 8年前
   <p>本文介绍了</p>    <ol>     <li> <p>Google官方的VR demo</p> </li>     <li> <p>全景图(PanoramaActivity)</p> </li>     <li> <p>360 视频</p> </li>     <li> <p>VR开发demo(源码:https://github.com/uncleleonfan/VRDemo)</p> </li>    </ol>    <h2>一.VR介绍</h2>    <h3>目前VR主流产品有:</h3>    <p>Google VR</p>    <p>Oculus</p>    <p>HTC Vivi </p>    <p>Google VR for Android 文档</p>    <p>支持DayDream和Cardboard</p>    <p>Github:https://github.com/googlevr/gvr-android-sdk</p>    <p>Document:https://developers.google.com/vr/android API Reference:https://developers.google.com/vr/android/reference_overview</p>    <h2>二. 官方Sample运行</h2>    <h3>1. SDK下载</h3>    <p>使用git命名下载或者直接在github上下载压缩包</p>    <pre>  <code class="language-java">git clone https://github.com/googlevr/gvr-android-sdk.git  </code></pre>    <h3>2. sdk导入</h3>    <p>导入gvr-android-sdk到Android Studio, 同步的过程中需要下载很多库所以会比较耗时,另外可能出现build失败的情况,这时可以尝试使用本地的gradle来编译。gradle版本最好为最新版本。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/451c76f77447cdd254515761304bfc3d.jpg"></p>    <h3>3.simplepanowidget</h3>    <p>simplepanowidget展示了印加文明遗迹马丘比丘的全景图(Panorama)</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/974562d1493f9b376ad54b84d69d790e.gif"></p>    <p>在真机上运行时,会有一个Cardboard选项。 </p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/93aae846445f6b8cdf7e14c8197e01cb.jpg"></p>    <p>点击上图红色框中的按钮即可进入Cardboard模式。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7e61e2c465f57114f651e59d396818bb.jpg"></p>    <p>Demo代码的主要逻辑就是加载一张全景图放入VrPanoramaView中。</p>    <pre>  <code class="language-java">panoOptions = new Options();  panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;    //图像类型为立体图像  istr = assetManager.open("andes.jpg");    //加载assets目录下的全景图  panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);</code></pre>    <p>全景图片andes是由两张图片组成,上面一张是给左眼看,下面一张是给右眼看。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fd2e365274d77e6ee36dee7e4295fb70.jpg"></p>    <p>图片类型</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fb11eb913f32a25eebcdee381d942551.jpg"></p>    <h3>4. simeplevideowidget</h3>    <p>simeplevideowidget展示了刚果雨林中大猩猩的360视频。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/52108049a525b2ea023e7478ed42f9f1.jpg"></p>    <p>Demo的核心代码是加载assets目录下的congo.mp4视频到VrVideoView中</p>    <pre>  <code class="language-java">videoWidgetView.loadVideoFromAsset("congo.mp4", options);  </code></pre>    <p>congo.mp4的视频内容也是分为上下部分,上面给左眼看,下面给右眼看。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/362a3313563a701afb96fae482faae25.jpg"></p>    <h3>5. treasurehunt</h3>    <p>treasurehunt展示了一个简单到离谱的寻宝游戏,当vr世界中矩形变成金黄色时,点击手机屏幕或者使用Daydream的控制器,即可完成寻宝。游戏还伴有音效。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/be223db8584f6bc5ba9e55f1b1abe5af.gif"></p>    <h3>6. controllerclient</h3>    <p>接收DayDream控制器输入示例</p>    <h3>7. videoplayer</h3>    <p>使用Asynchronous Reprojection播放视频示例</p>    <h2>三. 全景图(PanoramaActivity)</h2>    <h3>1. 配置build.gradle</h3>    <pre>  <code class="language-java">//修改minSDK为19   minSdkVersion 19    //添加依赖    compile 'com.google.vr:sdk-panowidget:1.20.0'   </code></pre>    <h3>2. 配置AndroidManifest.xml</h3>    <p>由于全景图占内存较大,当加载多张全景图时可能存在内存溢出的情况,所以这里开启largeHeap。</p>    <pre>  <code class="language-java"><application      android:largeHeap="true">  </application></code></pre>    <h3>3. 加载全景图</h3>    <pre>  <code class="language-java">private class LoadPanoramaImageTask extends AsyncTask<Void, Void, Bitmap> {        @Override      protected Bitmap doInBackground(Void... params) {          try {              //加载assets目录下的全景图片              AssetManager assetManager = getAssets();              InputStream open = assetManager.open("andes.jpg");              return BitmapFactory.decodeStream(open);          } catch (IOException e) {              e.printStackTrace();          }          return null;      }        @Override      protected void onPostExecute(Bitmap bitmap) {          VrPanoramaView.Options options = new VrPanoramaView.Options();          //图片类型为立体图像          options.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;          mVrPanoramaView.loadImageFromBitmap(bitmap, options);      }  }</code></pre>    <h3>4. 生命周期管理</h3>    <pre>  <code class="language-java">@Override  protected void onPause() {      mVrPanoramaView.pauseRendering();      super.onPause();      }    @Override  protected void onResume() {      super.onResume();      mVrPanoramaView.resumeRendering();  }    @Override  protected void onDestroy() {      // Destroy the widget and free memory.      mVrPanoramaView.shutdown();      // The background task has a 5 second timeout so it can potentially stay alive for 5 seconds      // after the activity is destroyed unless it is explicitly cancelled.      if (mLoadPanoramaImageTask != null) {          mLoadPanoramaImageTask.cancel(true);      }      super.onDestroy();  }</code></pre>    <h3>5. 事件监听</h3>    <pre>  <code class="language-java">mVrPanoramaView.setEventListener(mVrPanoramaEventListener);    private VrPanoramaEventListener mVrPanoramaEventListener = new VrPanoramaEventListener() {      /**       * 点击回调       */      @Override      public void onClick() {          super.onClick();      }        /**       * 加载数据成功回调       */      @Override      public void onLoadSuccess() {          super.onLoadSuccess();      }        /**       * 加载数据失败回调       */      @Override      public void onLoadError(String errorMessage) {          super.onLoadError(errorMessage);      }  };</code></pre>    <h2>四. 360 视频</h2>    <h3>1. 配置build.gradle</h3>    <pre>  <code class="language-java">//添加依赖  //minSdkVersion 19  //已经配置则忽略  compile 'com.google.vr:sdk-videowidget:1.20.0'</code></pre>    <h3>2. 配置AndroidManifest.xml (已经配置则忽略)</h3>    <pre>  <code class="language-java"><application      android:largeHeap="true">  </application></code></pre>    <h3>3. 加载视频</h3>    <pre>  <code class="language-java">VrVideoView.Options options = new VrVideoView.Options();    //视频类型为立体视频  options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;    try {      mVrVideoView.loadVideoFromAsset("congo.mp4", options);    } catch (IOException e) {      e.printStackTrace();  }</code></pre>    <h3>4. 绳命周期管理</h3>    <pre>  <code class="language-java">@Override  protected void onPause() {      super.onPause();      // Prevent the view from rendering continuously when in the background.      mVrVideoView.pauseRendering();      // If the video is playing when onPause() is called, the default behavior will be to pause      // the video and keep it paused when onResume() is called.      isPaused = true;  }    @Override  protected void onResume() {      super.onResume();      mVrVideoView.resumeRendering();  }    @Override  protected void onDestroy() {      // Destroy the widget and free memory.      mVrVideoView.shutdown();      super.onDestroy();  }</code></pre>    <h3>5. 事件监听</h3>    <pre>  <code class="language-java">private VrVideoEventListener mVrEventListener = new VrVideoEventListener() {        @Override      public void onLoadError(String errorMessage) {          Toast.makeText(VrVideoActivity.this, "onLoadError", Toast.LENGTH_SHORT).show();      }        @Override      public void onLoadSuccess() {          Toast.makeText(VrVideoActivity.this, "onLoadSuccess", Toast.LENGTH_SHORT).show();      }        @Override      public void onNewFrame() {      }        @Override      public void onCompletion() {          Toast.makeText(VrVideoActivity.this, "onCompletion", Toast.LENGTH_SHORT).show();          mVrVideoView.seekTo(0);//播放结束后重新开始播放      }        @Override      public void onClick() {          togglePause();//点击暂停或者播放      }};</code></pre>    <h2>五. Demo</h2>    <p>该Demo简单展示了全景图控件VrPanoramaView的使用,及其相关的基本的配置。 </p>    <h3>初始化VrPanoramaView</h3>    <pre>  <code class="language-java">private void initPanoramaView() {      mVrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_panorama_view);      //mVrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);//全屏模式,弹出一个全屏的Dialog      mVrPanoramaView.setInfoButtonEnabled(false);//隐藏信息按钮      mVrPanoramaView.setStereoModeButtonEnabled(false);//隐藏cardboard按钮      mVrPanoramaView.setFullscreenButtonEnabled(false);//隐藏全屏按钮      mUrl = getIntent().getStringExtra("url");      OkGo.get(mUrl).cacheKey(mUrl).tag(mUrl).execute(new BitmapCallback() {            @Override          public void onSuccess(Bitmap bitmap, Call call, Response response) {              VrPanoramaView.Options options = new VrPanoramaView.Options();              //设置图片类型为单通道图片              options.inputType = VrPanoramaView.Options.TYPE_MONO;              mVrPanoramaView.loadImageFromBitmap(bitmap, options);          }      });  }</code></pre>    <h3>初始化MediaPlayer</h3>    <pre>  <code class="language-java">/**   * 如果有音乐数据则播放音乐   */  private void initMediaPlayer() {      String mp3 = getIntent().getStringExtra("mp3");      if (mp3 != null) {          mMediaPlayer = new MediaPlayer();          try {              mMediaPlayer.setDataSource(this, Uri.parse(mp3));              mMediaPlayer.setOnPreparedListener(mOnPreparedListener);              mMediaPlayer.prepareAsync();          } catch (IOException e) {              e.printStackTrace();          }      }  }</code></pre>    <h3>生命周期管理</h3>    <pre>  <code class="language-java">@Override  protected void onResume() {      super.onResume();      mVrPanoramaView.resumeRendering();  }    @Override    protected void onPause() {      super.onPause();      mVrPanoramaView.pauseRendering();      if (mMediaPlayer != null) {          mMediaPlayer.pause();      }  }    @Override  protected void onDestroy() {      super.onDestroy();      mVrPanoramaView.shutdown();      OkGo.getInstance().cancelTag(mUrl);//取消请求      if (mMediaPlayer != null) {          mMediaPlayer.release();          mMediaPlayer = null;      }  }</code></pre>    <h2> </h2>    <p> </p>    <p> </p>    <p> </p>    <p>来自:http://mp.weixin.qq.com/s/mjOvJMQ_5Zy-LstduPA9Zg</p>    <p> </p>