1. 程式人生 > >Android實現VR全景立體化顯示以及優化

Android實現VR全景立體化顯示以及優化

實現效果圖:
提示: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
//匯入三個庫檔案 commoncommonwidgetpanowidgetprotected 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.optionsmVrPanoramaView.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();
        }
    }
}