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
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:
I suggest you to do small modifications on your code
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>
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();
}
});
}
});
}
capture
button clickpublic 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();
}
}