Skip to content
This repository has been archived by the owner on Mar 1, 2022. It is now read-only.

Commit

Permalink
Merge pull request #4 from darryncampbell/work_in_progress
Browse files Browse the repository at this point in the history
Work in progress
  • Loading branch information
darryncampbell authored Sep 27, 2018
2 parents 7a868cd + 0c47942 commit f4b84af
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,35 @@
import android.content.IntentFilter;
import android.os.Bundle;
import org.json.JSONObject;
import org.json.JSONException;
import org.json.JSONArray;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import java.util.Map;
import java.util.HashMap;
import java.util.Calendar;
import java.util.Arrays;
import java.util.Iterator;
import java.lang.SecurityException;
import java.text.SimpleDateFormat;
import java.text.ParseException;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
Expand All @@ -43,6 +53,7 @@ public class RNDataWedgeIntentsModule extends ReactContextBaseJavaModule impleme

private static final String TAG = RNDataWedgeIntentsModule.class.getSimpleName();

// THESE ACTIONS ARE DEPRECATED, PLEASE SPECIFY THE ACTION AS PART OF THE CALL TO sendBroadcastWithExtras
private static final String ACTION_SOFTSCANTRIGGER = "com.symbol.datawedge.api.ACTION_SOFTSCANTRIGGER";
private static final String ACTION_SCANNERINPUTPLUGIN = "com.symbol.datawedge.api.ACTION_SCANNERINPUTPLUGIN";
private static final String ACTION_ENUMERATESCANNERS = "com.symbol.datawedge.api.ACTION_ENUMERATESCANNERS";
Expand All @@ -60,6 +71,8 @@ public class RNDataWedgeIntentsModule extends ReactContextBaseJavaModule impleme
// Enumerated Scanner receiver
private static final String ACTION_ENUMERATEDLISET = "com.symbol.datawedge.api.ACTION_ENUMERATEDSCANNERLIST";
private static final String KEY_ENUMERATEDSCANNERLIST = "DWAPI_KEY_ENUMERATEDSCANNERLIST";
// END DEPRECATED PROPERTIES

// Scan data receiver
private static final String RECEIVED_SCAN_SOURCE = "com.symbol.datawedge.source";
private static final String RECEIVED_SCAN_DATA = "com.symbol.datawedge.data_string";
Expand Down Expand Up @@ -159,9 +172,167 @@ public void sendIntent(String action, String parameterValue)
this.reactContext.sendBroadcast(dwIntent);
}

@ReactMethod
public void sendBroadcastWithExtras(ReadableMap obj) throws JSONException
{
String action = obj.hasKey("action") ? obj.getString("action") : null;
Intent i = new Intent();
if (action != null)
i.setAction(action);

Map<String, Object> intentMap = recursivelyDeconstructReadableMap(obj);
Map<String, Object> extrasMap = null;
if (intentMap.containsKey("extras") && intentMap.get("extras") != null &&
intentMap.get("extras") instanceof Map)
extrasMap = (Map<String, Object>) intentMap.get("extras");

for (String key : extrasMap.keySet()) {
Object value = extrasMap.get(key);
String valueStr = String.valueOf(value);
// If type is text html, the extra text must sent as HTML
if (value instanceof Boolean) {
i.putExtra(key, Boolean.valueOf(valueStr));
} else if(value instanceof Integer) {
i.putExtra(key, Integer.valueOf(valueStr));
} else if(value instanceof Long) {
i.putExtra(key, Long.valueOf(valueStr));
} else if(value instanceof Double) {
i.putExtra(key, Double.valueOf(valueStr));
} else if(valueStr.startsWith("{"))
{
// UI has passed a JSON object
Bundle bundle = toBundle(new JSONObject(valueStr));
i.putExtra(key, bundle);
}
else {
i.putExtra(key, valueStr);
}
}

this.reactContext.sendBroadcast(i);
}

