skip to Main Content

I followed the istructions of the tutorial at com.google.codelab.mlkit.

Instead of using intent.data I am using FileProvider to get and analyze the full picture.

I replaced the virtural image in the emulation based on the recommendation in Android emulator camera custom image.

So I start my app (main activity), take a photo with the internal camera (which is the replaced virtual image) and get back to the main activity. I run into the code recognizeTextFromImage(), but I never run into .addOnSuccessListener() and .addOnFailureListener(). That surpises me because I even do not get a failure. Nothing is printed into the log.

I am using API-level 23 because the resultCode is 0 (instead of -1) if I am using a higher API.

My question is: why doesn’t my code run into .addOnSuccessListener() or at least into .addOnFailureListener() ?

1. Update

I tried "intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);“` and this changed the behavior. It took seconds to read the file. So I think @Danish was correct that the file was not created by the camera. But: same issue with addOnFailureListener(). Maybe the file is to big? Or did I send the wrong format? The Log says "W/e.codelab.mlki: Verification of java.lang.String com.google.codelab.mlkit.MainActivity.recognizeTextFromImage(com.google.mlkit.vision.common.InputImage) took 536.238ms"

2. Update

<?xml version="1.0" encoding="utf-8"?>

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_images" path="Pictures" />
</paths>

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.codelab.mlkit">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"  />
    <uses-feature
        android:name="android.hardware.camera"
        android:required="true"/>

    <queries>
        <intent>
            <action android:name="android.media.action.IMAGE_CAPTURE" />
        </intent>
    </queries>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:screenOrientation="portrait"
            android:configChanges="keyboardHidden|orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <meta-data
            android:name="com.google.codelab.mlkit.vision.DEPENDENCIES"
            android:value="ocr" />
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths">
            </meta-data>
        </provider>

    </application>

</manifest>

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    app:layoutDescription="@xml/activity_main_scene"
    tools:context=".MainActivity" >

    <TableLayout
        android:layout_width="360dp"
        android:layout_height="539dp"
        android:layout_centerInParent="true">

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TableLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <TableRow
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

                    <TextView
                        android:id="@+id/textView_ServiceID"
                        android:layout_width="11dp"
                        android:layout_height="match_parent"
                        android:layout_weight="0.3"
                        android:gravity="center"
                        android:text="ServiceID"
                        android:textAlignment="viewStart" />

                    <EditText
                        android:id="@+id/editText_ServiceID"
                        android:layout_height="match_parent"
                        android:layout_weight="0.7
"
                        android:gravity="left"
                        android:inputType="text"
                        android:text="4711" />

                </TableRow>

            </TableLayout>
        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TableLayout
                android:layout_width="359dp"
                android:layout_height="match_parent">

                <TableRow
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

                    <TextView
                        android:id="@+id/textView_Site"
                        android:layout_height="match_parent"
                        android:layout_weight="0.3"
                        android:gravity="center"
                        android:text="Site"
                        android:textAlignment="viewStart" />

                    <Spinner
                        android:id="@+id/spinner_Site"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent" />

                    <ImageButton
                        android:id="@+id/imageButton_Site"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        app:srcCompat="@drawable/ic_photo" />

                    <EditText
                        android:id="@+id/editText_Site"
                        android:layout_height="match_parent"
                        android:layout_weight="0.6"
                        android:inputType="text"
                        android:text="not yet reconized" />

                </TableRow>

 
            </TableLayout>

        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TableLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="end"  >

                <TableRow
                    android:layout_gravity="end"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"  >

                    <ImageButton
                        android:id="@+id/imageButton6"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        app:srcCompat="@drawable/ic_send" />

                    <ImageButton
                        android:id="@+id/imageButton7"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        app:srcCompat="@drawable/ic_save" />

                </TableRow>

            </TableLayout>
        </TableRow>

    </TableLayout>

