!!!!!!!!! The following content is the author’s original, first in the nuggets platform. Without the consent and permission of the original author, any person, any organization shall not be reproduced in any form. It is not easy to be original. If I have provided some help to your problem, I hope I can get your support.

0. Put it first

PaddleOcr: paddleOcr: paddleOcr: paddleOcr: paddleOcr: paddleOcr: paddleOcr: paddleOcr

But for a variety of reasons, the company is still looking for a direct Ocr SDK solution for Android devices. After a search and search on the Internet, found Baidu AI – text recognition provided offline SDK.

Why do we do apicloud modules? Because our company android APP development technology stack is mainly used in Apicloud, so this tutorial: Apicloud project how to develop Baidu Android OCR SDK module

Technical requirements for this tutorial: 1. It is better to be familiar with module development in Apicloud (if you have not developed modules, it is ok, just read the official module development video tutorial link 2). Basic knowledge of android native development.

1. Environment preparation

  • Development tools:

Android Studio download link ApiCloud Studio download link

  • The project download

Baidu Ocr SDK: Baidu offline SDK is charged, a single device licensing fee 299. However, the official also provides two free trial authorization, activation period of 30 days. Please go to Baidu AI background to apply and download the SDK

2. Import Baidu SDK DEMO into Android Studio and run it

  • There is no problem importing Baidu SDK Demo. After you configure the local SDK, NDK and JDK path, you can run the demo on Android devices.

Note: Baidu SDK should have requirements for Android version, test down on a few devices at hand: Android 5.1.1x does not support Android 10 support other versions of devices have not been tested

  • Baidu background activation authorization code

After applying for trial, it will automatically allocate 2 trial versions of authorization, enter the background “Add serial number”, and then wait for a moment to copy the sequence number generated below:

  • Modify the authorization code and run it

Modify the initLicense method in PredictorWrapper to replace the serial number with the one just generated in the previous step

    public static boolean initLicense(Activity activity, TextView textView) {
        // Obtain authentication information about local devices and applications
        BDLicenseLocalInfo bdLicenseLocalInfo =
                AndroidLicenser.getInstance().authGetLocalInfo(activity, Predictor.getAlgorithmId());
        Log.d(TAG, "BDLicenseLocalInfo :" + bdLicenseLocalInfo.toString());

        // Automatic online activation
        int ret = BDLicenseActivator.initLicenseOnLine(activity, "BADH-XXXX-XXXX-VXVY"."", Predictor.getAlgorithmId());
        if(ret ! =0) {
            setTextViewOnUiThread(activity, textView, "Authentication failed");
        } else {
            setTextViewOnUiThread(activity, textView, "Authentication successful");
        }
        return true;
    }
Copy the code
  • Select connect device to debug run

USB connects to the device, select the device in Android Studio to run directly on the device. If no device is selected, check the following: 1. Open developer mode for the device. 2

Click Initialize. The system displays a message indicating that authentication succeeds and the model is initialized successfully

Then you can use the three ways provided in the official DEMO to obtain pictures and OCR identification

3. AndroidStudio imports Apicloud module to develop demo

After downloading and decompressing the apicloud module development demo, it is divided into Android Studio and Eclipse. We directly import the Apicloud ModulesDK folder under Android Studio directory into Android Studio

3.1 Modify the Demo project as follows:

  • Change the minimum version to 14 in gradle.properties for app and all modules. Many modules in Demo are specified as 9. However, errors will be reported during subsequent operation.
  • Add a minSdkVersion line to your app’s build.gradle. If this line is missing in demo, it will default to the lowest version 1 and keep reporting errors.
defaultConfig { applicationId project.ANDROID_BUILD_APP_PKG targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION) versionCode Integer.parseInt(project.ANDROID_BUILD_VERSION_CODE)  versionName project.ANDROID_BUILD_VERSION_NAME multiDexEnabled true }Copy the code

3.2 New Baidu Ocr Module (moduleOcr)

  • The first problem encountered:

Android Studio new modules must be androidX, otherwise the following error will be reported: Projects need to be converted to Androidx.* dependencies

  • Solution:

Modify gradle.properties: Add the following two lines:

android.useAndroidX=true
android.enableJetifier=true
Copy the code
  • Create a module named moduleOcr

Apicloud module development has rules for naming. For details, see the apicloud module development document.

  • Copy all the codes and resources under Baidu SDK, so files under jniLibs, assets files under the current module

In order to distinguish, I changed the name of the MainActivity in the SDK to TestActivity, so the TestActivity in the following code is the MainActivity in the original SDK

  • New ocrdemo.java for the module source code (note that the package name is changed to the new package name in your module) :
