androidtextureview

Camera shows black screen with TextureView


I want to use TextureView as a camera. but I got a black screen.

my class:

    package com.sm.carpet.activity;

    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.content.ActivityNotFoundException;
    import android.content.Intent;
    import android.graphics.SurfaceTexture;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Handler;
    import android.util.Log;
    import android.view.Display;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.Surface;
    import android.view.TextureView;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.Toast;

    import com.sm.carpet.R;
    import com.sm.carpet.view.ModelSurfaceView;
    import com.sm.carpet.services.ExampleSceneLoader;
    import com.sm.carpet.services.SceneLoader;
    import com.sm.carpet.utils.ContentUtils;
    import com.sm.carpet.utils.Utils;

    import java.io.File;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;

    /**
     * This activity represents the container for our 3D viewer.
     * 
     * @author andresoviedo
     */
    public class TDModelActivity extends Activity implements TextureView.SurfaceTextureListener{

        private final static String TAG = TDModelActivity.class.getName();
        private android.hardware.Camera mCamera;
        private SurfaceTexture mSurfaceTexture;

        private static final int REQUEST_CODE_OPEN_FILE = 1000;

        private String paramAssetDir;
        private String paramAssetFilename;
        /**
         * The file to load. Passed as input parameter
         */
        private String paramFilename;
        /**
         * Enter into Android Immersive mode so the renderer is full screen or not
         */
        private boolean immersiveMode = true;
        /**
         * Background GL clear color. Default is light gray
         */
        private float[] backgroundColor = new float[]{0.2f, 0.2f, 0.2f, 1.0f};

        private ModelSurfaceView gLView;
        private TextView mTextView;

        private SceneLoader scene;

        private Handler handler;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_model_textureview);



            // Try to get input parameters
            Bundle b = getIntent().getExtras();
            if (b != null) {
                this.paramAssetDir = b.getString("assetDir");
                this.paramAssetFilename = b.getString("assetFilename");
                this.paramFilename = b.getString("uri");
                this.immersiveMode = "true".equalsIgnoreCase(b.getString("immersiveMode"));
                try{
                    String[] backgroundColors = b.getString("backgroundColor").split(" ");
                    backgroundColor[0] = Float.parseFloat(backgroundColors[0]);
                    backgroundColor[1] = Float.parseFloat(backgroundColors[1]);
                    backgroundColor[2] = Float.parseFloat(backgroundColors[2]);
                    backgroundColor[3] = Float.parseFloat(backgroundColors[3]);
                }catch(Exception ex){
                    // Assuming default background color
                }
            }
            Log.i("Renderer", "Params: assetDir '" + paramAssetDir + "', assetFilename '" + paramAssetFilename + "', uri '"
                    + paramFilename + "'");

            handler = new Handler(getMainLooper());

            gLView = new ModelSurfaceView(this);
            gLView.setZOrderOnTop(true);




            RelativeLayout lyCamera = (RelativeLayout) findViewById(R.id.ly_parent_camera);
            TextureView textureView = new TextureView(this);
            textureView.setSurfaceTextureListener(this);
            lyCamera.addView(textureView);

            LinearLayout lyModel = (LinearLayout) findViewById(R.id.ly_parent_model);
            //lyModel.addView(gLView);



            if (paramFilename == null && paramAssetFilename == null) {
                scene = new ExampleSceneLoader(this);
            } else {
                scene = new SceneLoader(this);
            }
            scene.init();

            // Show the Up button in the action bar.
            setupActionBar();

            // TODO: Alert user when there is no multitouch support (2 fingers). He won't be able to rotate or zoom for
            // example
            Utils.printTouchCapabilities(getPackageManager());

            setupOnSystemVisibilityChangeListener();
        }

        /**
         * Set up the {@link android.app.ActionBar}, if the API is available.
         */
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        private void setupActionBar() {
            // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // getActionBar().setDisplayHomeAsUpEnabled(true);
            // }
        }



        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        private void setupOnSystemVisibilityChangeListener() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
                return;
            }
            getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
                @Override
                public void onSystemUiVisibilityChange(int visibility) {
                    // Note that system bars will only be "visible" if none of the
                    // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
                    if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                        // TODO: The system bars are visible. Make any desired
                        // adjustments to your UI, such as showing the action bar or
                        // other navigational controls.
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                            hideSystemUIDelayed(3000);
                        }
                    } else {
                        // TODO: The system bars are NOT visible. Make any desired
                        // adjustments to your UI, such as hiding the action bar or
                        // other navigational controls.
                    }
                }
            });
        }

        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            if (hasFocus) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    if (immersiveMode) hideSystemUIDelayed(5000);
                }
            }
        }


        private void hideSystemUIDelayed(long millis) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
                return;
            }
            handler.postDelayed(new Runnable() {
                public void run() {
                    hideSystemUI();
                }
            }, millis);
        }

        private void hideSystemUI() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                hideSystemUIKitKat();
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                hideSystemUIJellyBean();
            }
        }

        // This snippet hides the system bars.
        @TargetApi(Build.VERSION_CODES.KITKAT)
        private void hideSystemUIKitKat() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
                return;
            }
            // Set the IMMERSIVE flag.
            // Set the content to appear under the system bars so that the content
            // doesn't resize when the system bars hide and show.
            final View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE);
        }

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        private void hideSystemUIJellyBean() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                return;
            }
            final View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE);
        }

        // This snippet shows the system bars. It does this by removing all the flags
        // except for the ones that make the content appear under the system bars.
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        private void showSystemUI() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                return;
            }
            final View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        }

        public File getParamFile() {
            return getParamFilename() != null ? new File(getParamFilename()) : null;
        }

        public String getParamAssetDir() {
            return paramAssetDir;
        }

        public String getParamAssetFilename() {
            return paramAssetFilename;
        }

        public String getParamFilename() {
            return paramFilename;
        }

        public float[] getBackgroundColor(){
            return backgroundColor;
        }

        public SceneLoader getScene() {
            return scene;
        }

        public ModelSurfaceView getgLView() {
            return gLView;
        }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            switch (requestCode) {
                case REQUEST_CODE_OPEN_FILE:
                    if (resultCode == RESULT_OK) {
                        // The URI of the selected file
                        final Uri uri = data.getData();
                        Log.i("Menu", "Loading '" + uri.toString() + "'");
                        if (uri != null) {
                            final String path = ContentUtils.getPath(getApplicationContext(), uri);
                            if (path != null) {
                                try {
                                    scene.loadTexture(null, new URL("file://"+path));
                                } catch (MalformedURLException e) {
                                    Toast.makeText(getApplicationContext(), "Problem loading texture '" + uri.toString() + "'",
                                            Toast.LENGTH_SHORT).show();
                                }
                            } else {
                                Toast.makeText(getApplicationContext(), "Problem loading texture '" + uri.toString() + "'",
                                        Toast.LENGTH_SHORT).show();
                            }
                        }
                    } else {
                        Toast.makeText(getApplicationContext(), "Result when loading texture was '" + resultCode + "'",
                                Toast.LENGTH_SHORT).show();
                    }
            }
        }



        ///////////////
        /*
        *
        * START CAMERA
        *
         */

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            mSurfaceTexture = surface;
            //if (!PermissionHelper.hasCameraPermission(this)) {
            //  PermissionHelper.requestCameraPermission(this, false);
            //} else {
            Log.e("masoud","ali");
            startPreview();

            //}
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            mCamera.stopPreview();
            mCamera.release();
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

        }


        private void startPreview() {
            mCamera = android.hardware.Camera.open();
            if (mCamera == null) {
                // Seeing this on Nexus 7 2012 -- I guess it wants a rear-facing camera, but
                // there isn't one.  TODO: fix
                throw new RuntimeException("Default camera not available");
            }

            try {
                mCamera.setPreviewTexture(mSurfaceTexture);
                Display display = ((WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

                if(display.getRotation() == Surface.ROTATION_0) {
                    mCamera.setDisplayOrientation(90);
                }
                if(display.getRotation() == Surface.ROTATION_270) {
                    mCamera.setDisplayOrientation(180);
                }
                mCamera.startPreview();
            } catch (IOException ioe) {
                // Something bad happened
                Log.e(TAG,"Exception starting preview", ioe);
            }
        }
    }

my layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="2">

    <RelativeLayout
        android:id="@+id/ly_parent_camera"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:id="@+id/ly_parent_model">

        </LinearLayout>

        <TextureView
            android:id="@+id/textureView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/transparent"/>

    </RelativeLayout>

</LinearLayout>

my permissions:

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />

<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />

Solution

  • Solved: I used hardwareAccelerated:

    <Application
        android:hardwareAccelerated="true"