DEV Community 👩‍💻👨‍💻

Dilmohit
Dilmohit

Posted on

Text Detector App - An Android Project

Hey guys today in this article, we will be creating an application that will lets users click Pictures and then let them detect text in those Pictures. For this we will be using firebase MLkit. And we will be creating this project using Java Language.

  1. Create a new Project in android studio -

Create a New Android Project

  1. Connect this Project with firebase - if you don't know how to connect an android project with firebase, its quite simple.
  • first open firebase website.
  • Login using google account
  • After that click on a new project
  • Add an name for your project
  • And click on create a project
  • Then at the dashboard click at android icon

Find Package Name

  • On the register app page add the package name of the application. You can find this package name in almost all the files

Connect With Firebase

  • After that download json file and add that file here

Add Json File

  1. Add these dependencies in build.gradle/module
implementation 'com.google.firebase:firebase-core:20.1.0'
    implementation 'com.google.android.gms:play-services-mlkit-text-recognition:18.0.0'
Enter fullscreen mode Exit fullscreen mode
  1. Add these Permissions in AndroidManifest file
<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
Enter fullscreen mode Exit fullscreen mode
  1. Add this below code in your activity_main.xml
<?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"
    tools:context=".MainActivity">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="200dp"
        android:layout_height="150dp"
        android:layout_marginTop="106dp"
        android:layout_marginBottom="96dp"
        app:cardCornerRadius="30dp"
        app:layout_constraintBottom_toTopOf="@+id/idTVHead"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/idIVLogo"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:scaleType="centerCrop"
            android:contentDescription="@string/scanner_image"
            android:src="@drawable/scanimg" />

    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:cardCornerRadius="18dp"
        app:layout_constraintBottom_toTopOf="@+id/idBTNCapture"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/cardView">

    <TextView
        android:id="@+id/idTVHead"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/idIVLogo"
        android:layout_centerHorizontal="true"
        android:gravity="center"
        android:padding="15dp"
        android:text="Welcome To Text Detector"
        android:textAlignment="center"
        android:textColor="@color/black"
        android:textSize="20sp"
        android:textStyle="bold" />

    </androidx.cardview.widget.CardView>

    <!--This button is used to go in Scanner Activity-->

    <Button
        android:id="@+id/idBTNCapture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/idTVHead"
        android:layout_marginBottom="205dp"
        android:background="@drawable/button_back"
        android:text="Capture Image"
        android:textAllCaps="false"
        app:backgroundTint="@color/teal_700"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/idTVHead" />

</androidx.constraintlayout.widget.ConstraintLayout>
Enter fullscreen mode Exit fullscreen mode
  1. Add this below code in your MainActivity.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // this will hide status bar in this activity
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_main);

        // Initialize Button
        Button captureButton = findViewById(R.id.idBTNCapture);

        // add onclicklistener on button
        captureButton.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, ScannerActivity.class);
            startActivity(intent);
        });

    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Create a new Activity, name it as Scanner Activity or whatever you like. Add the below code in activity_scanner.xml
<?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"
    tools:context=".ScannerActivity">

    <!--This CardView Contains imageView is where clicked image will show up-->

    <androidx.cardview.widget.CardView
        android:id="@+id/cardView2"
        android:layout_width="200dp"
        android:layout_height="150dp"
        android:layout_marginTop="50dp"
        app:cardCornerRadius="15dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/idIVCaptureImage"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="@string/scanner_image"
            android:scaleType="centerCrop"
            android:src="@drawable/scanimg" />

    </androidx.cardview.widget.CardView>

    <!--This CardView Contains text view that will show the results-->

    <androidx.cardview.widget.CardView
        android:id="@+id/cardView3"
        android:layout_width="300dp"
        android:layout_height="200dp"
        android:layout_marginTop="30dp"
        app:cardCornerRadius="18dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/cardView2">

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

            <TextView
                android:id="@+id/idIvDetectedText"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:padding="20dp"
                android:text="Your Result Will Appear Here"
                android:textAlignment="center"
                android:textColor="@color/black"
                android:textSize="20sp"
                android:textStyle="bold" />

        </ScrollView>

    </androidx.cardview.widget.CardView>

    <!--This button is use to click picture-->

    <Button
        android:id="@+id/idBTNSnap"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/idIvDetectedText"
        android:layout_marginStart="91dp"
        android:layout_marginTop="82dp"
        android:background="@drawable/button_back"
        android:text="Snap"
        android:textAllCaps="false"
        app:backgroundTint="@color/teal_700"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/cardView3" />

