概要
[コンテンツ プロバイダの使用] オプションを使用すると、アプリケーションで DataWedge のコンテンツ プロバイダを利用して、画像 (主に署名読み取りや NextGen SimulScan を使用してスキャンした画像) などの 500KB を超えるファイルからスキャンしたデータを取得できます。コンテンツ プロバイダは、アプリ間で共有できるようにデータをカプセル化する Android アプリ コンポーネントです。
DataWedge のコンテンツ プロバイダは、Android の ContentProvider
クラス オブジェクトを通じて一度に 768KB (786,432 バイト) の未加工データしか送信できません。スキャンしたデータがこの制限を超えると、残りのデータは、同じサイズ制限の後続の ContentProvider
オブジェクト (URI は最初の ContentProvider
に含まれている) で送信されます。URI とは、コンテンツ プロバイダに問い合わせてデータを取得するために使用される文字列のことで、プロバイダとパスが含まれています。ContentProvider
を個別の部分に分割するこのプロセスは、未加工のスキャン データが実際のファイル サイズに達するまで繰り返されます。次に、クライアント アプリケーションで、すべての ContentProviders
からの未加工データを連結して、最終的な完全な未加工データ オブジェクトを byte[] 形式で再構築する必要があります。
コンテンツ プロバイダ
コンテンツ プロバイダを使用してデータを取得するには、次のセクションの手順に従います。
1.Android マニフェストを変更
次の権限を Android アプリケーションのマニフェストに追加して、そのアプリケーションから DataWedge コンテンツ プロバイダにアクセスできるようにする必要があります。
<uses-permission android:name="com.symbol.datawedge.permission.contentprovider" />
2.コンテンツ プロバイダを有効にする
次のオプションのいずれかを選択して、コンテンツ プロバイダを有効にします。
2a.DataWedge UI を介したコンテンツ プロバイダの有効化
DataWedge UI を介してコンテンツ プロバイダ オプションを有効にするには、DataWedge プロファイルの [インテント出力] セクションに移動し、[インテント出力] を有効にします。
インテント出力
次に、[コンテンツ プロバイダの使用] オプションを有効にします。
コンテンツ プロバイダの使用
2bDataWedge インテント API を介したコンテンツ プロバイダの有効化
DataWedge Intent API を介してコンテンツ プロバイダ オプションを有効にするには、インテント キー intent_use_content_provider を、サポートされている値 true または false とともに使用します。
次のサンプル コードでは、プロファイル Profile009 のコンテンツ プロバイダを有効にする方法を示しています。
Bundle bMain = new Bundle();
ArrayList<Bundle> bundlePluginConfig = new ArrayList<>();
Bundle bConfigIntent = new Bundle();
Bundle bParamsIntent = new Bundle();
bParamsIntent.putString("intent_output_enabled", "true");
bParamsIntent.putString("intent_use_content_provider", "true");
bConfigIntent.putString("PLUGIN_NAME", "INTENT");
bConfigIntent.putString("RESET_CONFIG", "true");
bConfigIntent.putBundle("PARAM_LIST", bParamsIntent);
bundlePluginConfig.add(bConfigIntent);
bMain.putParcelableArrayList("PLUGIN_CONFIG", bundlePluginConfig);
bMain.putString("PROFILE_NAME", "Profile009");
bMain.putString("PROFILE_ENABLED", "true");
bMain.putString("CONFIG_MODE", "CREATE_IF_NOT_EXIST");
Intent iSetConfig = new Intent();
iSetConfig.setAction("com.symbol.datawedge.api.ACTION");
iSetConfig.putExtra("com.symbol.datawedge.api.SET_CONFIG", bMain);
iSetConfig.putExtra("SEND_RESULT", "LAST_RESULT");
this.sendBroadcast(iSetConfig);
3.コンテンツ プロバイダを使用してインテント出力を処理
コンテンツ プロバイダを使用するように構成されている場合は、最初に、インテント出力プラグインでの構成方法に基づいてスキャン データ インテントが送信されます。
インテント エクストラには、DataWedge コンテンツ プロバイダの URI が含まれています。アプリケーションでは、コンテンツ プロバイダ URI を使用し、ContentResolver
によりデータを Cursor
オブジェクトに問い合わせる必要があります。
パラメータ
署名の有無ステータス - ドキュメント キャプチャ中に手書きの署名の有無を確認する必要がある場合は、既存のコンテンツ プロバイダ カーソルを通じて署名の有無ステータス パラメータが公開されます。これにより、署名が存在するかどうか、署名の有無ステータスがサポートされているかどうか、または署名の有無ステータスが要求されなかったかどうかが返されます。ドキュメント キャプチャ テンプレートを作成または編集するときは、署名の有無ステータスを要求する必要があります。
カーソル列名 | 列の値 |
---|---|
field_signature_status | -2 – 基盤となるスキャナ フレームワークで署名の有無ステータスがサポートされていない -1 – 署名の有無ステータスが要求されていない 0 – 署名が存在しない 1 – 署名が存在する |
サンプル コード
NextGen SimulScan でスキャン データを処理
次のサンプル コードでは、NextGen SimulScan を使用してスキャン データを処理する方法を示します。
public class MainActivity extends AppCompatActivity {
public static final String DATA_NEXT_URI = "next_data_uri";
public static final String FULL_DATA_SIZE = "full_data_size";
public static final String RAW_DATA_SIZE = "data_buffer_size";
public static final String DECODE_DATA_EXTRA = "com.symbol.datawedge.decode_data";
public static final String INTENT_OUTPUT_ACTION = "com.symbol.genericdata.INTENT_OUTPUT";
public static final String LABEL_TYPE_SIGNATURE = "LABEL-TYPE-SIGNATURE";
public static final String FIELD_DATA_URI = "com.symbol.datawedge.field_data_uri";
public static final String DECODED_MODE = "com.symbol.datawedge.decoded_mode";
public static final String DATA_TAG = "com.symbol.datawedge.data";
public static final String LABEL_TYPE = "label_type";
public static final String FIELD_LABEL_TYPE = "field_label_type";
public static final String DATA_STRING = "field_string_data";
public static final String DECODE_DATA = "field_raw_data";
public static final String IMAGE_WIDTH_TAG = "field_image_width";
public static final String IMAGE_HEIGHT_TAG = "field_image_height";
public static final String SINGLE_DECODE_MODE = "single_decode";
public static final String MULTIPLE_DECODE_MODE = "multiple_decode";
public static final String STRING_DATA_KEY = "com.symbol.datawedge.data_string";
public static final String LABEL_TYPE_TAG = "com.symbol.datawedge.label_type";
public static final String STRING_DATA_KEY_SINGLE_BARCODE = "data_string";
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
try {
String action = intent.getAction();
Bundle extras = intent.getExtras();
/* ###### Processing scanned data from Intent output [Start] ###### */
if (action.equals(INTENT_OUTPUT_ACTION)) {
Thread dataProcessingThrad = new Thread(new Runnable() {
@Override
public void run() {
Bundle data = intent.getExtras();
if (data != null) {
String decodedMode = data.getString(DECODED_MODE);
/* ###### Processing scanned data when ScanningMode is set as "Single" [Start] ###### */
if (decodedMode.equals(SINGLE_DECODE_MODE)) {
processSingleDecode(data);
}
/* ###### Processing scanned data when ScanningMode is set as "Single" [Finish] ###### */
/* ###### Processing scanned data when ScanningMode is set as "SimulScan" [Start] ###### */
else if (decodedMode.equals(MULTIPLE_DECODE_MODE)) {
processMultipleDecode(data);
}
/* ###### Processing scanned data when ScanningMode is set as "SimulScan" [Finish] ###### */
}
}
});
dataProcessingThrad.start();
}
/* ###### Processing scanned data from Intent output [Finish] ###### */
} catch (Exception ex) {
Toast.makeText(context, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
}
};
private void processSingleDecode(Bundle data)
{
String decodeDataUri = data.getString(DECODE_DATA_EXTRA);
String barcodeData = "";
//Check if the data coming through the content provider.
if(decodeDataUri != null) {
//Data is coming through the content provider, using a Cursor object to extract data
Cursor cursor = getContentResolver()
.query(Uri.parse(decodeDataUri), null, null, null);
if (cursor != null) {
cursor.moveToFirst();
String labelType = cursor
.getString(cursor.getColumnIndex(LABEL_TYPE));
String dataString = cursor
.getString(cursor.getColumnIndex(STRING_DATA_KEY_SINGLE_BARCODE));
barcodeData += "\nLabel type: " + labelType;
barcodeData += "\nString data: " + dataString;
}
}
else
{
//Data is coming through the Intent bundle itself
String labelType = data.getString(LABEL_TYPE_TAG);
String dataString = data.getString(STRING_DATA_KEY);
barcodeData += "\nLabel type: " + labelType;
barcodeData += "\nString data: " + dataString;
}
TextView txtBarcodeData = new TextView(getApplicationContext());
txtBarcodeData.setText(barcodeData);
showInUI(txtBarcodeData, null);
updateStatus("Data processing successful");
}
private void processMultipleDecode(Bundle data)
{
ArrayList<Bundle> fields = data.getParcelableArrayList(DATA_TAG);
if(fields == null) //Content provider is not enabled in Intent Output plugin or Scanning mode is not selected as "SimulScan"
{
updateStatus("Content provider is not enabled in Intent Output plugin " +
"or Scanning mode is not selected as \"SimulScan\".\nPlease check and try again");
return;
}
//Iterate through each field
for (Bundle field : fields) {
String decodeDataUri = field.getString(FIELD_DATA_URI);
Cursor cursor = null;
if(decodeDataUri != null)
cursor = getContentResolver().query(Uri.parse(decodeDataUri),
null, null, null);
if (cursor != null) {
int imgWidth = 0;
int imgHeight = 0;
cursor.moveToFirst();
String strResultStatusData = "";
String labelType = cursor.
getString(cursor.getColumnIndex(FIELD_LABEL_TYPE));
strResultStatusData += "\nLabel type: " + labelType;
if (labelType.equals(LABEL_TYPE_SIGNATURE)) {
strResultStatusData += "\nImage data: ";
imgWidth = cursor.getInt(cursor.getColumnIndex(IMAGE_WIDTH_TAG));
imgHeight = cursor.getInt(cursor.getColumnIndex(IMAGE_HEIGHT_TAG));
} else {
String dataString = cursor
.getString(cursor.getColumnIndex(DATA_STRING));
strResultStatusData += "\nString data: " + dataString;
}
String nextURI = cursor.getString(cursor.getColumnIndex(DATA_NEXT_URI));
byte[] binaryData = null;
if (nextURI.isEmpty()) { //No data chunks. All data are available in one chunk
binaryData = cursor.getBlob(cursor.getColumnIndex(DECODE_DATA));
} else {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final String fullDataSize = cursor
.getString(cursor.getColumnIndex(FULL_DATA_SIZE));
int bufferSize = cursor.getInt(cursor
.getColumnIndex(RAW_DATA_SIZE));
baos.write(cursor.getBlob(cursor
.getColumnIndex(DECODE_DATA))); //Read the first chunk from initial set
while (!nextURI.isEmpty()) {
Cursor imageDataCursor = getContentResolver()
.query(Uri.parse(nextURI), null,
null, null);
if (imageDataCursor != null) {
imageDataCursor.moveToFirst();
bufferSize += imageDataCursor
.getInt(imageDataCursor
.getColumnIndex(RAW_DATA_SIZE));
byte[] bufferData = imageDataCursor
.getBlob(imageDataCursor
.getColumnIndex(DECODE_DATA));
baos.write(bufferData);
nextURI = imageDataCursor
.getString(imageDataCursor
.getColumnIndex(DATA_NEXT_URI));
}
imageDataCursor.close();
updateStatus("Data being processed, please wait..\n" +
bufferSize + "/" + fullDataSize + " bytes merged");
}
binaryData = baos.toByteArray();
baos.close();
} catch (final Exception ex) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, ex.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
}
}
final TextView txtBarcodeData = new TextView(getApplicationContext());
txtBarcodeData.setText(strResultStatusData);
showInUI(txtBarcodeData,null);
if (labelType.equals(LABEL_TYPE_SIGNATURE)) {
try {
//-- Creating YUV Image and Bitmap Image [Start]
ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(binaryData, ImageFormat.NV21,
imgWidth, imgHeight, null);
yuvImage.compressToJpeg(new Rect(0, 0, imgWidth, imgHeight),
50, out);
byte[] imageBytes = out.toByteArray();
Bitmap bmp = null;
if (binaryData != null) {
bmp = BitmapFactory.decodeByteArray(imageBytes, 0,
imageBytes.length);
}
final ImageView img = new ImageView(getApplicationContext());
img.setImageBitmap(bmp);
showInUI(null,img);
//-- Creating YUV Image and Bitmap Image [Finish]
}
catch (final Exception ex)
{
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,
"Error: " + ex.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
}
}
updateStatus("Data processing successful");
}
void updateStatus(String status)
{
//Show status in UI
}
private void showInUI(final TextView textView, final ImageView imageView)
{
runOnUiThread(new Runnable() {
@Override
public void run() {
if(textView != null)
//Add text view to UI
if(imageView != null)
//Add image view to UI
}
});
}
}
署名読み取りサンプル コード
次のサンプル コードは、署名読み取りを使用してスキャン データを処理する方法を示しています。
public static final String BARCODE_IMAGE_FORMAT_TAG = "image_format";
public static final String BARCODE_SIGNATURE_TYPE_TAG = "signature_type";
public static final String BARCODE_IMAGE_SIZE_TAG = "image_size";
public static final String BARCODE_IMAGE_DATA_TAG = "com.symbol.datawedge.image_data";
public static final String SIGNATURE_IMAGE_DATA = "image_data";
public static final String DATA_NEXT_URI = "next_data_uri";
public static final String FULL_DATA_SIZE = "full_data_size";
public static final String RAW_DATA_SIZE = "data_buffer_size";
public static final String INTENT_OUTPUT_ACTION = "data_buffer_size";
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context,final Intent intent) {
try {
String action = intent.getAction();
//Process scanned data from Intent output
if (action.equals(INTENT_OUTPUT_ACTION)) {
Bundle data = intent.getExtras();
if (data != null) {
String imageDataUri = data.getString(BARCODE_IMAGE_DATA_TAG);
if(imageDataUri == null)
return;
Cursor cursor = getContentResolver().query(Uri.parse(imageDataUri), null, null, null);
if (cursor != null) {
cursor.moveToFirst();
String format = cursor.getString(cursor.getColumnIndex(BARCODE_IMAGE_FORMAT_TAG));
String sigType = cursor.getString(cursor.getColumnIndex(BARCODE_SIGNATURE_TYPE_TAG));
String size = cursor.getString(cursor.getColumnIndex(BARCODE_IMAGE_SIZE_TAG));
String text = "Image format: " + format + "\n";
text += "Signature type: " + sigType + "\n";
text += "Image size: " + size + "\n";
final TextView txt = new TextView(getApplicationContext());
txt.setText(text);
String nextURI = cursor.getString(cursor.getColumnIndex(DATA_NEXT_URI));
byte[] binaryData = null;
if (nextURI.isEmpty()) { //No data chunks. All data are available in one chunk
binaryData = cursor.getBlob(cursor.getColumnIndex(SIGNATURE_IMAGE_DATA));
} else {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final String fullDataSize = cursor.getString(cursor.getColumnIndex(FULL_DATA_SIZE));
int bufferSize = cursor.getInt(cursor.getColumnIndex(RAW_DATA_SIZE));
baos.write(cursor.getBlob(cursor.getColumnIndex(SIGNATURE_IMAGE_DATA))); //Read the first chunk from initial set
while (!nextURI.isEmpty()) {
Cursor imageDataCursor = getContentResolver().query(Uri.parse(nextURI), null, null, null);
if (imageDataCursor != null) {
imageDataCursor.moveToFirst();
bufferSize += imageDataCursor.getInt(imageDataCursor.getColumnIndex(RAW_DATA_SIZE));
byte[] bufferData = imageDataCursor.getBlob(imageDataCursor.getColumnIndex(SIGNATURE_IMAGE_DATA));
baos.write(bufferData);
nextURI = imageDataCursor.getString(imageDataCursor.getColumnIndex(DATA_NEXT_URI));
}
imageDataCursor.close();
final int finalBufferSize = bufferSize;
Log.d("TAG","Data being processed, please wait..\n" + finalBufferSize + "/" + fullDataSize + " bytes merged");
}
binaryData = baos.toByteArray();
baos.close();
}
catch (final Exception ex)
{
Toast.makeText(context, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
}
Bitmap bmp = null;
if (binaryData != null) {
bmp = BitmapFactory.decodeByteArray(binaryData, 0, binaryData.length);
}
final ImageView img = new ImageView(getApplicationContext());
img.setImageBitmap(bmp);
}
Log.d("TAG","Data processing successful");
}
}
} catch (Exception ex) {
Toast.makeText(context, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
}
};
関連ガイド: