AsyncTask выполняется только при переходе в отладчике - PullRequest
0 голосов
/ 04 июля 2018

Прежде всего, позвольте мне сказать, что я только начинаю свое приключение на Android и изучаю код, размещенный ниже.

Итак, у меня есть сканер штрих-кода Zebra и устройство Android, которое должно обрабатывать сканированные штрих-коды. Два устройства общаются друг с другом через соединение BT (у меня это работает). Отсканированные штрих-коды обрабатываются JsonObjectRequest (также работает). В зависимости от ответа (или отсутствия) от внешней службы, сканер должен реагировать определенным образом:

зеленый / красный светодиод включен - звуковой сигнал - зеленый / красный светодиод выключен

И вот где я борюсь:

Если у меня только бипер - все работает. Если у меня светодиод включен / выключен - работает только светодиод. Если у меня есть все 3 действия - ни одно не выполняется.

Теперь странно то, что отладчик показывает полученные и выполненные действия

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

Код, который я использую для построения этих запросов, основан на примере приложения и документации, предоставленной Zebra , см. Здесь Zebra Android SDK , и вот как я называю эти действия:

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);
}

Когда я устанавливаю точки останова и выполняю код, все действия выполняются, и как только я запускаю приложение, я получаю эти проблемы.

Может кто-нибудь помочь мне?

1 Ответ

0 голосов
/ 04 июля 2018

Вот что я понял из вашего кода. Вы отправляете HTTP-запрос на сервер и, основываясь на ответе, собираетесь выполнить последовательность событий, таких как переключение состояния индикатора и звука.

В качестве фона Asynctask используется для выполнения фрагмента кода в фоновом потоке. В вашем случае вы хотите выполнять команды. Как видно из названия, они асинхронные и будут работать параллельно с вашим основным потоком (по крайней мере, doInBackground).

В setScanResultOK и setScanResultERR вы потенциально можете создать 3 асинхронные задачи. Только один из них будет работать по умолчанию, асинхронные задачи выполняются в одном потоке выполнения. Если вы хотите запустить их полностью, запустите их в пуле потоков.

Теперь вы упомянули, что хотите запустить их последовательно. Я предлагаю реорганизовать ваш код как таковой.

  1. Создайте 2 асинхронные задачи, 1 для успеха и 1 для ошибки.
  2. Выполнение нескольких вызовов prepareInXML в doInBackground
  3. Создание асинхронной задачи на основе ответа и выполнение.

Как пример:

@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);
}

Конечно, для этого потребуется изменить сигнатуру некоторых функций. Затем обработайте все изменения пользовательского интерфейса в 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: Попробуйте добавить задержку между командами. «Нет операции» может быть чем-то, что на самом деле происходит очень быстро, и мы замечаем это.

...