diff --git a/FreeFormOCRSample1/.gitignore b/FreeFormOCRSample1/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/FreeFormOCRSample1/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/FreeFormOCRSample1/app/.gitignore b/FreeFormOCRSample1/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/FreeFormOCRSample1/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/FreeFormOCRSample1/app/build.gradle b/FreeFormOCRSample1/app/build.gradle new file mode 100644 index 0000000..0391cc6 --- /dev/null +++ b/FreeFormOCRSample1/app/build.gradle @@ -0,0 +1,39 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'com.zebra.freeformocrsample1' + compileSdk 33 + + defaultConfig { + applicationId "com.zebra.freeformocrsample1" + minSdk 30 + targetSdk 33 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.9.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' +} \ No newline at end of file diff --git a/FreeFormOCRSample1/app/proguard-rules.pro b/FreeFormOCRSample1/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/FreeFormOCRSample1/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/FreeFormOCRSample1/app/src/androidTest/java/com/zebra/freeformocrsample1/ExampleInstrumentedTest.java b/FreeFormOCRSample1/app/src/androidTest/java/com/zebra/freeformocrsample1/ExampleInstrumentedTest.java new file mode 100644 index 0000000..b009bb1 --- /dev/null +++ b/FreeFormOCRSample1/app/src/androidTest/java/com/zebra/freeformocrsample1/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.zebra.freeformocrsample1; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.zebra.freeformocrsample1", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/FreeFormOCRSample1/app/src/main/AndroidManifest.xml b/FreeFormOCRSample1/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c237c7b --- /dev/null +++ b/FreeFormOCRSample1/app/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/ImageProcessing.java b/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/ImageProcessing.java new file mode 100644 index 0000000..066383d --- /dev/null +++ b/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/ImageProcessing.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2018-2023 Zebra Technologies Corp + * All rights reserved. + */ +package com.zebra.freeformocrsample1; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.ImageFormat; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.YuvImage; + +import java.io.ByteArrayOutputStream; + +public class ImageProcessing { + + private final String IMG_FORMAT_YUV = "YUV"; + private final String IMG_FORMAT_Y8 = "Y8"; + + private static ImageProcessing instance = null; + + public static ImageProcessing getInstance() { + + if (instance == null) { + instance = new ImageProcessing(); + } + return instance; + } + + private ImageProcessing() { + //Private Constructor + } + + public Bitmap getBitmap(byte[] data, String imageFormat, int orientation, int stride, int width, int height) + { + if(imageFormat.equalsIgnoreCase(IMG_FORMAT_YUV)) + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, width, height, new int[]{stride, stride}); + yuvImage.compressToJpeg(new Rect(0, 0, stride, height), 100, out); + yuvImage.getYuvData(); + byte[] imageBytes = out.toByteArray(); + if(orientation != 0) + { + Matrix matrix = new Matrix(); + matrix.postRotate(orientation); + Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); + return Bitmap.createBitmap(bitmap, 0 , 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + } + else + { + return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); + } + } + else if(imageFormat.equalsIgnoreCase(IMG_FORMAT_Y8)) + { + return convertYtoJPG_CPU(data, orientation, stride, height); + } + + return null; + } + + + private Bitmap convertYtoJPG_CPU(byte[] data, int orientation, int stride, int height) + { + int mLength = data.length; + int [] pixels = new int[mLength]; + for(int i = 0; i < mLength; i++) + { + int p = data[i] & 0xFF; + pixels[i] = 0xff000000 | p << 16 | p << 8 | p; + } + if(orientation != 0) + { + Matrix matrix = new Matrix(); + matrix.postRotate(orientation); + Bitmap bitmap = Bitmap.createBitmap(pixels, stride, height, Bitmap.Config.ARGB_8888); + return Bitmap.createBitmap(bitmap, 0 , 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + } + else + { + return Bitmap.createBitmap(pixels, stride, height, Bitmap.Config.ARGB_8888); + } + } + +} \ No newline at end of file diff --git a/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/IntentKeys.java b/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/IntentKeys.java new file mode 100644 index 0000000..53bff06 --- /dev/null +++ b/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/IntentKeys.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018-2023 Zebra Technologies Corp + * All rights reserved. + */ +package com.zebra.freeformocrsample1; + +public class IntentKeys { + + public static final String DATA_NEXT_URI = "next_data_uri"; + public static final String STRIDE = "stride"; + public static final String RAW_DATA = "raw_data"; + public static final String ORIENTATION = "orientation"; + public static final String IMAGE_FORMAT = "imageformat"; + public static final String IMAGE_WIDTH = "width"; + public static final String IMAGE_HEIGHT = "height"; + + public static final String COMMAND_IDENTIFIER_CREATE_PROFILE = "CREATE_PROFILE"; + public static final String COMMAND_IDENTIFIER_EXTRA = "COMMAND_IDENTIFIER"; + public static final String RESULT_ACTION = "com.symbol.datawedge.api.RESULT_ACTION"; + + public static final String DATA_TAG = "com.symbol.datawedge.data"; + + public static final String REGISTER_NOTIFICATION = "com.symbol.datawedge.api.REGISTER_FOR_NOTIFICATION"; + public static final String UNREGISTER_NOTIFICATION = "com.symbol.datawedge.api.UNREGISTER_FOR_NOTIFICATION"; + + public static final String STRING_DATA_KEY = "string_data"; + public static final String DATAWEDGE_API_NAME = "com.symbol.datawedge.api.APPLICATION_NAME"; + public static final String NOTIFICATION_TYPE = "com.symbol.datawedge.api.NOTIFICATION_TYPE"; + public static final String NOTIFICATION = "com.symbol.datawedge.api.NOTIFICATION"; + + + public static final String EXTRA_GET_PROFILES_LIST = "com.symbol.datawedge.api.GET_PROFILES_LIST"; + public static final String EXTRA_DELETE_PROFILE = "com.symbol.datawedge.api.DELETE_PROFILE"; + + public static final String SET_CONFIG = "com.symbol.datawedge.api.SET_CONFIG"; + + public static final String PROFILE_NAME = "FreeFormScanningProfile"; + public static final String DATAWEDGE_API_ACTION = "com.symbol.datawedge.api.ACTION"; + public static final String INTENT_OUTPUT_ACTION = "com.zebra.id_scanning.ACTION"; + public static final String SELECTED_WORKFLOW = "free_form_ocr"; + public static final String NOTIFICATION_ACTION = "com.symbol.datawedge.api.NOTIFICATION_ACTION"; + public static final String NOTIFICATION_TYPE_WORKFLOW_STATUS = "WORKFLOW_STATUS"; + public static final String KEY_STRING_DATA = "string_data"; + public static final String KEY_BLOCK_LABEL = "block_label"; + public static final String JSON_IMAGE_FORMAT = "imageformat"; + public static final String KEY_GROUP_ID = "group_id"; + + public static final String EXTRA_RESULT_GET_PROFILES_LIST = "com.symbol.datawedge.api.RESULT_GET_PROFILES_LIST"; + public static final String DATAWEDGE_PACKAGE = "com.symbol.datawedge"; + + public static final String EXTRA_SOFT_SCAN_TRIGGER = "com.symbol.datawedge.api.SOFT_SCAN_TRIGGER"; + public static final String INTENT_RESULT_CODE_FAILURE = "FAILURE"; + + +} diff --git a/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/MainActivity.java b/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/MainActivity.java new file mode 100644 index 0000000..a63729b --- /dev/null +++ b/FreeFormOCRSample1/app/src/main/java/com/zebra/freeformocrsample1/MainActivity.java @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2018-2023 Zebra Technologies Corp + * All rights reserved. + */ +package com.zebra.freeformocrsample1; + +import static com.zebra.freeformocrsample1.IntentKeys.DATAWEDGE_API_ACTION; +import static com.zebra.freeformocrsample1.IntentKeys.INTENT_OUTPUT_ACTION; +import static com.zebra.freeformocrsample1.IntentKeys.PROFILE_NAME; +import static com.zebra.freeformocrsample1.IntentKeys.SELECTED_WORKFLOW; + +import androidx.appcompat.app.AppCompatActivity; + +import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MainActivity extends AppCompatActivity { + + TextView txtWorkflowStatus, txtProfileStatus = null; + LinearLayout layoutRegion = null; + Button btnClear; + + private final String TAG = MainActivity.class.getCanonicalName(); + + + @SuppressLint("MissingInflatedId") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + txtWorkflowStatus = findViewById(R.id.txtStatus); + txtProfileStatus = findViewById(R.id.txtProfileStatus); + btnClear = findViewById(R.id.btnClear); + layoutRegion = findViewById(R.id.layoutRegeions); + + registerReceivers(); + } + private void registerReceivers() { + + IntentFilter filter = new IntentFilter(); + filter.addAction(IntentKeys.RESULT_ACTION); + filter.addAction(IntentKeys.NOTIFICATION_ACTION); + filter.addAction(IntentKeys.INTENT_OUTPUT_ACTION); + filter.addCategory(Intent.CATEGORY_DEFAULT); + registerReceiver(broadcastReceiver, filter); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(broadcastReceiver); + } + + @Override + protected void onPause() { + super.onPause(); + registerUnregisterForNotifications(false, IntentKeys.NOTIFICATION_TYPE_WORKFLOW_STATUS); + } + + @Override + protected void onResume() { + super.onResume(); + queryProfileList(); + registerUnregisterForNotifications(true, IntentKeys.NOTIFICATION_TYPE_WORKFLOW_STATUS); + } + + void registerUnregisterForNotifications(boolean register, String type) { + Bundle b = new Bundle(); + b.putString(IntentKeys.DATAWEDGE_API_NAME, getPackageName()); + b.putString(IntentKeys.NOTIFICATION_TYPE, type); + Intent i = new Intent(); + i.putExtra("APPLICATION_PACKAGE", getPackageName()); + i.setAction(DATAWEDGE_API_ACTION); + i.setPackage(IntentKeys.DATAWEDGE_PACKAGE); + + if (register) + i.putExtra(IntentKeys.REGISTER_NOTIFICATION, b); + else + i.putExtra(IntentKeys.UNREGISTER_NOTIFICATION, b); + + this.sendBroadcast(i); + } + + void createProfile() { + + Bundle bMain = new Bundle(); + + Bundle bConfigWorkflow = new Bundle(); + ArrayList bundlePluginConfig = new ArrayList<>(); + + /*###### Configurations for Workflow Input [Start] ######*/ + bConfigWorkflow.putString("PLUGIN_NAME", "WORKFLOW"); + bConfigWorkflow.putString("RESET_CONFIG", "true"); //Reset existing configurations of barcode input plugin + + bConfigWorkflow.putString("workflow_input_enabled", "true"); + bConfigWorkflow.putString("selected_workflow_name", SELECTED_WORKFLOW); + bConfigWorkflow.putString("workflow_input_source", "1"); + + + bConfigWorkflow.putParcelableArrayList("PARAM_LIST", getWorkflowInputParams()); + bundlePluginConfig.add(bConfigWorkflow); + /*###### Configurations for Workflow Input [Finish] ######*/ + + /*###### Configurations for Intent Output [Start] ######*/ + Bundle bConfigIntent = new Bundle(); + Bundle bParamsIntent = new Bundle(); + bConfigIntent.putString("PLUGIN_NAME", "INTENT"); + bConfigIntent.putString("RESET_CONFIG", "true"); //Reset existing configurations of intent output plugin + bParamsIntent.putString("intent_output_enabled", "true"); //Enable intent output plugin + bParamsIntent.putString("intent_action", INTENT_OUTPUT_ACTION); //Set the intent action + bParamsIntent.putString("intent_category", "android.intent.category.DEFAULT"); //Set a category for intent + bParamsIntent.putInt("intent_delivery", 2); // Set intent delivery mechaism, Use "0" for Start Activity, "1" for Start Service, "2" for Broadcast, "3" for start foreground service + bConfigIntent.putBundle("PARAM_LIST", bParamsIntent); + bundlePluginConfig.add(bConfigIntent); + /*###### Configurations for Intent Output [Finish] ######*/ + + //Putting the INTENT and BARCODE plugin settings to the PLUGIN_CONFIG extra + bMain.putParcelableArrayList("PLUGIN_CONFIG", bundlePluginConfig); + + + /*###### Associate this application to the profile [Start] ######*/ + Bundle configApplicationList = new Bundle(); + configApplicationList.putString("PACKAGE_NAME", getPackageName()); + configApplicationList.putStringArray("ACTIVITY_LIST", new String[]{"*"}); + bMain.putParcelableArray("APP_LIST", new Bundle[]{ + configApplicationList + }); + /* ###### Associate this application to the profile [Finish] ######*/ + + bMain.putString("PROFILE_NAME", PROFILE_NAME); //Specify the profile name + bMain.putString("PROFILE_ENABLED", "true"); //Enable the profile + bMain.putString("CONFIG_MODE", "CREATE_IF_NOT_EXIST"); + bMain.putString("RESET_CONFIG", "true"); + + Intent iSetConfig = new Intent(); + + iSetConfig.setAction(DATAWEDGE_API_ACTION); + iSetConfig.setPackage(IntentKeys.DATAWEDGE_PACKAGE); + iSetConfig.putExtra(IntentKeys.SET_CONFIG, bMain); + iSetConfig.putExtra("SEND_RESULT", "COMPLETE_RESULT"); + iSetConfig.putExtra(IntentKeys.COMMAND_IDENTIFIER_EXTRA, + IntentKeys.COMMAND_IDENTIFIER_CREATE_PROFILE); + this.sendBroadcast(iSetConfig); + + } + + private void deleteProfile() + { + Intent i = new Intent(); + i.setAction(IntentKeys.DATAWEDGE_API_ACTION); + i.setPackage(IntentKeys.DATAWEDGE_PACKAGE); + i.putExtra(IntentKeys.EXTRA_DELETE_PROFILE, IntentKeys.PROFILE_NAME); + sendBroadcast(i); + } + + private void queryProfileList() + { + Intent i = new Intent(); + i.setAction(IntentKeys.DATAWEDGE_API_ACTION); + i.setPackage(IntentKeys.DATAWEDGE_PACKAGE); + i.putExtra(IntentKeys.EXTRA_GET_PROFILES_LIST, ""); + sendBroadcast(i); + } + + public void btnOnClickCreateProfile(View view) + { + createProfile(); + } + + public void btnOnClickClearScannedData(View view) + { + layoutRegion.removeAllViews(); + } + + public void btnOnClickScan(View view) + { + Intent i = new Intent(); + i.setPackage(IntentKeys.DATAWEDGE_PACKAGE); + i.setAction(DATAWEDGE_API_ACTION); + i.putExtra(IntentKeys.EXTRA_SOFT_SCAN_TRIGGER, "TOGGLE_SCANNING"); + this.sendBroadcast(i); + } + + private Bundle getWorkflowParamBundle(String workflowName) { + Bundle paramList = new Bundle(); + paramList.putString("workflow_name", workflowName); + paramList.putString("workflow_input_source", "1"); + + Bundle paramSetFeedbackModule = new Bundle(); + paramSetFeedbackModule.putString("module", "BarcodeTrackerModule"); + Bundle moduleParamsFeedback = new Bundle(); + moduleParamsFeedback.putString("decode_and_highlight_barcodes", "1"); + paramSetFeedbackModule.putBundle("module_params", moduleParamsFeedback); + + ArrayList paramSetList = new ArrayList<>(); + paramSetList.add(paramSetFeedbackModule); + + paramList.putParcelableArrayList("workflow_params", paramSetList); + return paramList; + } + + private ArrayList getWorkflowInputParams() { + ArrayList workFlowList = new ArrayList<>(); + workFlowList.add(getWorkflowParamBundle(SELECTED_WORKFLOW)); + return workFlowList; + } + + BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { + @SuppressLint("Range") + @Override + public void onReceive(Context context, Intent intent) { + + String action = intent.getAction(); + Bundle extras = intent.getExtras(); + + // Check the profile list returned from the EXTRA_GET_PROFILES_LIST method + /* ###### Processing quarried profile list [Start] ###### */ + if (intent.hasExtra(IntentKeys.EXTRA_RESULT_GET_PROFILES_LIST)) { + + String[] profilesList = extras. + getStringArray(IntentKeys.EXTRA_RESULT_GET_PROFILES_LIST); + List arrProfileList = Arrays.asList(profilesList); + // Check if the profile list contains the DocumentCapture profile + if (arrProfileList.contains(PROFILE_NAME)) { + updateProfileStatus("Profile already exists, not creating the profile"); + // Profile exists, no need to create the profile again + } else { + // Profile does not exist, create the profile + updateProfileStatus("Profile does not exists. Creating the profile.."); + createProfile(); + } + + } + /* ###### Processing queried profile list [Finish] ###### */ + + /* ###### Processing the result of CREATE_PROFILE [Start] ###### */ + else if (extras.containsKey(IntentKeys.COMMAND_IDENTIFIER_EXTRA)) { + + // Check if the create profile command succeeded for + // Barcode Input and Intent Output modules + if (extras.getString(IntentKeys.COMMAND_IDENTIFIER_EXTRA) + .equalsIgnoreCase(IntentKeys.COMMAND_IDENTIFIER_CREATE_PROFILE)) { + ArrayList result_list = (ArrayList) extras.get("RESULT_LIST"); + if (result_list != null && result_list.size() > 0) { + boolean allSuccess = true; + String resultInfo = ""; + // Iterate through the result list for each module + for (Bundle result : result_list) { + if (result.getString("RESULT") + .equalsIgnoreCase(IntentKeys.INTENT_RESULT_CODE_FAILURE)) { + + // Profile creation failed for the module. + // Getting more information on what failed + allSuccess = false; + resultInfo = "Module: " + result + .getString("MODULE") + "\n"; // Name of the module that failed + resultInfo += "Result code: " + result + .getString("RESULT_CODE") + "\n"; // Information on the type of the failure + if (result.containsKey("SUB_RESULT_CODE")) // More Information on the failure if exists + resultInfo += "\tSub Result code: " + result + .getString("SUB_RESULT_CODE") + "\n"; + + break; // Breaking the loop as there is a failure + } else { + // Profile creation success for the module. + resultInfo = "Module: " + result.getString("MODULE") + "\n"; + resultInfo += "Result: " + result.getString("RESULT") + "\n"; + } + } + + if (allSuccess) { + updateProfileStatus("Profile created successfully"); + } else { + + updateProfileStatus("Profile creation failed!\n\n" + resultInfo); + deleteProfile(); + } + } + } + } + /* ###### Processing the result of CREATE_PROFILE [End] ###### */ + + /* ###### Processing the result of NOTIFICATION_ACTION [Start] ###### */ + else if (action.equals(IntentKeys.NOTIFICATION_ACTION)) { + + if (intent.hasExtra(IntentKeys.NOTIFICATION)) { + Bundle b = intent.getBundleExtra(IntentKeys.NOTIFICATION); + String NOTIFICATION_TYPE = b.getString("NOTIFICATION_TYPE"); + if (NOTIFICATION_TYPE != null) { + switch (NOTIFICATION_TYPE) { + case IntentKeys.NOTIFICATION_TYPE_WORKFLOW_STATUS: + //Must register for scanner status notification + String status = b.getString("STATUS"); + updateWorkflowStatus(status); + break; + } + + } + } + } + /* ###### Processing the result of NOTIFICATION_ACTION [End] ###### */ + + /* ###### Processing the result of INTENT_OUTPUT [Start] ###### */ + else if (action.equalsIgnoreCase(INTENT_OUTPUT_ACTION)) { + TextView txtBarcodeData = new TextView(getApplicationContext()); + Bundle bundle = intent.getExtras(); + String jsonData = bundle.getString(IntentKeys.DATA_TAG); + try { + JSONArray jsonArray = new JSONArray(jsonData); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + if (jsonObject.has(IntentKeys.STRING_DATA_KEY)) { + //String data + outputFreeFormOcrStringData(jsonArray,txtBarcodeData); + } else if(jsonObject.has("uri")){ + //Image data + String uri = jsonObject.getString("uri"); + outputFreeFormOCRImageData(uri,jsonObject); + } + + } + } catch (Exception ex) { + Log.e(TAG, "Error to receive data: "+ex.getMessage() ); + } + + } + /* ###### Processing the result of INTENT_OUTPUT [End] ###### */ + } + }; + + + + private void outputFreeFormOcrStringData(JSONArray array, TextView txtBarcodeData) throws JSONException { + + String fullDataString = ""; + String prevBlock = null; + String prevGroup = null; + for (int i = 0; i < array.length(); i++) { + try { + if(!array.getJSONObject(i).has(IntentKeys.JSON_IMAGE_FORMAT)) + { + JSONObject jsonObject = array.getJSONObject(i); + String blockLabel = jsonObject.get(IntentKeys.KEY_BLOCK_LABEL).toString(); + String groupLabel = jsonObject.get(IntentKeys.KEY_GROUP_ID).toString(); + String stringData = jsonObject.get(IntentKeys.KEY_STRING_DATA).toString(); + + if (prevBlock != null && !prevBlock.equals(blockLabel)) + fullDataString = fullDataString + "\n\n"; + + if (prevGroup != null && !prevGroup.equals(groupLabel)) + fullDataString = fullDataString + "\n"; + + fullDataString = fullDataString + stringData + " "; + + prevGroup = groupLabel; + prevBlock = blockLabel; + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + + txtBarcodeData.setText(fullDataString); + showInUI(txtBarcodeData, null); + + } + + private synchronized void outputFreeFormOCRImageData(String uri, JSONObject jsonObject) throws IOException, JSONException { + Cursor cursor = getContentResolver().query(Uri.parse(uri), null, null, null); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + if (cursor != null) { + cursor.moveToFirst(); + baos.write(cursor.getBlob(cursor.getColumnIndex(IntentKeys.RAW_DATA))); + String nextURI = cursor.getString(cursor.getColumnIndex(IntentKeys.DATA_NEXT_URI)); + while (nextURI != null && !nextURI.isEmpty()) { + Cursor cursorNextData = getContentResolver().query(Uri.parse(nextURI), + null, null, null); + if (cursorNextData != null) { + cursorNextData.moveToFirst(); + baos.write(cursorNextData.getBlob(cursorNextData.getColumnIndex(IntentKeys.RAW_DATA))); + nextURI = cursorNextData.getString(cursorNextData.getColumnIndex(IntentKeys.DATA_NEXT_URI)); + + + cursorNextData.close(); + } + + } + cursor.close(); + } + + int width = 0; + int height = 0; + int stride = 0; + int orientation = 0; + String imageFormat = ""; + + width = jsonObject.getInt(IntentKeys.IMAGE_WIDTH); + height = jsonObject.getInt(IntentKeys.IMAGE_HEIGHT); + stride = jsonObject.getInt(IntentKeys.STRIDE); + orientation = jsonObject.getInt(IntentKeys.ORIENTATION); + imageFormat = jsonObject.getString(IntentKeys.IMAGE_FORMAT); + + Bitmap bitmap = ImageProcessing.getInstance().getBitmap(baos.toByteArray(), imageFormat, orientation, stride, width, height); + + final ImageView img = new ImageView(getApplicationContext()); + img.setImageBitmap(bitmap); + showInUI(null, img); + } + + private void showInUI(final TextView textView, final ImageView imageView) + { + runOnUiThread(new Runnable() { + @Override + public void run() { + + if(textView != null) + layoutRegion.addView(textView); + + if(imageView != null) + layoutRegion.addView(imageView); + } + }); + } + + void updateWorkflowStatus(final String status) + { + runOnUiThread(new Runnable() { + @Override + public void run() { + txtWorkflowStatus.setText("Workflow Status: " + status); + } + }); + } + + void updateProfileStatus(final String status) + { + runOnUiThread(new Runnable() { + @Override + public void run() { + txtProfileStatus.setText("Profile Status: " + status); + } + }); + } +} \ No newline at end of file diff --git a/FreeFormOCRSample1/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/FreeFormOCRSample1/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/FreeFormOCRSample1/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/FreeFormOCRSample1/app/src/main/res/drawable/ic_launcher_background.xml b/FreeFormOCRSample1/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/FreeFormOCRSample1/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeFormOCRSample1/app/src/main/res/layout/activity_main.xml b/FreeFormOCRSample1/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..67a19a3 --- /dev/null +++ b/FreeFormOCRSample1/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,105 @@ + + + +