Google VR全景图片与视频功能开发详解
1. VR開發(fā)概述
時(shí)下關(guān)于“谷歌、Android與VR”的各種言論紛飛。VR群里有人在爭論Android VR是不是一體機(jī),是不是類似Android Wear、為VR打造的全新平臺,是不是改良后的Android N。
隨著vr設(shè)備的流行開來,各大招聘平臺上也發(fā)布了不少關(guān)于andorid vr開發(fā)相關(guān)的Android工程師崗位,從這點(diǎn)來說掌握vr在項(xiàng)目中的實(shí)際應(yīng)用要點(diǎn),有助于大家為自己的開發(fā)經(jīng)驗(yàn)上增加前沿技術(shù)的積累。
經(jīng)過研發(fā)市面上的主流vr app 的功能,抽取并整合項(xiàng)目中的vr開發(fā)知識點(diǎn),希望大家掌握后,在企業(yè)相關(guān)vr app游刃有余。
1.1 下載google vr sdk 并搭建開發(fā)環(huán)境
- 帶大家去github上搜索并下載google vr sdk
- 介紹sdk的組成部分與應(yīng)用范圍
- 搭建一個(gè)基本android vr app的開發(fā)環(huán)境
1.2 CardBorad應(yīng)用核心功能
- 帶大家查找本地vr 全景圖片資源
- 介紹vr全景圖與普通圖片的不同點(diǎn)
- 使用rv列表進(jìn)行展示
- 使用VrPanoramaView控件進(jìn)行本地全景圖片的展示
1.3 UtoVR應(yīng)用核心功能
- 帶大家通過網(wǎng)絡(luò)請求獲取vr視頻的json數(shù)據(jù)
- 使用 Gson解析得到j(luò)avaBean數(shù)據(jù)
- 使用VrVideoView控件進(jìn)行網(wǎng)絡(luò)全景視圖的展示
以上這些功能是現(xiàn)流行的在線vr視頻,vr圖片相關(guān)app的核心功能。例如.vr管家應(yīng)用,3d播播,discovery VR ,看房 vr等等熱門應(yīng)用。
1.4 知識點(diǎn)
- http網(wǎng)絡(luò)請求技術(shù)
- Gson解析技術(shù)與gsonformat插件
- RecyclerView與cardView
- Glider流行圖片加載框架
- VrPanoramaView
- VrVideoView
1.5 好玩好用的VR
成本其實(shí)很便宜!教你用手機(jī)體驗(yàn)VR魅力
- 17塊錢!把手機(jī)改造為VR眼鏡
- 好玩好用的VR APP推薦
2. 全景圖片顯示
2.1 搭建vr全景圖片的開發(fā)環(huán)境
VR開發(fā)需要gvr-android-sdk,GitHub下載地址
VR開發(fā)Google官方技術(shù)文檔
2.1.1 導(dǎo)入全景圖相關(guān)的三個(gè)開發(fā)庫
common,commonwidget,panowidget
PS:最新的SDK已經(jīng)沒有這三個(gè)文件夾了,使用下一步的依賴庫即可
2.1.2 依賴該庫
compile 'com.google.vr:sdk-panowidget:1.30.0' //compile project(':common') //compile project(':commonwidget') //compile project(':panowidget') //google的一套序列化數(shù)據(jù)結(jié)構(gòu)開發(fā)庫 //compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'2.1.3 準(zhǔn)備全景圖片測試資源
放在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.導(dǎo)入到我們的工作空間 common,commonwidget panowidget//1.2.依賴到我們的項(xiàng)目中//1.3.依賴sdk中找不到的api//1.4.準(zhǔn)備一些測試素材 放置在assets目錄下面 例:assets/a.jpg//1.5.開啟內(nèi)存設(shè)置 android:largeHeap="true"盡可能使應(yīng)用使用最大內(nèi)存2.2.1 布局查找控件
//步驟二。布局全景控件顯示加載后的全景圖片 //2.1.布局查找控件 vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pv);2.2.2 設(shè)置初始化參數(shù)
//2.2.設(shè)置初始化參數(shù) vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO); //刪除不需要連接,信息圖標(biāo) vrPanoramaView.setInfoButtonEnabled(false); //隱藏全屏按鈕 vrPanoramaView.setFullscreenButtonEnabled(false);2.2.3 創(chuàng)建異步任務(wù)加載圖片
Bitmap是圖片在內(nèi)存中的表示對象,全景圖也可加載成bitmap
//2.3.創(chuàng)建異步任務(wù)加載圖片 Bitmap是圖片在內(nèi)存中的表示對象,全景圖也可加載成bitmapimageTask = new ImageTask();imageTask.execute();} private class ImageTask extends AsyncTask<Void, Void, Bitmap> {@Overrideprotected Bitmap doInBackground(Void... params) {//2.4.從資產(chǎn)目錄打開一個(gè)流try {InputStream inputStream = getAssets().open("a.jpg");//2.5.使用BitmapFactory轉(zhuǎn)換成BitmapBitmap bitmap = BitmapFactory.decodeStream(inputStream);return bitmap;} catch (IOException e) {e.printStackTrace();}return null;}//2.6任務(wù)執(zhí)行完后,可獲取Bitmap圖片@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);if (bitmap != null) {//loadImageFromBitmap加載bitmap到顯示控件 參1.bitmap 參2 顯示參數(shù)的封裝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, "錯(cuò)誤消息:" + errorMessage, Toast.LENGTH_SHORT).show();}@Overridepublic void onLoadSuccess() {super.onLoadSuccess();//成功的情況提示下現(xiàn)在要進(jìn)行全景圖片的展示Toast.makeText(MainActivity.this, "進(jìn)入vr:", Toast.LENGTH_SHORT).show();}};// 增加加載出錯(cuò)的業(yè)務(wù)邏輯處理vrPanoramaView.setEventListener(listener);}//2.7.讓控件加載bitmap對象vrPanoramaView.loadImageFromBitmap(bitmap, options);//2.8.如果loadImageFromBitmap加載失敗需要提示用戶相關(guān)信息則需要添加事件監(jiān)聽器listener}} } private VrPanoramaEventListener listener;2.3 VrPanoramaView控件退到后臺,回到屏幕,銷毀處理細(xì)節(jié)
//步驟三。VrPanoramaView控件退到后臺,回到屏幕,銷毀處理細(xì)節(jié)//3.1.退到后臺.暫停顯示@Overrideprotected void onPause() {super.onPause();if (vrPanoramaView != null) {vrPanoramaView.pauseRendering();}}//3.2.回到屏幕,恢復(fù)顯示@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()) {//銷毀任務(wù)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.導(dǎo)入到我們的工作空間 common,commonwidget panowidget//1.2.依賴到我們的項(xiàng)目中//1.3.依賴sdk中找不到的api//1.4.準(zhǔn)備一些測試素材 放置在assets目錄下面 例:assets/a.jpg//1.5.開啟內(nèi)存設(shè)置 android:largeHeap="true"盡可能使應(yīng)用使用最大內(nèi)存//步驟二。將全景圖片加載到內(nèi)存中,再顯示在控件//2.1.布局全景圖片顯示控件vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_pano);//刪除不需要連接vrPanoramaView.setInfoButtonEnabled(false);//隱藏全屏按鈕vrPanoramaView.setFullscreenButtonEnabled(false);//2.2.所有的圖片在內(nèi)存表示成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 顯示參數(shù)的封裝VrPanoramaView.Options option = new VrPanoramaView.Options();//立體圖片:上半張顯示在左眼,下半張顯示在右眼option.inputType = VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER;VrPanoramaEventListener listener=new VrPanoramaEventListener(){@Overridepublic void onLoadSuccess() {super.onLoadSuccess();//成功的情況提示下現(xiàn)在要進(jìn)行全景圖片的展示Toast.makeText(MainActivity.this, "進(jìn)入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.增加加載出錯(cuò)的業(yè)務(wù)邏輯處理vrPanoramaView.setEventListener(listener);//2.6.全屏展示vrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_MONO);//2.4.加載bitmap到控件上顯示vrPanoramaView.loadImageFromBitmap(bitmap, option);}}}//步驟三。優(yōu)化程序細(xì)節(jié) ,頁面退到后臺,暫停顯示 ,頁面顯示在屏幕 恢復(fù)顯示。銷毀頁面,釋放全景圖片//3.1 頁面退到后臺,暫停顯示@Overrideprotected void onPause() {super.onPause();if(vrPanoramaView!=null){vrPanoramaView.pauseRendering();}}//3.2 頁面顯示在屏幕 恢復(fù)顯示@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. 全景視頻顯示開發(fā)
3.1 vr視頻環(huán)境搭建
- 導(dǎo)入需要的三個(gè)庫 common,comonwidget.videowiget
- 依賴這三個(gè)庫
- 準(zhǔn)備顯示使用到全景視頻 assets目錄下面 例:assets/b.mp4
- 配置大內(nèi)存選項(xiàng) android:largeHeap=”true” 可以使用最大內(nèi)存
3.1.1 導(dǎo)入vr sdk 中的相關(guān)庫
common,commonwidget,videowidget
PS:最新的SDK已經(jīng)沒有這三個(gè)文件夾了,使用下一步的依賴庫即可
3.1.2 依賴以上三個(gè)庫
compile 'com.google.vr:sdk-videowidget:1.30.0' //compile project(':common') //compile project(':commonwidget') //compile project(':videowidget') // 出現(xiàn)類未定義錯(cuò)誤的缺少庫 //compile 'com.google.android.exoplayer:exoplayer:r1.5.10' //compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'3.1.3 打開內(nèi)存設(shè)置 android:largeHeap=”true”
<application android:largeHeap="true"> </application>3.1.4 準(zhǔn)備測試使用的全景視頻
放置在assets目錄 例:assets/congo_2048.mp4
3.2 布局視頻控件,并加載視頻內(nèi)容
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全景視頻的開發(fā)環(huán)境//1.1.導(dǎo)入需要的三個(gè)庫 common,comonwidget.videowiget//1.2.依賴這三個(gè)庫//1.3.準(zhǔn)備顯示使用到全景視頻 assets目錄下面 例:assets/b.mp4//1.4.配置大內(nèi)存選項(xiàng) android:largeHeap="true" 可以使用最大內(nèi)存//步驟二。布局視頻控件,并加載視頻內(nèi)容//2.1布局控件//2.2查找控件vrVideoView = (VrVideoView) findViewById(R.id.vr_vv);//2.3加載視頻數(shù)據(jù)videoTask = new VideoTask();videoTask.execute("congo_2048.mp4");}// 創(chuàng)建異步任務(wù)防止占用主線程private class VideoTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... params) {// 把文件名取出來進(jìn)行加載 視頻資源來自asssetsVrVideoView.Options options = new VrVideoView.Options();//2.4.輸入模式//立體模式options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;//2.5.設(shè)置視頻來源//處理視頻加載的格式(sd卡或者assets)//options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;//FORMAT_DEFAULT 視頻資源來自assetss/sd//FORMAT_HLS 視頻來自網(wǎng)絡(luò)流媒 直播//處理視頻加載的格式 流媒體直播格式options.inputFormat=VrVideoView.Options.FORMAT_HLS;try {//2.8 如果資源有問題,不能正常播放需要處理下界面提示if (listener == null) {listener = new VrVideoEventListener() {@Overridepublic void onLoadSuccess() {super.onLoadSuccess();//獲取當(dāng)前總時(shí)長long max=vrVideoView.getDuration();seekBar.setMax((int) max);seekBar.setProgress(0);Toast.makeText(MainActivity.this, "準(zhǔn)備播放vr", Toast.LENGTH_SHORT).show();}@Overridepublic void onNewFrame() {super.onNewFrame();//獲取當(dāng)前播放位置long currentPosition = vrVideoView.getCurrentPosition();//設(shè)置當(dāng)前進(jìn)度seekBar.setProgress((int) currentPosition);//時(shí)間值String total=String.format("%.2f",vrVideoView.getDuration()/1000f);String curr=String.format("%.2f",vrVideoView.getCurrentPosition()/1000f);text.setText("播放進(jìn)度"+curr+":"+total);}private boolean isPause=true;@Overridepublic void onCompletion() {super.onCompletion();seekBar.setProgress(0);vrVideoView.seekTo(0);//重回0位置vrVideoView.pauseVideo();//暫停播放isPause=true;//保存暫停狀態(tài)}@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.頁面回到屏幕繼續(xù)播放@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 添加進(jìn)度條相關(guān)事件
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.加載成功設(shè)置最大值
在VrVideoEventListener中的onLoadSuccess處理
3.4.3.在播放過程中不斷更新
進(jìn)度值 onNewFrame 每播放一個(gè)畫面就調(diào)用該方法一次
3.4.4.同步理新文本時(shí)間值
在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全景視頻的開發(fā)環(huán)境//1.1.導(dǎo)入需要的三個(gè)庫 common,comonwidget.videowiget//1.2.依賴這三個(gè)庫//1.3.準(zhǔn)備顯示使用到全景視頻 assets目錄下面 例:assets/b.mp4//1.4.配置大內(nèi)存選項(xiàng) android:largeHeap="true" 可以使用最大內(nèi)存//步驟二。加載視頻到內(nèi)存中,再使用控件顯示//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創(chuàng)建異步任務(wù)防止占用主線程private class VideoTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... params) {//2.2.2.把文件名取出來進(jìn)行加載 視頻資源來自asssetsVrVideoView.Options options = new VrVideoView.Options();//立體的視頻資源:上半畫面顯示在左眼,下半畫面顯示右眼options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;//FORMAT_DEFAULT 視頻資源來自assetss/sd//FORMAT_HLS 視頻來自網(wǎng)絡(luò)流媒 直播options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;try {//步驟四.編寫進(jìn)度顯示 業(yè)務(wù)邏輯VrVideoEventListener listener = new VrVideoEventListener() {//4.1.加載成功@Overridepublic void onLoadSuccess() {super.onLoadSuccess();Toast.makeText(MainActivity.this, "準(zhǔn)備放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.顯示播放時(shí)長與播放進(jìn)度//4.3.1.布局顯示控件SeekBar 與TextView//4.3.2.查找出來//4.3.3.在onLoadSuccess里面獲取視頻時(shí)長 視頻播放位置//4.3.4.在onNewFrame 不斷獲取最新的進(jìn)度值來更新界面@Override//播放了一個(gè)畫面,onNewFrame就被調(diào)用次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.點(diǎn)擊業(yè)務(wù)@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 設(shè)置參數(shù)} 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));}}//步驟三。程序優(yōu)化 頁面退到后臺,暫停 頁面回到屏幕繼續(xù)播放 頁面銷毀 關(guān)閉//3.1. 頁面退到后臺,暫停@Overrideprotected void onPause() {super.onPause();if (vrVideoView != null) {vrVideoView.pauseRendering();}}//3.2 頁面回到屏幕繼續(xù)播放@Overrideprotected void onResume() {super.onResume();if (vrVideoView != null) {vrVideoView.resumeRendering();}}//3.3. 頁面銷毀 關(guān)閉銷毀@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
總結(jié)
以上是生活随笔為你收集整理的Google VR全景图片与视频功能开发详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++在Android开发中的应用
- 下一篇: 苹果核 - 页面动态化的基础 —— Ta