Google VR全景图片与视频功能开发详解
1. VR開發概述
時下關于“谷歌、Android與VR”的各種言論紛飛。VR群里有人在爭論Android VR是不是一體機,是不是類似Android Wear、為VR打造的全新平臺,是不是改良后的Android N。
隨著vr設備的流行開來,各大招聘平臺上也發布了不少關于andorid vr開發相關的Android工程師崗位,從這點來說掌握vr在項目中的實際應用要點,有助于大家為自己的開發經驗上增加前沿技術的積累。
經過研發市面上的主流vr app 的功能,抽取并整合項目中的vr開發知識點,希望大家掌握后,在企業相關vr app游刃有余。
1.1 下載google vr sdk 并搭建開發環境
- 帶大家去github上搜索并下載google vr sdk
- 介紹sdk的組成部分與應用范圍
- 搭建一個基本android vr app的開發環境
1.2 CardBorad應用核心功能
- 帶大家查找本地vr 全景圖片資源
- 介紹vr全景圖與普通圖片的不同點
- 使用rv列表進行展示
- 使用VrPanoramaView控件進行本地全景圖片的展示
1.3 UtoVR應用核心功能
- 帶大家通過網絡請求獲取vr視頻的json數據
- 使用 Gson解析得到javaBean數據
- 使用VrVideoView控件進行網絡全景視圖的展示
以上這些功能是現流行的在線vr視頻,vr圖片相關app的核心功能。例如.vr管家應用,3d播播,discovery VR ,看房 vr等等熱門應用。
1.4 知識點
- http網絡請求技術
- Gson解析技術與gsonformat插件
- RecyclerView與cardView
- Glider流行圖片加載框架
- VrPanoramaView
- VrVideoView
1.5 好玩好用的VR
成本其實很便宜!教你用手機體驗VR魅力
- 17塊錢!把手機改造為VR眼鏡
- 好玩好用的VR APP推薦
2. 全景圖片顯示
2.1 搭建vr全景圖片的開發環境
VR開發需要gvr-android-sdk,GitHub下載地址
VR開發Google官方技術文檔
2.1.1 導入全景圖相關的三個開發庫
common,commonwidget,panowidget
PS:最新的SDK已經沒有這三個文件夾了,使用下一步的依賴庫即可
2.1.2 依賴該庫
compile 'com.google.vr:sdk-panowidget:1.30.0' //compile project(':common') //compile project(':commonwidget') //compile project(':panowidget') //google的一套序列化數據結構開發庫 //compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'2.1.3 準備全景圖片測試資源
放在assets目錄 例:assets/a.jpg(全景圖與普通圖片的不同 大,立體)
2.1.4 功能清單配置
android:largeHeap=”true” 全景圖片比較耗資源
<application android:largeHeap="true"> </application>2.2 布局全景控件顯示加載后的全景圖片
<com.google.vr.sdk.widgets.pano.VrPanoramaView android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/vr_pv" /> public class MainActivity extends AppCompatActivity {private VrPanoramaView vrPanoramaView;private ImageTask imageTask;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//全景圖片的瀏覽功能//步驟一。下載github上google開源 vr-sdk//1.1.導入到我們的工作空間 common,commonwidget panowidget//1.2.依賴到我們的項目中//1.3.依賴sdk中找不到的api//1.4.準備一些測試素材 放置在assets目錄下面 例:assets/a.jpg//1.5.開啟內存設置 android:largeHeap="true"盡可能使應用使用最大內存2.2.1 布局查找控件
//步驟二。布局全景控件顯示加載后的全景圖片 //2.1.布局查找控件 vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pv);2.2.2 設置初始化參數
//2.2.設置初始化參數 vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO); //刪除不需要連接,信息圖標 vrPanoramaView.setInfoButtonEnabled(false); //隱藏全屏按鈕 vrPanoramaView.setFullscreenButtonEnabled(false);2.2.3 創建異步任務加載圖片
Bitmap是圖片在內存中的表示對象,全景圖也可加載成bitmap
//2.3.創建異步任務加載圖片 Bitmap是圖片在內存中的表示對象,全景圖也可加載成bitmapimageTask = new ImageTask();imageTask.execute();} private class ImageTask extends AsyncTask<Void, Void, Bitmap> {@Overrideprotected Bitmap doInBackground(Void... params) {//2.4.從資產目錄打開一個流try {InputStream inputStream = getAssets().open("a.jpg");//2.5.使用BitmapFactory轉換成BitmapBitmap bitmap = BitmapFactory.decodeStream(inputStream);return bitmap;} catch (IOException e) {e.printStackTrace();}return null;}//2.6任務執行完后,可獲取Bitmap圖片@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);if (bitmap != null) {//loadImageFromBitmap加載bitmap到顯示控件 參1.bitmap 參2 顯示參數的封裝VrPanoramaView.Options options = new VrPanoramaView.Options();//加載立體圖片,上部分顯示在左眼,下部分顯示在右眼options.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;if (listener == null) {listener = new VrPanoramaEventListener() {@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);//處理加載失敗的情況Toast.makeText(MainActivity.this, "錯誤消息:" + errorMessage, Toast.LENGTH_SHORT).show();}@Overridepublic void onLoadSuccess() {super.onLoadSuccess();//成功的情況提示下現在要進行全景圖片的展示Toast.makeText(MainActivity.this, "進入vr:", Toast.LENGTH_SHORT).show();}};// 增加加載出錯的業務邏輯處理vrPanoramaView.setEventListener(listener);}//2.7.讓控件加載bitmap對象vrPanoramaView.loadImageFromBitmap(bitmap, options);//2.8.如果loadImageFromBitmap加載失敗需要提示用戶相關信息則需要添加事件監聽器listener}} } private VrPanoramaEventListener listener;2.3 VrPanoramaView控件退到后臺,回到屏幕,銷毀處理細節
//步驟三。VrPanoramaView控件退到后臺,回到屏幕,銷毀處理細節//3.1.退到后臺.暫停顯示@Overrideprotected void onPause() {super.onPause();if (vrPanoramaView != null) {vrPanoramaView.pauseRendering();}}//3.2.回到屏幕,恢復顯示@Overrideprotected void onResume() {super.onResume();if (vrPanoramaView != null) {vrPanoramaView.resumeRendering();}}//3.3.退出界面停止顯示@Overrideprotected void onDestroy() {if (vrPanoramaView != null) {vrPanoramaView.shutdown();}if (imageTask != null && !imageTask.isCancelled()) {//銷毀任務imageTask.cancel(true);imageTask = null;}super.onDestroy();} } package com.itheima.demovrimagevideo2;import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast;import com.google.vr.sdk.widgets.common.VrWidgetView; import com.google.vr.sdk.widgets.pano.VrPanoramaEventListener; import com.google.vr.sdk.widgets.pano.VrPanoramaView;import java.io.IOException; import java.io.InputStream;public class MainActivity extends AppCompatActivity {private VrPanoramaView vrPanoramaView;private ImageTask imageTask;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//全景圖片的瀏覽功能//步驟一。下載github上google開源 vr-sdk//1.1.導入到我們的工作空間 common,commonwidget panowidget//1.2.依賴到我們的項目中//1.3.依賴sdk中找不到的api//1.4.準備一些測試素材 放置在assets目錄下面 例:assets/a.jpg//1.5.開啟內存設置 android:largeHeap="true"盡可能使應用使用最大內存//步驟二。將全景圖片加載到內存中,再顯示在控件//2.1.布局全景圖片顯示控件vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pano);//刪除不需要連接vrPanoramaView.setInfoButtonEnabled(false);//隱藏全屏按鈕vrPanoramaView.setFullscreenButtonEnabled(false);//2.2.所有的圖片在內存表示成BitmapimageTask = new ImageTask();imageTask.execute();//vrPanoramaView.loadImageFromBitmap(bitmap);}//2.3.AsyncTask異步加載private class ImageTask extends AsyncTask<Void, Void, Bitmap> {@Overrideprotected Bitmap doInBackground(Void... params) {try {InputStream inputStream = getAssets().open("a.jpg");//2.4.使用BitmapFactory 可以sd ,byte[] inputstream-->BitmapBitmap bitmap = BitmapFactory.decodeStream(inputStream);return bitmap;} catch (IOException e) {e.printStackTrace();}return null;}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);if (bitmap != null) {//loadImageFromBitmap加載bitmap到顯示控件 參1.bitmap 參2 顯示參數的封裝VrPanoramaView.Options option = new VrPanoramaView.Options();//立體圖片:上半張顯示在左眼,下半張顯示在右眼option.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;VrPanoramaEventListener listener=new VrPanoramaEventListener(){@Overridepublic void onLoadSuccess() {super.onLoadSuccess();//成功的情況提示下現在要進行全景圖片的展示Toast.makeText(MainActivity.this, "進入vr圖片", Toast.LENGTH_SHORT).show();}@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);//處理加載失敗的情況Toast.makeText(MainActivity.this, "E:"+errorMessage, Toast.LENGTH_SHORT).show();}};//2.5.增加加載出錯的業務邏輯處理vrPanoramaView.setEventListener(listener);//2.6.全屏展示vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);//2.4.加載bitmap到控件上顯示vrPanoramaView.loadImageFromBitmap(bitmap, option);}}}//步驟三。優化程序細節 ,頁面退到后臺,暫停顯示 ,頁面顯示在屏幕 恢復顯示。銷毀頁面,釋放全景圖片//3.1 頁面退到后臺,暫停顯示@Overrideprotected void onPause() {super.onPause();if(vrPanoramaView!=null){vrPanoramaView.pauseRendering();}}//3.2 頁面顯示在屏幕 恢復顯示@Overrideprotected void onResume() {super.onResume();if(vrPanoramaView!=null){vrPanoramaView.resumeRendering();}}//3.3.銷毀頁面,釋放全景圖片@Overrideprotected void onDestroy() {super.onDestroy();if (vrPanoramaView != null) {vrPanoramaView.shutdown();}if (imageTask != null && !imageTask.isCancelled()) {imageTask.cancel(true);imageTask = null;}} }3. 全景視頻顯示開發
3.1 vr視頻環境搭建
- 導入需要的三個庫 common,comonwidget.videowiget
- 依賴這三個庫
- 準備顯示使用到全景視頻 assets目錄下面 例:assets/b.mp4
- 配置大內存選項 android:largeHeap=”true” 可以使用最大內存
3.1.1 導入vr sdk 中的相關庫
common,commonwidget,videowidget
PS:最新的SDK已經沒有這三個文件夾了,使用下一步的依賴庫即可
3.1.2 依賴以上三個庫
compile 'com.google.vr:sdk-videowidget:1.30.0' //compile project(':common') //compile project(':commonwidget') //compile project(':videowidget') // 出現類未定義錯誤的缺少庫 //compile 'com.google.android.exoplayer:exoplayer:r1.5.10' //compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'3.1.3 打開內存設置 android:largeHeap=”true”
<application android:largeHeap="true"> </application>3.1.4 準備測試使用的全景視頻
放置在assets目錄 例:assets/congo_2048.mp4
3.2 布局視頻控件,并加載視頻內容
public class MainActivity extends AppCompatActivity {private VrVideoView vrVideoView;private VideoTask videoTask;private SeekBar seekBar;private TextView text;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//步驟一。搭建vr全景視頻的開發環境//1.1.導入需要的三個庫 common,comonwidget.videowiget//1.2.依賴這三個庫//1.3.準備顯示使用到全景視頻 assets目錄下面 例:assets/b.mp4//1.4.配置大內存選項 android:largeHeap="true" 可以使用最大內存//步驟二。布局視頻控件,并加載視頻內容//2.1布局控件//2.2查找控件vrVideoView = (VrVideoView) findViewById(R.id.vr_vv);//2.3加載視頻數據videoTask = new VideoTask();videoTask.execute("congo_2048.mp4");}// 創建異步任務防止占用主線程private class VideoTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... params) {// 把文件名取出來進行加載 視頻資源來自asssetsVrVideoView.Options options = new VrVideoView.Options();//2.4.輸入模式//立體模式options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;//2.5.設置視頻來源//處理視頻加載的格式(sd卡或者assets)//options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;//FORMAT_DEFAULT 視頻資源來自assetss/sd//FORMAT_HLS 視頻來自網絡流媒 直播//處理視頻加載的格式 流媒體直播格式options.inputFormat=VrVideoView.Options.FORMAT_HLS;try {//2.8 如果資源有問題,不能正常播放需要處理下界面提示if (listener == null) {listener = new VrVideoEventListener() {@Overridepublic void onLoadSuccess() {super.onLoadSuccess();//獲取當前總時長long max=vrVideoView.getDuration();seekBar.setMax((int) max);seekBar.setProgress(0);Toast.makeText(MainActivity.this, "準備播放vr", Toast.LENGTH_SHORT).show();}@Overridepublic void onNewFrame() {super.onNewFrame();//獲取當前播放位置long currentPosition = vrVideoView.getCurrentPosition();//設置當前進度seekBar.setProgress((int) currentPosition);//時間值String total=String.format("%.2f",vrVideoView.getDuration()/1000f);String curr=String.format("%.2f",vrVideoView.getCurrentPosition()/1000f);text.setText("播放進度"+curr+":"+total);}private boolean isPause=true;@Overridepublic void onCompletion() {super.onCompletion();seekBar.setProgress(0);vrVideoView.seekTo(0);//重回0位置vrVideoView.pauseVideo();//暫停播放isPause=true;//保存暫停狀態}@Overridepublic void onClick() {super.onClick();if (isPause) {//播放vrVideoView.playVideo();isPause=false;} else {vrVideoView.pauseVideo();isPause=true;}}@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);Toast.makeText(MainActivity.this, "加載失敗", Toast.LENGTH_SHORT).show();}};vrVideoView.setEventListener(listener);}//2.7加載視頻資源//vrVideoView.loadVideoFromAsset(params[0], options);String url="http://youkesvideo.oss-cn-hangzhou.aliyuncs.com/movie2/2016/10/11/%E6%B9%84%E5%85%AC%E6%B2%B3%E8%A1%8C%E5%8A%A8.Operation.Mekong.2016.TC720P.X264.AAC.Mandarin.CHS.Mp4Ba.mp4";vrVideoView.loadVideo(Uri.parse(url),options);} catch (IOException e) {e.printStackTrace();}return null;}}private VrVideoEventListener listener;3.3 處理頁面退到后臺,回到屏幕,頁面銷毀
//步驟三。處理頁面退到后臺,回到屏幕,頁面銷毀。//3.1.頁面退到后臺暫停視頻@Overrideprotected void onPause() {super.onPause();if (vrVideoView != null) {vrVideoView.pauseRendering();}}//3.2.頁面回到屏幕繼續播放@Overrideprotected void onResume() {super.onResume();if (vrVideoView != null) {vrVideoView.resumeRendering();}}//3.3.頁面銷毀@Overrideprotected void onDestroy() {super.onDestroy();if (vrVideoView != null) {vrVideoView.shutdown();}if (videoTask != null && !videoTask.isCancelled()) {videoTask.cancel(false);videoTask = null;}} }3.4 添加進度條相關事件
3.4.1布局查找出控件
<LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><SeekBar android:id="@+id/seek_bar"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextView android:id="@+id/text"android:background="#AEAEAE"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:textColor="#FFFFFF"android:textSize="22sp"android:text="00:00" /> </LinearLayout> seekBar = (SeekBar) findViewById(R.id.seek_bar); text = (TextView) findViewById(R.id.text);3.4.2.加載成功設置最大值
在VrVideoEventListener中的onLoadSuccess處理
3.4.3.在播放過程中不斷更新
進度值 onNewFrame 每播放一個畫面就調用該方法一次
3.4.4.同步理新文本時間值
在VrVideoEventListener中的onNewFrame處理
3.4.5.播放完成重新播放
在VrVideoEventListener中的onCompletion處理
package com.itheima.appvideo;import android.os.AsyncTask; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast;import com.google.vr.sdk.widgets.common.VrWidgetView; import com.google.vr.sdk.widgets.video.VrVideoEventListener; import com.google.vr.sdk.widgets.video.VrVideoView;import java.io.IOException;public class MainActivity extends AppCompatActivity {private VrVideoView vrVideoView;private VideoTask task;private SeekBar seekBar;private TextView timeText;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//步驟一。搭建vr全景視頻的開發環境//1.1.導入需要的三個庫 common,comonwidget.videowiget//1.2.依賴這三個庫//1.3.準備顯示使用到全景視頻 assets目錄下面 例:assets/b.mp4//1.4.配置大內存選項 android:largeHeap="true" 可以使用最大內存//步驟二。加載視頻到內存中,再使用控件顯示//2.1 布局全景視頻控件vrVideoView = (VrVideoView) findViewById(R.id.vr_video_view);//2.2加載全景視頻task = new VideoTask();task.execute("b.mp4");seekBar = (SeekBar) findViewById(R.id.seekbar);timeText = (TextView) findViewById(R.id.time);}//2.2.1創建異步任務防止占用主線程private class VideoTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... params) {//2.2.2.把文件名取出來進行加載 視頻資源來自asssetsVrVideoView.Options options = new VrVideoView.Options();//立體的視頻資源:上半畫面顯示在左眼,下半畫面顯示右眼options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;//FORMAT_DEFAULT 視頻資源來自assetss/sd//FORMAT_HLS 視頻來自網絡流媒 直播options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;try {//步驟四.編寫進度顯示 業務邏輯VrVideoEventListener listener = new VrVideoEventListener() {//4.1.加載成功@Overridepublic void onLoadSuccess() {super.onLoadSuccess();Toast.makeText(MainActivity.this, "準備放3d視頻", Toast.LENGTH_SHORT).show();upProgress();}//4.2加載失敗的提示@Overridepublic void onLoadError(String errorMessage) {super.onLoadError(errorMessage);Toast.makeText(MainActivity.this, "視頻加載失敗" + errorMessage, Toast.LENGTH_SHORT).show();}//4.3.顯示播放時長與播放進度//4.3.1.布局顯示控件SeekBar 與TextView//4.3.2.查找出來//4.3.3.在onLoadSuccess里面獲取視頻時長 視頻播放位置//4.3.4.在onNewFrame 不斷獲取最新的進度值來更新界面@Override//播放了一個畫面,onNewFrame就被調用次public void onNewFrame() {super.onNewFrame();upProgress();}private boolean isPause = false;//4.4.處理播放完成@Overridepublic void onCompletion() {super.onCompletion();vrVideoView.seekTo(0);vrVideoView.pauseVideo();isPause = true;upProgress();}//4.5.點擊業務@Overridepublic void onClick() {super.onClick();if (isPause) {isPause = false;vrVideoView.playVideo();} else {isPause = true;vrVideoView.pauseVideo();}}};vrVideoView.setEventListener(listener);vrVideoView.loadVideoFromAsset(params[0], options);//參1文件名 參2 設置參數} catch (IOException e) {e.printStackTrace();}return null;}private void upProgress() {long max = vrVideoView.getDuration();long currPosition = vrVideoView.getCurrentPosition();seekBar.setMax((int) max);seekBar.setProgress((int) currPosition);timeText.setText(String.format("%.2f", currPosition / 1000f) + "/" + String.format("%.2f", max / 1000f));}}//步驟三。程序優化 頁面退到后臺,暫停 頁面回到屏幕繼續播放 頁面銷毀 關閉//3.1. 頁面退到后臺,暫停@Overrideprotected void onPause() {super.onPause();if (vrVideoView != null) {vrVideoView.pauseRendering();}}//3.2 頁面回到屏幕繼續播放@Overrideprotected void onResume() {super.onResume();if (vrVideoView != null) {vrVideoView.resumeRendering();}}//3.3. 頁面銷毀 關閉銷毀@Overrideprotected void onDestroy() {super.onDestroy();if (vrVideoView != null) {vrVideoView.shutdown();}if (task != null && !task.isCancelled()) {task.cancel(true);task = null;}} }GitHub:https://github.com/JackChen1999/GoogleVR
總結
以上是生活随笔為你收集整理的Google VR全景图片与视频功能开发详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++在Android开发中的应用
- 下一篇: 苹果核 - 页面动态化的基础 —— Ta