// Credit: https://github.com/facebook/react-native/issues/4655
private Map<String, Object> recursivelyDeconstructReadableMap(ReadableMap readableMap) {
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
Map<String, Object> deconstructedMap = new HashMap<>();
while (iterator.hasNextKey()) {
String key = iterator.nextKey();
ReadableType type = readableMap.getType(key);
switch (type) {
case Null:
deconstructedMap.put(key, null);
break;
case Boolean:
deconstructedMap.put(key, readableMap.getBoolean(key));
break;
case Number:
deconstructedMap.put(key, readableMap.getDouble(key));
break;
case String:
deconstructedMap.put(key, readableMap.getString(key));
break;
case Map:
deconstructedMap.put(key, recursivelyDeconstructReadableMap(readableMap.getMap(key)));
break;
case Array:
deconstructedMap.put(key, recursivelyDeconstructReadableArray(readableMap.getArray(key)));
break;
default:
throw new IllegalArgumentException("Could not convert object with key: " + key + ".");
}
}
return deconstructedMap;
}

// Credit: https://github.com/facebook/react-native/issues/4655
private List<Object> recursivelyDeconstructReadableArray(ReadableArray readableArray) {
List<Object> deconstructedList = new ArrayList<>(readableArray.size());
for (int i = 0; i < readableArray.size(); i++) {
ReadableType indexType = readableArray.getType(i);
switch(indexType) {
case Null:
deconstructedList.add(i, null);
break;
case Boolean:
deconstructedList.add(i, readableArray.getBoolean(i));
break;
case Number:
deconstructedList.add(i, readableArray.getDouble(i));
break;
case String:
deconstructedList.add(i, readableArray.getString(i));
break;
case Map:
deconstructedList.add(i, recursivelyDeconstructReadableMap(readableArray.getMap(i)));
break;
case Array:
deconstructedList.add(i, recursivelyDeconstructReadableArray(readableArray.getArray(i)));
break;
default:
throw new IllegalArgumentException("Could not convert object at index " + i + ".");
}
}
return deconstructedList;
}

// https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/blob/master/src/android/IntentShim.java
private Bundle toBundle(final JSONObject obj) {
Bundle returnBundle = new Bundle();
if (obj == null) {
return null;
}
try {
Iterator<?> keys = obj.keys();
while(keys.hasNext())
{
String key = (String)keys.next();
Object compare = obj.get(key);
if (obj.get(key) instanceof String)
returnBundle.putString(key, obj.getString(key));
else if (obj.get(key) instanceof Boolean)
returnBundle.putBoolean(key, obj.getBoolean(key));
else if (obj.get(key) instanceof Integer)
returnBundle.putInt(key, obj.getInt(key));
else if (obj.get(key) instanceof Long)
returnBundle.putLong(key, obj.getLong(key));
else if (obj.get(key) instanceof Double)
returnBundle.putDouble(key, obj.getDouble(key));
else if (obj.get(key).getClass().isArray() || obj.get(key) instanceof JSONArray)
{
JSONArray jsonArray = obj.getJSONArray(key);
int length = jsonArray.length();
if (jsonArray.get(0) instanceof String)
{
String[] stringArray = new String[length];
for (int j = 0; j < length; j++)
stringArray[j] = jsonArray.getString(j);
returnBundle.putStringArray(key, stringArray);
//returnBundle.putParcelableArray(key, obj.get);
}
else
{
Bundle[] bundleArray = new Bundle[length];
for (int k = 0; k < length ; k++)
bundleArray[k] = toBundle(jsonArray.getJSONObject(k));
returnBundle.putParcelableArray(key, bundleArray);
}
}
else if (obj.get(key) instanceof JSONObject)
returnBundle.putBundle(key, toBundle((JSONObject)obj.get(key)));
}
}
catch (JSONException e) {
e.printStackTrace();
}

return returnBundle;
}

@ReactMethod
public void registerReceiver(String action, String category)
{
// THIS METHOD IS DEPRECATED
Log.d(TAG, "Registering an Intent filter for action: " + action);
this.registeredAction = action;
this.registeredCategory = category;
Expand All @@ -181,6 +352,46 @@ public void registerReceiver(String action, String category)
this.reactContext.registerReceiver(scannedDataBroadcastReceiver, filter);
}