package com.factoryeasy.ocr;

import android.content.Intent;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;

import com.uzmap.pkg.uzcore.UZWebView;
import com.uzmap.pkg.uzcore.uzmodule.UZModule;
import com.uzmap.pkg.uzcore.uzmodule.UZModuleContext;

import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;

public class OcrDemo extends UZModule {

    public OcrDemo(UZWebView webView) {
        super(webView);
        getPermission();
    }

    public void jsmethod_ocrDemo(UZModuleContext moduleContext){
        Intent intent = new Intent(mContext, TestActivity.class);
        startActivity(intent);
    }

    void getPermission(a) {
        if(ContextCompat.checkSelfPermission(mContext, CAMERA) ! = PERMISSION_GRANTED || ContextCompat.checkSelfPermission(mContext, WRITE_EXTERNAL_STORAGE) ! = PERMISSION_GRANTED || ContextCompat.checkSelfPermission(mContext, READ_EXTERNAL_STORAGE) ! = PERMISSION_GRANTED) { ActivityCompat.requestPermissions(mContext,new String[]{CAMERA, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE}, 1); }}}Copy the code

3.3 Restoring AndroidX and adjusting module code

In order to create a new module, we have temporarily changed the device to AndroidX in Gradle. properties, but the official module does not support AndroidX when integrating, so we will change the environment back in this step. And make some adjustments to the code in moduleOcr (mainly to kick out the part that uses AndroidX)

  • Gradle. properties set the two newly added parameters to false
android.useAndroidX=false
android.enableJetifier=false
Copy the code
  • Replace build.gradle content under moduleOcr with the following content, the purpose is to remove androidX dependency in the module, and introduce Baidu SDK Lib dependency
apply plugin: 'com.android.library' Android {compileSdkVersion 28 buildToolsVersion "28.0.03" defaultConfig {minSdkVersion 14 TargetSdkVersion 28 versionCode 1 versionName "1.0"} buildTypes {release {minifyEnabled false}} sourceSets{main{ jniLibs.srcDirs = ['libs'] } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) provided files('.. /app/libs/apiEngine v1.1.0.jar') implementation files('libs/bd_unifylicense.jar') implementation files('libs/liantian.jar') implementation files('libs/ocrgeneralocr.jar') implementation 'com. Android. Support: support - v4:28.0.0'}Copy the code
  • Java source code modification:

The copy of baidu SDK Java source code to do the following modifications

  1. Find all the activities and change the inheritance from AppCompatActivity to activity
public class TestAssetsImageActivity extends Activity 
Copy the code
  1. Import any androidX-related errors reported elsewhere in your code into the corresponding other package as a tooltip

  2. Modify TestCameraImageActivity getImageStreamFromExternal, change the FileProvider package name below to get automatically, don’t write die package for baidu

if (Build.VERSION.SDK_INT >= 24) {
    uri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", picPath);
} else {
    uri = Uri.fromFile(picPath);
}
Copy the code
  1. Modify all layout files below Layout to

Androidx. Coordinatorlayout. Widget. Coordinatorlayout direct replacement for the LinearLayout

<LinearLayout 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=".TestAssetsImageActivity">
Copy the code
  1. Change the styles to replace the original content with the following
<resources>

    <! -- Base application theme. -->
    <style name="AppTheme">
        <! -- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.NoActionBar">
    </style>


</resources>
Copy the code
  1. Modify the androidmanifest.xml of the module

Replace the original content with the following package name as it was when you actually created the module. It defines the provider file, defines the activity, and declares the permission to use the app

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.factoryeasy.ocr">

    <uses-feature android:name="android.hardware.camera" />

    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application>
        <provider
            android:name="android.support.v4.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" />
        </provider>

        <activity android:name=".TestActivity"/>
        <activity android:name=".TestCameraImageActivity" />
        <activity android:name=".TestAssetsImageActivity" />
        <activity android:name=".TestCameraStreamActivity" />
        <activity android:name=".TestPhotoImageActivity" />


    </application>

</manifest>
Copy the code

After the above changes, the code compilation will pass.

3.4 App project introduces moduleOcr module

  • Add moduleOcr dependency to app build.gradle
dependencies { compile fileTree(dir: 'libs', include: [' *. Jar ']) compile 'com. Android. Support: support - v4:26.0.0' compile 'com. Android. Support: multidex: 1.0.1' five modules / / compile project(':moduleDemo') compile project(':moduleSyncInterface') compile project(':moduleRefresh') compile project(':moduleAppdelegate') compile project(':moduleOcr') }Copy the code
  • Add the following module reference to module.json in the app. uzmap directory
{
   "name":"moduleOcr"."class":"com.factoryeasy.ocr.OcrDemo"
}
Copy the code
  • Index_frm. HTML in the assets. Widget in the app directory writes the test method
