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
}
}