Search code examples
androidmultithreadingandroid-studiogoogle-cardboard

Cardboard sample, method must be called from UI thread


Trying to develop an app for google cardboard, i downloaded the sample from the official sdk. In the inner class ImageLoaderTask ( which it should be the helper class to manage threading )

    class ImageLoaderTask extends AsyncTask<Pair<Uri, Options>, Void, Boolean> {

    /**
     * Reads the bitmap from disk in the background and waits until it's loaded by pano widget.
     */
    @Override
    protected Boolean doInBackground(Pair<Uri, Options>... fileInformation) {
      Options panoOptions = null;  // It's safe to use null VrPanoramaView.Options.
      InputStream istr = null;
      if (fileInformation == null || fileInformation.length < 1
          || fileInformation[0] == null || fileInformation[0].first == null) {
        AssetManager assetManager = getAssets();
        try {
          istr = assetManager.open("andes.jpg");
          panoOptions = new Options();
          panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;
        } catch (IOException e) {
          Log.e(TAG, "Could not decode default bitmap: " + e);
          return false;
        }
      } else {
        try {
          istr = new FileInputStream(new File(fileInformation[0].first.getPath()));
          panoOptions = fileInformation[0].second;
        } catch (IOException e) {
          Log.e(TAG, "Could not load file: " + e);
          return false;
        }
      }

      panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);
      try {
        istr.close();
      } catch (IOException e) {
        Log.e(TAG, "Could not close input stream: " + e);
      }

      return true;
    }
  }

panoWidgetView is the widget for the panorama, and it is declared inside the activity which includes this inner class. But Android Studio gives me this error: Method loadImageFromBitmap must be called from the UI thread, currently inferred thread is worker. Any possible solution?


Solution

  • try moving "loadImageFromBitmap" inside onPostExecute :

    class ImageLoaderTask extends AsyncTask<Pair<Uri, BitmapFactory.Options>, Void, Boolean> {
            Options panoOptions = null;  // It's safe to use null VrPanoramaView.Options.
            InputStream istr = null;
    
            /**
             * Reads the bitmap from disk in the background and waits until it's loaded by pano widget.
             */
            @Override
            protected Boolean doInBackground(Pair<Uri, BitmapFactory.Options>... fileInformation) {
    
                if (fileInformation == null || fileInformation.length < 1
                        || fileInformation[0] == null || fileInformation[0].first == null) {
                    AssetManager assetManager = getAssets();
                    try {
                        istr = assetManager.open("andes.jpg");
                        panoOptions = new Options();
                        panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;
                    } catch (IOException e) {
                        Log.e(TAG, "Could not decode default bitmap: " + e);
                        return false;
                    }
                } else {
                    try {
                        istr = new FileInputStream(new File(fileInformation[0].first.getPath()));
                        panoOptions = fileInformation[0].second;
                    } catch (IOException e) {
                        Log.e(TAG, "Could not load file: " + e);
                        return false;
                    }
                }
    
                try {
                    istr.close();
                } catch (IOException e) {
                    Log.e(TAG, "Could not close input stream: " + e);
                }
    
                return true;
            }
    
            @Override
            protected void onPostExecute(Boolean aBoolean) {
                if( istr!=null && panoOptions!=null){
                     panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);
                }
                super.onPostExecute(aBoolean);
            }
        }