Issue
First off, let me say that I'm just starting my Android adventure and am learning on the code posted below.
So i have a Zebra barcode scanner and an Android device, which is supposed to handle the scanned barcodes. The two devices communicate with each other via BT connection (I got it working). Scanned barcodes are being handled by JsonObjectRequest
(also working). Depending on the response (or lack of) from external service, scanner has to react in a certain way:
green/red LED on - beeper - green/red LED off
And here is where I am struggling:
If I have only beeper - everything works. If I have a LED on/off - only LED on works. If I have all 3 actions - none gets executed.
Now, strange thing is, that debugger shows those actions received and executed
D/MainActivity: Barcode Received
I/ViewRootImpl: CPU Rendering VSync enable = false
I/BluetoothScanner: executeCommand started. opcode = DCSSDK_SET_ACTION inXML = <inArgs><scannerID>5</scannerID><cmdArgs><arg-int>45</arg-int></cmdArgs></inArgs>
I/BluetoothScanner: 7 SSI bytes sent: 0x05 0xE7 0x04 0x00 0x04 0xFF 0x0C
I/BluetoothScanner: executeCommand returningDCSSDK_RESULT_SUCCESS
I/ViewRootImpl: CPU Rendering VSync enable = false
I/BluetoothScanner: executeCommand started. opcode = DCSSDK_SET_ACTION inXML = <inArgs><scannerID>5</scannerID><cmdArgs><arg-int>17</arg-int></cmdArgs></inArgs>
I/BluetoothScanner: 7 SSI bytes sent: 0x05 0xE6 0x04 0x00 0x11 0xFF 0x00
I/BluetoothScanner: soundBeeper command write successful. Wait for Status.
executeCommand returningDCSSDK_RESULT_SUCCESS
I/ViewRootImpl: CPU Rendering VSync enable = false
I/BluetoothScanner: executeCommand started. opcode = DCSSDK_SET_ACTION inXML = <inArgs><scannerID>5</scannerID><cmdArgs><arg-int>46</arg-int></cmdArgs></inArgs>
I/BluetoothScanner: 7 SSI bytes sent: 0x05 0xE8 0x04 0x00 0x04 0xFF 0x0B
executeCommand returningDCSSDK_RESULT_SUCCESS
Code, that I am using to construct those requests is based on an example app and documentation provided by Zebra see here the Zebra Android SDK and this is how I am calling those actions:
private class MyAsyncTask extends AsyncTask<String,Integer,Boolean> {
int scannerId;
StringBuilder outXML;
DCSSDKDefs.DCSSDK_COMMAND_OPCODE opcode;
private CustomProgressDialog progressDialog;
public MyAsyncTask(int scannerId, DCSSDKDefs.DCSSDK_COMMAND_OPCODE opcode){
this.scannerId=scannerId;
this.opcode=opcode;
this.outXML = outXML;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new CustomProgressDialog(MainActivity.this, "Execute Command...");
progressDialog.show();
}
@Override
protected Boolean doInBackground(String... strings) {
return executeCommand(opcode,strings[0],null,scannerId);
}
@Override
protected void onPostExecute(Boolean b) {
super.onPostExecute(b);
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
if(!b){
Toast.makeText(MainActivity.this, "Cannot perform the Action", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public boolean executeCommand(DCSSDKDefs.DCSSDK_COMMAND_OPCODE opCode, String inXML, StringBuilder outXML, int scannerID) {
if (Application.sdkHandler != null)
{
if(outXML == null){
outXML = new StringBuilder();
}
DCSSDKDefs.DCSSDK_RESULT result=Application.sdkHandler.dcssdkExecuteCommandOpCodeInXMLForScanner(opCode,inXML,outXML,scannerID);
if(result== DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS)
return true;
else if(result==DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_FAILURE)
return false;
}
return false;
}
private final Handler dataHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch(msg.what){
case Constants.BARCODE_RECEIVED:
Barcode barcode = (Barcode) msg.obj;
sendApiHttpRequest(new String(barcode.getBarcodeData()));
break;
}
return false;
}
});
private void sendApiHttpRequest(String ticketId){
String url = "https://#################################/" + ticketId;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, myJsonListener(), myJsonErrorListener());
// tag the request for ease of debugging
jsonObjectRequest.setTag(TAG);
// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);
}
private Response.Listener<JSONObject> myJsonListener() {
return new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
boolean status;
try {
status = response.getBoolean("status");
if (status){
setScanResultOK();
}else{
setScanResultERR();
}
}catch(JSONException e){
setScanResultERR();
Log.e(TAG, "Failure", e);
}
}
};
}
private Response.ErrorListener myJsonErrorListener() {
return new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
setScanResultERR();
Log.i(TAG, "Error : " + error.getLocalizedMessage());
}
};
}
private void setScanResultOK(){
prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_ON);
prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_FAST_WARBLE_BEEP);
prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_OFF);
TextView textViewScanResult = findViewById(R.id.txt_scan_result);
textViewScanResult.setText(R.string.scan_res_ok);
textViewScanResult.setTextAppearance(getApplicationContext(), R.style.roboto_medium_96dp_green);
}
private void setScanResultERR(){
prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_RED_ON);
prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LOW_LONG_BEEP_3);
prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_RED_OFF);
TextView textViewScanResult = findViewById(R.id.txt_scan_result);
textViewScanResult.setText(R.string.scan_res_err);
textViewScanResult.setTextAppearance(getApplicationContext(), R.style.roboto_medium_96dp_red);
}
private void performOpcodeAction(String inXML) {
if (scannerID != -1) {
new MyAsyncTask(scannerID, DCSSDKDefs.DCSSDK_COMMAND_OPCODE.DCSSDK_SET_ACTION).execute(new String[]{inXML});
} else {
Toast.makeText(this, "Invalid scanner ID", Toast.LENGTH_SHORT).show();
}
}
private void prepareInXML(int value){
String inXML = "<inArgs><scannerID>" + scannerID + "</scannerID><cmdArgs><arg-int>" +
value + "</arg-int></cmdArgs></inArgs>";
performOpcodeAction(inXML);
}
When I set up breakpoints and step through the code, all actions are executed and as soon as I run the app, I get those issues.
Can anyone please help me?
Solution
Here's what I understood from your code. Your are sending an HTTP request to a server and based on the response, your are going to perform a sequence of events such as LED and sound state toggling.
As a background, Asynctask is used to execute a piece of code on a background thread. In your case, you want to perform the commands. As from the name, they are asynchronous and will run in parallel with your main thread (at least the doInBackground).
In setScanResultOK
and setScanResultERR
, you are potentially instantiating 3 asynctasks. Only one of them will run as by default, asynctasks run on a single execution thread. If you want to run them altogether, execute them in a thread pool executor.
Now, you mentioned that you want to run them in sequence. I propose to refactor your code as such.
- Create 2 asynctasks, 1 for success and 1 for error.
- Perform the multiple
prepareInXML
calls in doInBackground - Instantiate an asynctask based on the response, and execute.
As an example:
@Override
protected Boolean doInBackground(String... strings) {
if (!prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_ON)) {
return false;
}
if (!prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_FAST_WARBLE_BEEP)) {
return false;
}
return prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_OFF);
}
Of course this will require you to change some function signature to accommodate. Then process all UI changes in onPostExecute.
@Override
protected void onPostExecute(Boolean b) {
super.onPostExecute(b);
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
if(!b){
Toast.makeText(MainActivity.this, "Cannot perform the Action", Toast.LENGTH_SHORT).show();
}
/* perform UI changes particular to the type of task (success/fail) */
}
UPDATE: Try adding a delay in between commands. The no op might be something that is actually a on-sound-off sequence happening real fast for us to notice.
Answered By - tompee
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.