Declare a module variable:var ocr = null; OCR = API. Require (OCR = API. Require (OCR = API.'moduleOcr'); Define test methods:function ocrDemo(){
   varparams = {}; ocr.ocrDemo(params); } HTML page add: <divclass='itemtitle'>0Ocr Demo</div><div class="clickbtn" tapmode="active" onclick="ocrDemo()" >Click to enter Ocr Demo</div>
Copy the code
  • Under jniLibs in app directory, copy all the SO files needed by Baidu OCR. Please note that so files distinguish between 64 bits and 32 bits, so files in the corresponding directory of Baidu SDK need to be copied to jniLibs in app respectively

It is important to note that if the directory in the screenshot below does not exist, you should manually create it because the so file under arm64-v8a will be used for the local runtime. The cloud compiler after the apicloud upload module uses the 32-bit SO under armeabi. I couldn’t find “xxx.so” is 64-bit instead of 32-bit. I couldn’t find “xxx.so” is 64-bit instead of 32-bit

  • Copy the identification model in the baidu SDK directory to the assets. Widget under the app

  • Modify the PredictorWrapper code to adjust the code below initModel as follows:

The main directory under initModelFromAssets is changed to Widget/ocrGeneralocr_Models

public static boolean initModel(Activity activity, TextView textView) {
    try {
        // Initialize the model
        int ret = Predictor.getInstance().initModelFromAssets(activity, "widget/ocrgeneralocr_models".1);
        if(ret ! =0) {
            Log.d(TAG, "initModel error : " + ret);
            setTextViewOnUiThread(activity, textView, "Model initialization failed");
            return false;
        } else {
            setTextViewOnUiThread(activity, textView, "Model initialization successful");
            return true; }}catch (Exception e) {
        setTextViewOnUiThread(activity, textView, "Model initialization failed");
        e.printStackTrace();
        return false; }}Copy the code

Why the last two changes?

  1. Because the default starting directory of initModelFromAssets in Baidu SDK is assets directory under app project, this method cannot be modified at present.
  2. For local testing, we can put ocrGeneralocr_Models directly into the assets under the app. However, when the package module is uploaded to the Apicloud server for cloud packaging, the assets resources in the app will not be added together. This will cause the module to be introduced into our real project without finding resources.
  3. After decompressing the app after the apicloud cloud packaging, I found a bit of apicloud packaging strategy: It puts all the resources in our normal project under assets/ Widgets together, so we can make a change and put the resource bundle ocrGeneralocr_Models used by Baidu SDK directly under the root directory of our project. And by adjusting the read path, you can read both the local run and the imported module after packaging.

At the end of this step, we can run the module demo of Apicloud locally and test baidu offline OCR SDK in the successful demo normally.

3.5 Packing Modules

  • The aar package of the Module will be generated in the build.outputs. Aar directory after the Module is completed. You can decompress the AAR package and ensure that the JAR package and so file under the lib have been typed into it

  • Create a directory moduleOcr, put the module AAR package in it, and create a module.json file in the same directory, the content is as follows:
{
"name":"moduleOcr"."class":"com.factoryeasy.ocr.OcrDemo"
}
Copy the code
  • Compress the directory into the moduleocr. zip package and upload it to the custom module under the Apicloud project

  • The module is added to the project and the cloud compilation tests are passed

4. ModuleOcr module was introduced into the project

  • As explained earlier, we want to place the recognition model, ocrGeneralOCR_Models, in the root directory of the project

  • The module is introduced into the business code and tested
The outermost layer declares variablesvarocr ; Reference module OCR = api.require("moduleOcr"); Module test testOcr =function () {
    var params = {};
    ocr.ocrDemo({});
}
Copy the code

So far, we have completed the module of APicloud Baidu offline Ocr SDK: the function is relatively simple, which is directly built-in Baidu SDK. Later, we can make some customized modifications in the module according to our own project needs.

5. Summary of key steps

1. How to place resources under assets of the entire project? Cloud packaging packages resources under assets.widget by placing the resource directory directly under the root of the Apicloud project

2. How do I include resources under a module in an AAR package? The build.gradle module should contain the following configuration:

sourceSets{
   main{
       jniLibs.srcDirs = ['libs']}}Copy the code
  1. The 32 and 64 bits of the so file are clearly distinguishable and placed in different lib directories

Arm64-v8a: 64-bit so Armeabi: 32-bit so Armeabi – V7A: 32-bit SO

6. Reference links

  • Apicloud official help document

  • Apicloud module development video

  • Baidu Ai Offline Ocr SDK help document