Search code examples
javaandroidcamera

Below is my code but there is some error when i open camera appear and immediately disappear. How to hold on the camera view for a bit longer.?


1.MainActivity.java file I think the error got at this line

 public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop()

I'm trying to open the camera and display using SurfaceView. This delays the loading of the activity for a really long time. So I'm wondering what are the best practices of opening the camera.

package com.example.software2.ocrhy;
public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private SurfaceView surfaceView;
    private CameraSource cameraSource;
    private TextRecognizer textRecognizer;
    private TextToSpeech textToSpeech;
    private String stringResult = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActivityCompat.requestPermissions(this, new String[]{CAMERA}, PackageManager.PERMISSION_GRANTED);
        textToSpeech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        cameraSource.release();
    }
    private void textRecognizer(){
        textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();
        cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer)
                .setRequestedPreviewSize(1280, 1024)
                .build();

        surfaceView = findViewById(R.id.surfaceView);
        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @SuppressLint("MissingPermission")
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    cameraSource.start(surfaceView.getHolder());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });
        textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
            @Override
            public void release() {
            }

            @Override
            public void receiveDetections(Detector.Detections<TextBlock> detections) {

                SparseArray<TextBlock> sparseArray = detections.getDetectedItems();
                StringBuilder stringBuilder = new StringBuilder();

                for (int i = 0; i<sparseArray.size(); ++i){
                    TextBlock textBlock = sparseArray.valueAt(i);
                    if (textBlock != null && textBlock.getValue() !=null){
                        stringBuilder.append(textBlock.getValue() + " ");
                    }
                }

                final String stringText = stringBuilder.toString();

                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(() -> {
                    stringResult = stringText;
                    resultObtained();
                });
            }
        });
    }
    private void resultObtained(){
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        textView.setText(stringResult);
        textToSpeech.speak(stringResult, TextToSpeech.QUEUE_FLUSH, null, null);
    }
    public void buttonStart(View view){
        setContentView(R.layout.surface);
        textRecognizer();
    }
}

I got full code from this link

  1. javafile
  2. error got in camera activity

Solution

  • According to your source code, your camera starts reading the text immediately. If you want to first see your text on your camera and only then start reading it we can break down it to following steps:

    1. Open your camera
    2. Navigate to specific text
    3. Finally when you see via your camera the text what you want to read it

    I suggest you to do small modifications on your code

    1. Add Capture button on your surfaceview.xml (for example in a code below)
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto"
       xmlns:tools="http://schemas.android.com/tools"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
    
       <SurfaceView
           android:id="@+id/surfaceView"
           android:layout_width="308dp"
           android:layout_height="503dp"
           android:layout_marginStart="64dp"
           android:layout_marginTop="32dp"
           app:layout_constraintStart_toStartOf="parent"
           app:layout_constraintTop_toTopOf="parent" />
    
       <Button
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           app:layout_constraintBottom_toBottomOf="parent"
           app:layout_constraintStart_toStartOf="parent"
           android:id="@+id/capture"
           android:layout_marginHorizontal="32dp"
           android:layout_marginBottom="32dp"
           android:text="Capture"
           app:layout_constraintEnd_toEndOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    1. Move out text processing to separate function
    private void capture() {
            textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
                @Override
                public void release() {
                }
    
                @Override
                public void receiveDetections(Detector.Detections<TextBlock> detections) {
    
                    SparseArray<TextBlock> sparseArray = detections.getDetectedItems();
                    StringBuilder stringBuilder = new StringBuilder();
    
                    for (int i = 0; i<sparseArray.size(); ++i){
                        TextBlock textBlock = sparseArray.valueAt(i);
                        if (textBlock != null && textBlock.getValue() !=null){
                            stringBuilder.append(textBlock.getValue() + " ");
                        }
                    }
    
                    final String stringText = stringBuilder.toString();
    
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                       stringResult = stringText;
                       resultObtained();
                        }
                    });
                }
            });
    }
    
    1. Capture your text on capture button click
    public void buttonStart(View view){
            setContentView(R.layout.surfaceview);
            Button capture = findViewById(R.id.capture);
            capture.setOnClickListener(v -> capture());
            textRecognizer();
    }
    
    

    As a result whole MainActivity

    
    
    import android.Manifest;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.speech.tts.TextToSpeech;
    import android.util.SparseArray;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    
    import com.google.android.gms.vision.CameraSource;
    import com.google.android.gms.vision.Detector;
    import com.google.android.gms.vision.text.TextBlock;
    import com.google.android.gms.vision.text.TextRecognizer;
    
    import java.io.IOException;
    
    import static android.Manifest.permission.CAMERA;
    
    public class MainActivity extends AppCompatActivity {
    
        private TextView textView;
        private SurfaceView surfaceView;
    
        private CameraSource cameraSource;
        private TextRecognizer textRecognizer;
    
        private TextToSpeech textToSpeech;
        private String stringResult = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ActivityCompat.requestPermissions(this, new String[]{CAMERA}, PackageManager.PERMISSION_GRANTED);
            textToSpeech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
                @Override
                public void onInit(int status) {
                }
            });
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            cameraSource.release();
        }
    
        private void textRecognizer() {
            textRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();
            cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer)
                    .setRequestedPreviewSize(1280, 1024)
                    .setAutoFocusEnabled(true)
                    .build();
    
            surfaceView = findViewById(R.id.surfaceView);
            Context context = this;
            surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    try {
                        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                            // TODO: Consider calling
                            //    ActivityCompat#requestPermissions
                            // here to request the missing permissions, and then overriding
                            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                            //                                          int[] grantResults)
                            // to handle the case where the user grants the permission. See the documentation
                            // for ActivityCompat#requestPermissions for more details.
                            return;
                        }
                        cameraSource.start(surfaceView.getHolder());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                }
    
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    cameraSource.stop();
                }
            });
        }
        private void capture() {
            textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
                @Override
                public void release() {
                }
    
                @Override
                public void receiveDetections(Detector.Detections<TextBlock> detections) {
    
                    SparseArray<TextBlock> sparseArray = detections.getDetectedItems();
                    StringBuilder stringBuilder = new StringBuilder();
    
                    for (int i = 0; i<sparseArray.size(); ++i){
                        TextBlock textBlock = sparseArray.valueAt(i);
                        if (textBlock != null && textBlock.getValue() !=null){
                            stringBuilder.append(textBlock.getValue() + " ");
                        }
                    }
    
                    final String stringText = stringBuilder.toString();
    
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            stringResult = stringText;
                            resultObtained();
                        }
                    });
                }
            });
        }
    
        private void resultObtained(){
            setContentView(R.layout.activity_main);
            textView = findViewById(R.id.textView);
            textView.setText(stringResult);
            textToSpeech.speak(stringResult, TextToSpeech.QUEUE_FLUSH, null, null);
        }
    
        public void buttonStart(View view){
            setContentView(R.layout.surfaceview);
            Button capture = findViewById(R.id.capture);
            capture.setOnClickListener(v -> capture());
            textRecognizer();
        }
    }