@ReactMethod
public void registerBroadcastReceiver(ReadableMap filterObj)
{
try
{
this.reactContext.unregisterReceiver(genericReceiver);
}
catch (IllegalArgumentException e)
{
// Expected behaviour if there was not a previously registered receiver.
}
IntentFilter filter = new IntentFilter();
if (filterObj.hasKey("filterActions"))
{
ReadableType type = filterObj.getType("filterActions");
if (type == ReadableType.Array)
{
ReadableArray actionsArray = filterObj.getArray("filterActions");
for (int i = 0; i < actionsArray.size(); i++)
{
filter.addAction(actionsArray.getString(i));
}
}
}
if (filterObj.hasKey("filterCategories"))
{
ReadableType type = filterObj.getType("filterCategories");
if (type == ReadableType.Array)
{
ReadableArray categoriesArray = filterObj.getArray("filterCategories");
for (int i = 0; i < categoriesArray.size(); i++)
{
filter.addCategory(categoriesArray.getString(i));
}
}
}
this.reactContext.registerReceiver(genericReceiver, filter);

}

// Broadcast receiver for the response to the Enumerate Scanner API
public BroadcastReceiver myEnumerateScannersBroadcastReceiver = new BroadcastReceiver()
{
Expand All @@ -202,6 +413,16 @@ public void onReceive(Context context, Intent intent) {
}
};

public BroadcastReceiver genericReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "Received Broadcast from DataWedge");
intent.putExtra("v2API", true);
ObservableObject.getInstance().updateValue(intent);
}
};

// Sending events to JavaScript as defined in the native-modules documentation.
// Note: Callbacks can only be invoked a single time so are not a suitable interface for barcode scans.
private void sendEvent(ReactContext reactContext,
Expand All @@ -215,6 +436,16 @@ private void sendEvent(ReactContext reactContext,
public void update(Observable observable, Object data)
{
Intent intent = (Intent)data;

if (intent.hasExtra("v2API"))
{
Bundle intentBundle = intent.getExtras();
intentBundle.remove("com.symbol.datawedge.decode_data"); // fb converter cannot cope with byte arrays
intentBundle.remove("com.motorolasolutions.emdk.datawedge.decode_data"); // fb converter cannot cope with byte arrays
WritableMap map = Arguments.fromBundle(intentBundle);
sendEvent(this.reactContext, "datawedge_broadcast_intent", map);
}

String action = intent.getAction();
if (action.equals(ACTION_ENUMERATEDLISET))
{
Expand Down
8 changes: 8 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@ var DataWedgeIntents = {
DISABLE_PLUGIN: RNDataWedgeIntents.DISABLE_PLUGIN,

sendIntent(action, parameterValue) {
// THIS METHOD IS DEPRECATED, use SendBroadcastWithExtras
RNDataWedgeIntents.sendIntent(action, parameterValue);
},
sendBroadcastWithExtras(extrasObject) {
RNDataWedgeIntents.sendBroadcastWithExtras(extrasObject);
},
registerBroadcastReceiver(filter) {
RNDataWedgeIntents.registerBroadcastReceiver(filter);
},
registerReceiver(action, category) {
// THIS METHOD IS DEPRECATED, use registerBroadcastReceiver
RNDataWedgeIntents.registerReceiver(action, category);
},
};
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-datawedge-intents",
"version": "0.0.2",
"version": "0.1.0",
"description": "React Native Android module to interface with Zebra's DataWedge using Android Intents to control the barcode scanner and retrieve scanned data",
"main": "index.js",
"scripts": {
Expand All @@ -26,6 +26,6 @@
"repository": "https://github.com/darryncampbell/react-native-datawedge-intents",
"bugs": "https://github.com/darryncampbell/react-native-datawedge-intents/issues",
"peerDependencies": {
"react-native": ">=0.27"
"react-native": ">=0.56"
}
}

0 comments on commit f4b84af

Please sign in to comment.