</RelativeLayout>
package com.google.codelab.mlkit;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
    private static final String TAG = "MainActivity";
    private ImageButton imageButton_Site;
    private EditText editText_Site;
    private Spinner spinner_Site;
    private InputImage createdImage;
    String recognizedText = "";
    String currentPhotoPath;
    static final int REQUEST_IMAGE_CAPTURE = 1;

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

        imageButton_Site = findViewById(R.id.imageButton_Site);
        imageButton_Site.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dispatchTakePictureIntent();
            }
        });

        spinner_Site = findViewById(R.id.spinner_Site);
        String[] items = new String[]{"Chicago", "New York"}; // has to be retrieved from server based on GPS (satellite)
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, items);
        spinner_Site.setAdapter(adapter);
        spinner_Site.setOnItemSelectedListener(this);
    }

    private void dispatchTakePictureIntent() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
                Toast.makeText(getApplicationContext(), "Error occurred while creating the File!",Toast.LENGTH_LONG).show();
            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                Uri photoURI = FileProvider.getUriForFile(this,
                        BuildConfig.APPLICATION_ID + ".fileprovider",
                        photoFile);
                if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                    takePictureIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                    takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // new
                    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
                }
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult( requestCode, resultCode, data);
        // Log.d("OLR", "onActivityResult: "+ requestCode +" "+resultCode+" "+data);

        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {

            Bitmap bitmap=BitmapFactory.decodeFile(currentPhotoPath);
            Bitmap imagebitmap=Bitmap.createBitmap(bitmap);//Just add this line and everything will work fine.I tried this code, its working like a charm.
            int check = bitmap.getWidth();
            InputImage inputImage = InputImage.fromBitmap(imagebitmap, 0);

            String text = recognizeTextFromImage(inputImage);
            if (text.isEmpty())
            {
                Toast.makeText(getApplicationContext(), "Nothing recognized. Please try again!",Toast.LENGTH_LONG).show();
                editText_Site.setText("Failed !");
            }
            else {
                editText_Site.setText(text);
            }
        }
        else {
            Toast.makeText(getApplicationContext(), "An issue occurred. Please inform app owner!",Toast.LENGTH_LONG).show();
        }
    }

    private File createImageFile() throws IOException {

        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);

        // create directory if necessary
        if (!storageDir.exists()){
            storageDir.mkdir();
        }

        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",Locale.GERMANY).format(new Date());
        String imageFileName = "OLR_" + timeStamp + "_";
        File image = File.createTempFile(
                imageFileName,  // prefix
                ".jpg",   // suffix
                storageDir      // directory
        );

        // imageFile = image;
        currentPhotoPath = image.getAbsolutePath();

        return image;
    }

    private String recognizeTextFromImage(InputImage image) {

        TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
        Task<Text> task = recognizer.process(image);
        // recognizer.process(image)
        task
                .addOnSuccessListener(
                        new OnSuccessListener<Text>() {
                            @Override
                            public void onSuccess(Text texts) {
                                recognizedText = processTextRecognitionResult(texts);
                                Log.d(TAG,"Successful");
                            }
                        })

                /*.addOnSuccessListener(
                        new OnSuccessListener<Text>() {
                            @Override
                            public void onSuccess(Text texts) {
                                recognizedText = texts.getText();
                                editText_Site.setText(recognizedText);
                                Log.d(TAG,"Successful");
                            }
                        })*/
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                e.printStackTrace();
                                Log.d(TAG,"Not Successful");
                            }
                        });
        recognizer.close();
        return recognizedText;
    }

    private String processTextRecognitionResult(Text texts) {
        String recognizedText = "";
        List<Text.TextBlock> blocks = texts.getTextBlocks();
        if (blocks.size() == 0) {
            // No text found
        }
        else {
            for (int i = 0; i < blocks.size(); i++) {
                List<Text.Line> lines = blocks.get(i).getLines();
                for (int j = 0; j < lines.size(); j++) {
                    List<Text.Element> elements = lines.get(j).getElements();
                    for (int k = 0; k < elements.size(); k++) {
                        String elementText = elements.get(k).getText();
                        recognizedText = recognizedText + elementText;
                    }
                }
            }
        }
        return recognizedText;
    }
    private void showToast(String message) {
        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
    }

    public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
        spinner_Site = findViewById(R.id.spinner_Site);
        editText_Site = findViewById(R.id.editText_Site);
        editText_Site.setText(spinner_Site.getSelectedItem().toString());
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // Do nothing
    }

}


2

Answers


  1. Chosen as BEST ANSWER

    Problem solved

    (1) I had to add intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    (2) I checked the the returned string "recognizedText" which was always empty, because the thread executed after the variable was filled. Ashes on my head. My thanks go to @Danish who gave me the decisive hint to add logs to the right place.

    (3) For any reason I had to wait sometime before starting debugging.


  2. Worked for hours on this and Alhamdulillah I came out with the solution.
    @Micky I found bugs in your code.So to help you out I am providing you with solution below. Basically,the bug is related to rotation if the image is not captured in landscape mode the ocr did not recognized the text properly so its necessary to make sure that the image is rotated properly before scanning.There is also the problem in this line recognizedText = processTextRecognitionResult(texts); it doesnt recognize the text properly you can check below I have added one more edittext to show you the difference on how the text send by texts.getText() gives you better result.

    Check the code below:

    import android.app.Activity;
    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Matrix;
    import android.media.ExifInterface;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.ParcelFileDescriptor;
    import android.os.StrictMode;
    import android.provider.MediaStore;
    import android.util.Log;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.EditText;
    import android.widget.ImageButton;
    import android.widget.Spinner;
    import android.widget.Toast;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.RequiresApi;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.content.FileProvider;
    
    import com.google.android.gms.tasks.OnFailureListener;
    import com.google.android.gms.tasks.OnSuccessListener;
    import com.google.android.gms.tasks.Task;
    
    import com.google.mlkit.vision.common.InputImage;
    import com.google.mlkit.vision.text.Text;
    import com.google.mlkit.vision.text.TextRecognition;
    import com.google.mlkit.vision.text.TextRecognizer;
    import com.google.mlkit.vision.text.latin.TextRecognizerOptions;
    
    import java.io.File;
    import java.io.FileDescriptor;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Locale;
    
    public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
        private static final String TAG = "MainActivity";
        private ImageButton imageButton_Site;
        private EditText editText_Site;
        EditText editText;
        private Spinner spinner_Site;
        private InputImage createdImage;
        String recognizedText="";
        String currentPhotoPath;
        static final int REQUEST_IMAGE_CAPTURE = 1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            editText_Site=findViewById(R.id.editText_Site);
            editText=findViewById(R.id.editText);
            imageButton_Site = findViewById(R.id.imageButton_Site);
            spinner_Site = findViewById(R.id.spinner_Site);
            String[] items = new String[]{"Chicago", "Ludwigshafen"}; // has to be retrieved from server based on GPS (satellite)
            ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, items);
            spinner_Site.setAdapter(adapter);
            spinner_Site.setOnItemSelectedListener(this);
            imageButton_Site.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dispatchTakePictureIntent();
                }
            });
        }
    
        private void dispatchTakePictureIntent() {
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // Ensure that there's a camera activity to handle the intent
            if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                // Create the File where the photo should go
                File photoFile = null;
                try {
                    photoFile = createImageFile();
                } catch (IOException ex) {
                    Toast.makeText(getApplicationContext(), "Error occurred while creating the File!",Toast.LENGTH_LONG).show();
                }
                // Continue only if the File was successfully created
                if (photoFile != null) {
                    Uri photoURI = FileProvider.getUriForFile(this,BuildConfig.APPLICATION_ID+".fileprovider",
                            photoFile);
    
                    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
                    }
                }
            }
        }
    
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult( requestCode, resultCode, data);
            // Log.d("OLR", "onActivityResult: "+ requestCode +" "+resultCode+" "+data);
    
            if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
                ParcelFileDescriptor parcelFileDescriptor = null;
                try {
                    parcelFileDescriptor = getContentResolver().openFileDescriptor(Uri.fromFile(new File(currentPhotoPath)), "r");
    
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
             FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
    
                Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
                ExifInterface exifInterface = null;
                try {
                    exifInterface = new ExifInterface(fileDescriptor);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
    
                switch (orientation) {
                    case ExifInterface.ORIENTATION_ROTATE_90:
                        Matrix matrix = new Matrix();
                        matrix.setRotate(90);
                        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_180:
                        Matrix matrixe = new Matrix();
                        matrixe.setRotate(180);
                        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrixe, true);
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_270:
                        Matrix matrixes = new Matrix();
                        matrixes.setRotate(270);
                        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrixes, true);
                        break;
                    case ExifInterface.ORIENTATION_NORMAL:
                        Matrix matrix12 = new Matrix();
                        matrix12.setRotate(ExifInterface.ORIENTATION_ROTATE_90);
                        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix12, true);
    
    
    
            }
                InputImage inputImage=null;
                        inputImage= InputImage.fromBitmap(bitmap,0);
                 String text=null;
                try {
                    text = recognizeTextFromImage(inputImage);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (text.isEmpty())
                {
                    Toast.makeText(getApplicationContext(), "Nothing recognized. Please try again!",Toast.LENGTH_LONG).show();
                    editText_Site.setText("Failed !");
                }
                else {
                    editText_Site.setText(text);
                }
            }
            else {
                Toast.makeText(getApplicationContext(), "An issue occurred. Please inform app owner!",Toast.LENGTH_LONG).show();
            }
        }
    
        private File createImageFile() throws IOException {
    
            File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    
            // create directory if necessary
            if (!storageDir.exists()){
                storageDir.mkdir();
            }
    
            // Create an image file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.GERMANY).format(new Date());
            String imageFileName = "OLR_" + timeStamp + "_";
            File image = File.createTempFile(
                    imageFileName,  // prefix
                    ".jpg",   // suffix
                    storageDir      // directory
            );
    
            // imageFile = image;
            currentPhotoPath = image.getAbsolutePath();
    
            return image;
        }
    
        private String recognizeTextFromImage(InputImage image) throws IOException {
            TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
            Task<Text> task = recognizer.process(image)
    
                    .addOnSuccessListener(
                            new OnSuccessListener<Text>() {
                                @Override
                                public void onSuccess(Text texts) {
                                    recognizedText = processTextRecognitionResult(texts);
                                    editText.setText(texts.getText());
                                    Log.d(TAG,"Successful");
                                }
                            })
    
    
                    .addOnFailureListener(
                            new OnFailureListener() {
                                @Override
                                public void onFailure(@NonNull Exception e) {
                                    e.printStackTrace();
                                    Log.d(TAG,"Not Successful");
                                }
                            });
            return recognizedText;
        }
    
        private String processTextRecognitionResult(Text texts) {
            String recognizedText = "";
            List<Text.TextBlock> blocks = texts.getTextBlocks();
            if (blocks.size() == 0) {
                // No text found
            }
            else {
                for (int i = 0; i < blocks.size(); i++) {
                    List<Text.Line> lines = blocks.get(i).getLines();
                    for (int j = 0; j < lines.size(); j++) {
                        List<Text.Element> elements = lines.get(j).getElements();
                        for (int k = 0; k < elements.size(); k++) {
                            String elementText = elements.get(k).getText();
                            recognizedText = recognizedText + elementText;
                        }
                    }
                }
            }
            return recognizedText;
        }
        private void showToast(String message) {
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
        }
    
        public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
            spinner_Site = findViewById(R.id.spinner_Site);
    
            editText_Site.setText(spinner_Site.getSelectedItem().toString());
        }
    
    
    
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            // Do nothing
        }
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search