<!--This button is used to detect text from images-->

    <Button
        android:id="@+id/idBTNDetect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/idBTNSnap"
        android:layout_marginTop="82dp"
        android:layout_marginEnd="82dp"
        android:background="@drawable/button_back"
        android:text="Detect"
        android:textAllCaps="false"
        app:backgroundTint="@color/teal_700"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/cardView3" />

</androidx.constraintlayout.widget.ConstraintLayout>
Enter fullscreen mode Exit fullscreen mode
  1. Add this below code in ScannerActivity.java
public class ScannerActivity extends AppCompatActivity {

    // Initialize variables
    private ImageView captureIV;
    private TextView resultTV;
    private Bitmap imageBitmap;

    static final int REQUEST_IMAGE_CAPTURE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // this will hide status bar in this activity
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_scanner);

        captureIV = findViewById(R.id.idIVCaptureImage);
        resultTV = findViewById(R.id.idIvDetectedText);
        Button snapBTN = findViewById(R.id.idBTNSnap);
        Button detectBTN = findViewById(R.id.idBTNDetect);

        // set onclicklistener
        detectBTN.setOnClickListener(v -> {
            if (captureIV.getDrawable()==null){
                Toast.makeText(ScannerActivity.this, "Failed to fetch Image", Toast.LENGTH_SHORT).show();
            }else {
                detectText();
            }
        });

        // set onclicklistener
        snapBTN.setOnClickListener(v -> {

            if (checkPermission()){
                captureImage();
            }else {
                requestPermission();
            }

        });

    }

    // check Camera Permission
    private boolean checkPermission(){
        int camerpermission = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);
        return camerpermission == PackageManager.PERMISSION_GRANTED;
    }

    // Request Camera Permission
    private void requestPermission(){
        int PERMISSION_CODE = 200;
        ActivityCompat.requestPermissions(this, new String[]{CAMERA}, PERMISSION_CODE);
    }

    // Open Camera
    @SuppressLint("QueryPermissionsNeeded")
    private void captureImage(){
        Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePicture.resolveActivity(getPackageManager())!=null){
            startActivityForResult(takePicture,REQUEST_IMAGE_CAPTURE);
        }
    }

    // Show toast on the user response on Permission Request
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (grantResults.length>0){
            boolean cameraPermision = grantResults[0] == PackageManager.PERMISSION_GRANTED;
            if (cameraPermision){
                Toast.makeText(this, "Permissions Granted", Toast.LENGTH_SHORT).show();
                captureImage();
            }else {
                Toast.makeText(this, "Permissions Denied", Toast.LENGTH_SHORT).show();
            }
        }
    }

    // After detecting data add that data to text view
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK){
            Bundle extras = Objects.requireNonNull(data).getExtras();
            imageBitmap = (Bitmap) extras.get("data");
            captureIV.setImageBitmap(imageBitmap);
        }
    }

    // Detect text in image
    private void detectText(){
        InputImage image = InputImage.fromBitmap(imageBitmap,0);
        TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
        Task<Text> result = recognizer.process(image).addOnSuccessListener(text -> {
            StringBuilder result1 = new StringBuilder();
            for (Text.TextBlock block: text.getTextBlocks()){
                String blockText = block.getText();
                Point[] blockCornerPoint = block.getCornerPoints();
                Rect blockFrame = block.getBoundingBox();
                for (Text.Line line: block.getLines()){
                    String lineText = line.getText();
                    Point[] lineCornerPoint = line.getCornerPoints();
                    Rect linREct = line.getBoundingBox();
                    for (Text.Element element: line.getElements()){
                        String elementText = element.getText();
                        result1.append(elementText);
                    }

                    resultTV.setText(blockText);
                }
            }
        }).addOnFailureListener(e -> Toast.makeText(ScannerActivity.this, "Fail To Detect Text"+e.getMessage(), Toast.LENGTH_SHORT).show());

    }
}
Enter fullscreen mode Exit fullscreen mode

Output -

 Alt text

Thats it guys. Let me know your thoughts in the comments. Here is the Complete Source Code for this project.

Top comments (2)

Collapse
 
bhushant24 profile image
BhushanT24

'startActivityForResult(android.content.Intent, int)' is deprecated
I am getting this error.
Can anyone helpme on this

Collapse
 
dilmohit profile image
Dilmohit Author • Edited on

This method is deprecated. This solution could help Click Here
For Both Java and Kotlin

🌚 Browsing with dark mode makes you a better developer by a factor of exactly 40.

It's a scientific fact.