Android實現VR全景立體化顯示以及優化
阿新 • • 發佈:2019-01-04
實現效果圖:
提示:1.由於用虛擬機器測試,本圖片有部分功能不能顯示,建議大家用真機測試。給你不一樣的體驗 2.最下方附有主頁程式碼; 實現步驟: 1.谷歌官網提供的VR資源下載
2.因為使用VR的資源很小號記憶體,所以我們為了避免OOM的問題,在清單檔案中新增 android:largeHeap="true",提高警報線。 清單檔案程式碼: <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> 3.由於低版本要用高版本的東西,在Gradle檔案中新增 compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7' 4.匯入三個庫檔案common,commonwidget,panowidget 目錄為gvr-android-sdk-master\libraries下的三個檔案
再新增到moudle中,Ctrl+Alt+Shift+S,選擇你的moudle,點選右上角加號,匯入需要的庫檔案;
5.編譯構造版本太低,2.0後的studio沒辦法匯入此model.
會爆出這個異常,解決的辦法是進入檔案裡,修改build.gradle檔案
6.在佈局檔案中新增VR控制元件: 程式碼: <com.google.vr.sdk.widgets.pano.VrPanoramaView android:id="@+id/vr" android:layout_width="match_parent" android:layout_height="match_parent"></com.google.vr.sdk.widgets.pano.VrPanoramaView> 7.初始化VrPanoramaView控制元件
8.在src資料夾下的main資料夾下建立一個資產檔案assets,存放VR圖片;
9.由於VR資源資料量大,獲取需要時間,故把載入圖片放到子執行緒中進行,主執行緒來顯示圖片,可以使用一個非同步執行緒AsyncTask或EventBus技術完成; (1)建立一個子執行緒,繼承自AsyncTask<Void,Void,Bitmap>,並建立複寫方法; (2)在建立的複寫方法在子執行緒進行,從本地檔案中把資源載入到內容分中,從資產目錄中拿到資源,返回的結果是位元組流,把位元組流轉換為Bitmap物件;並返回Bitmap物件 (3)把複寫的方法執行在主執行緒中,建立onPostExecute()方法接收;使用VR的控制元件物件顯示效果 程式碼: private class ImagerLoaderTask extends AsyncTask<Void,Void,Bitmap>{ @Override protected Bitmap doInBackground(Void... params) { try { //從資產目錄中拿到資源,返回的結果是位元組流; InputStream inputStream = getAssets().open("andes.jpg"); //把位元組流轉換唄Bitmap物件; Bitmap bitmap = BitmapFactory.decodeStream(inputStream); return bitmap; } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap bitmap) { //建立VrPanoramaView.options,去決定顯示VR是普通效果還是立體效果; VrPanoramaView.Options options = new VrPanoramaView.Options(); //TYPE_STEREO_OVER_UNDER立體效果,就是圖片的上半部分放在左眼顯示,下半部分放在右眼顯示; //TYPE_MONO 普通效果; options.inputType= VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER; //使用VR控制元件物件,顯示效果 需要兩個引數1.Bitmap物件2.VrPanoramaView.options; mVrPanoramaView.loadImageFromBitmap(bitmap,options); super.onPostExecute(bitmap); } } 10.在Main方法中使用自定義的AsyncTask,播放VR效果 ImagerLoaderTask imagerLoaderTask = new ImagerLoaderTask(); imagerLoaderTask.execute(); 11.優化VR,因為VR很佔用記憶體,所以當介面進入onPause狀態,暫停VR檢視顯示,進入onResume狀態,繼續VR檢視顯示,進入onDestroy狀態,殺死VR,關閉非同步任務。當結束Activity時判斷ImagerLoaderTask是否為空,讓不為空的時候再判斷activity非同步任務是否取消。 建立onPause,onResume和onDestroy方法;(回撥:當觸動某個方法是自動呼叫;) 程式碼: //當失去焦點時,回撥 protected void onPause() { //暫停渲染和顯示 mVrPanoramaView.pauseRendering(); super.onPause(); } //當重新獲取焦點時,回撥 @Override protected void onResume() { //繼續渲染和顯示 mVrPanoramaView.resumeRendering(); super.onResume(); } //當Activity銷燬時,回撥 @Override protected void onDestroy() { //關閉渲染檢視 mVrPanoramaView.shutdown(); if(mImagerLoaderTask!=null){ //在退出Activity時,如果非同步任務沒有取消,就需要 if(!mImagerLoaderTask.isCancelled()){ mImagerLoaderTask.cancel(true); } } super.onDestroy(); } 12.設定完後執行測試,測試時,VR底部會有2個按鈕,不顯示,再新增切換VR的模式;
程式碼: //隱藏掉VR效果左下角的資訊按鈕顯示; mVrPanoramaView.setInfoButtonEnabled(false); //隱藏掉VR效果右下角的資訊按鈕顯示; mVrPanoramaView.setFullscreenButtonEnabled(false); //切換VR模式 // 有兩個模式:1.VrWidgetView.DisplayMode.FULLSCREEN_STEREO(手機模式) // 2.VrWidgetView.DisplayMode.FULLSCREEN_MONO(預設模式); mVrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO); 13.設定對VR執行狀態的監聽,如果VR執行出現錯誤,可以及時的處理; //設定VR執行狀態的監聽,如果VR執行出錯,可以及時處理; mVrPanoramaView.setEventListener(new MyVRLEventistener()); 建立一個VR執行狀態監聽的類 //VR執行狀態監聽類,自定義一個類繼承 private class MyVRLEventistener extends VrPanoramaEventListener{ //當VR檢視載入成功時回撥; @Override public void onLoadSuccess() { super.onLoadSuccess(); Toast.makeText(MainActivity.this, "載入成功", Toast.LENGTH_SHORT).show(); } //當VR檢視載入失敗時回撥; @Override public void onLoadError(String errorMessage) { super.onLoadError(errorMessage); Toast.makeText(MainActivity.this, "載入成功", Toast.LENGTH_SHORT).show(); } } MainActivity.java程式碼:
提示:1.由於用虛擬機器測試,本圖片有部分功能不能顯示,建議大家用真機測試。給你不一樣的體驗 2.最下方附有主頁程式碼; 實現步驟: 1.谷歌官網提供的VR資源下載
2.因為使用VR的資源很小號記憶體,所以我們為了避免OOM的問題,在清單檔案中新增 android:largeHeap="true",提高警報線。 清單檔案程式碼: <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> 3.由於低版本要用高版本的東西,在Gradle檔案中新增 compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7' 4.匯入三個庫檔案common,commonwidget,panowidget 目錄為gvr-android-sdk-master\libraries下的三個檔案
再新增到moudle中,Ctrl+Alt+Shift+S,選擇你的moudle,點選右上角加號,匯入需要的庫檔案;
5.編譯構造版本太低,2.0後的studio沒辦法匯入此model.
會爆出這個異常,解決的辦法是進入檔案裡,修改build.gradle檔案
6.在佈局檔案中新增VR控制元件: 程式碼: <com.google.vr.sdk.widgets.pano.VrPanoramaView android:id="@+id/vr" android:layout_width="match_parent" android:layout_height="match_parent"></com.google.vr.sdk.widgets.pano.VrPanoramaView> 7.初始化VrPanoramaView控制元件
8.在src資料夾下的main資料夾下建立一個資產檔案assets,存放VR圖片;
9.由於VR資源資料量大,獲取需要時間,故把載入圖片放到子執行緒中進行,主執行緒來顯示圖片,可以使用一個非同步執行緒AsyncTask或EventBus技術完成; (1)建立一個子執行緒,繼承自AsyncTask<Void,Void,Bitmap>,並建立複寫方法; (2)在建立的複寫方法在子執行緒進行,從本地檔案中把資源載入到內容分中,從資產目錄中拿到資源,返回的結果是位元組流,把位元組流轉換為Bitmap物件;並返回Bitmap物件 (3)把複寫的方法執行在主執行緒中,建立onPostExecute()方法接收;使用VR的控制元件物件顯示效果 程式碼: private class ImagerLoaderTask extends AsyncTask<Void,Void,Bitmap>{ @Override protected Bitmap doInBackground(Void... params) { try { //從資產目錄中拿到資源,返回的結果是位元組流; InputStream inputStream = getAssets().open("andes.jpg"); //把位元組流轉換唄Bitmap物件; Bitmap bitmap = BitmapFactory.decodeStream(inputStream); return bitmap; } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap bitmap) { //建立VrPanoramaView.options,去決定顯示VR是普通效果還是立體效果; VrPanoramaView.Options options = new VrPanoramaView.Options(); //TYPE_STEREO_OVER_UNDER立體效果,就是圖片的上半部分放在左眼顯示,下半部分放在右眼顯示; //TYPE_MONO 普通效果; options.inputType= VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER; //使用VR控制元件物件,顯示效果 需要兩個引數1.Bitmap物件2.VrPanoramaView.options; mVrPanoramaView.loadImageFromBitmap(bitmap,options); super.onPostExecute(bitmap); } } 10.在Main方法中使用自定義的AsyncTask,播放VR效果 ImagerLoaderTask imagerLoaderTask = new ImagerLoaderTask(); imagerLoaderTask.execute(); 11.優化VR,因為VR很佔用記憶體,所以當介面進入onPause狀態,暫停VR檢視顯示,進入onResume狀態,繼續VR檢視顯示,進入onDestroy狀態,殺死VR,關閉非同步任務。當結束Activity時判斷ImagerLoaderTask是否為空,讓不為空的時候再判斷activity非同步任務是否取消。 建立onPause,onResume和onDestroy方法;(回撥:當觸動某個方法是自動呼叫;) 程式碼: //當失去焦點時,回撥 protected void onPause() { //暫停渲染和顯示 mVrPanoramaView.pauseRendering(); super.onPause(); } //當重新獲取焦點時,回撥 @Override protected void onResume() { //繼續渲染和顯示 mVrPanoramaView.resumeRendering(); super.onResume(); } //當Activity銷燬時,回撥 @Override protected void onDestroy() { //關閉渲染檢視 mVrPanoramaView.shutdown(); if(mImagerLoaderTask!=null){ //在退出Activity時,如果非同步任務沒有取消,就需要 if(!mImagerLoaderTask.isCancelled()){ mImagerLoaderTask.cancel(true); } } super.onDestroy(); } 12.設定完後執行測試,測試時,VR底部會有2個按鈕,不顯示,再新增切換VR的模式;
程式碼: //隱藏掉VR效果左下角的資訊按鈕顯示; mVrPanoramaView.setInfoButtonEnabled(false); //隱藏掉VR效果右下角的資訊按鈕顯示; mVrPanoramaView.setFullscreenButtonEnabled(false); //切換VR模式 // 有兩個模式:1.VrWidgetView.DisplayMode.FULLSCREEN_STEREO(手機模式) // 2.VrWidgetView.DisplayMode.FULLSCREEN_MONO(預設模式); mVrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO); 13.設定對VR執行狀態的監聽,如果VR執行出現錯誤,可以及時的處理; //設定VR執行狀態的監聽,如果VR執行出錯,可以及時處理; mVrPanoramaView.setEventListener(new MyVRLEventistener()); 建立一個VR執行狀態監聽的類 //VR執行狀態監聽類,自定義一個類繼承 private class MyVRLEventistener extends VrPanoramaEventListener{ //當VR檢視載入成功時回撥; @Override public void onLoadSuccess() { super.onLoadSuccess(); Toast.makeText(MainActivity.this, "載入成功", Toast.LENGTH_SHORT).show(); } //當VR檢視載入失敗時回撥; @Override public void onLoadError(String errorMessage) { super.onLoadError(errorMessage); Toast.makeText(MainActivity.this, "載入成功", Toast.LENGTH_SHORT).show(); } } MainActivity.java程式碼:
public class MainActivity extends AppCompatActivity { private VrPanoramaView mVrPanoramaView; private ImagerLoaderTask mImagerLoaderTask; @Override //匯入三個庫檔案 common,commonwidget,panowidget; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //對VR控制元件例項化; mVrPanoramaView = (VrPanoramaView) findViewById(R.id.vr); //隱藏掉VR效果左下角的資訊按鈕顯示; mVrPanoramaView.setInfoButtonEnabled(false); //隱藏掉VR效果右下角的資訊按鈕顯示; mVrPanoramaView.setFullscreenButtonEnabled(false); //切換VR模式 // 有兩個模式:1.VrWidgetView.DisplayMode.FULLSCREEN_STEREO(手機模式) // 2.VrWidgetView.DisplayMode.FULLSCREEN_MONO(預設模式); mVrPanoramaView.setDisplayMode(VrWidgetView.DisplayMode.FULLSCREEN_STEREO); //設定VR執行狀態的監聽,如果VR執行出錯,可以及時處理; mVrPanoramaView.setEventListener(new MyVRLEventistener()); //使用自定義的AsyncTask,實現播放VR效果 mImagerLoaderTask = new ImagerLoaderTask(); mImagerLoaderTask.execute(); } private class ImagerLoaderTask extends AsyncTask<Void,Void,Bitmap>{ @Override protected Bitmap doInBackground(Void... params) { try { //從資產目錄中拿到資源,返回的結果是位元組流; InputStream inputStream = getAssets().open("andes.jpg"); //把位元組流轉換唄Bitmap物件; Bitmap bitmap = BitmapFactory.decodeStream(inputStream); return bitmap; } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap bitmap) { //建立VrPanoramaView.options,去決定顯示VR是普通效果還是立體效果; VrPanoramaView.Options options = new VrPanoramaView.Options(); //TYPE_STEREO_OVER_UNDER立體效果,就是圖片的上半部分放在左眼顯示,下半部分放在右眼顯示; //TYPE_MONO 普通效果; options.inputType= VrPanoramaView.Options.TYPE_STEREO_OVER_UNDER; //使用VR控制元件物件,顯示效果 需要兩個引數1.Bitmap物件2.VrPanoramaView.options; mVrPanoramaView.loadImageFromBitmap(bitmap,options); super.onPostExecute(bitmap); } } @Override //當失去焦點時,回撥 protected void onPause() { //暫停渲染和顯示 mVrPanoramaView.pauseRendering(); super.onPause(); } //當重新獲取焦點時,回撥 @Override protected void onResume() { //繼續渲染和顯示 mVrPanoramaView.resumeRendering(); super.onResume(); } //當Activity銷燬時,回撥 @Override protected void onDestroy() { //關閉渲染檢視 mVrPanoramaView.shutdown(); if(mImagerLoaderTask!=null){ //在退出Activity時,如果非同步任務沒有取消,就需要 if(!mImagerLoaderTask.isCancelled()){ mImagerLoaderTask.cancel(true); } } super.onDestroy(); } //VR執行狀態監聽類,自定義一個類繼承 private class MyVRLEventistener extends VrPanoramaEventListener{ //當VR檢視載入成功時回撥; @Override public void onLoadSuccess() { super.onLoadSuccess(); Toast.makeText(MainActivity.this, "載入成功", Toast.LENGTH_SHORT).show(); } //當VR檢視載入失敗時回撥; @Override public void onLoadError(String errorMessage) { super.onLoadError(errorMessage); Toast.makeText(MainActivity.this, "載入成功", Toast.LENGTH_SHORT).show(); } } }