По каким причинам функция gatt.writeCharacteristic () может возвращать false?

Я разрабатываю приложение для Android BLE. В некоторых Android-устройствах я сталкиваюсь с тем, что, когда я пытаюсь записать данные в характеристику с помощью метода writeCharacteristic(), он возвращает false и не записывает. Знаете ли вы, в каких случаях он может возвращать false? С моим BQ Aquaris U Plus этого не происходит, просто успешно написано и возвращается true. Но с моим Huawei Y6 такое случалось и столько раз. Может быть, в 7/10 случаях он возвращает ложь. Это мой код, он такой большой, но может помочь:

public class ServicioFirmadoNuevo extends Service{

private static final long NUMEROS_DE_RETRYS = Constantes.NUMEROS_DE_RETRYS;
private ServiceConnection serviceConn;
private ArrayList<byte[]> arrayDatosPartidos;
private Handler handler;
private BluetoothGatt mGatt;
private final IBinder mBinder = new ServicioFirmadoNuevo.LocalBinder();
private android.bluetooth.BluetoothDevice mBluetoothDevice;
private byte[] byteFinal;
private ArrayList<byte[]> datosAJuntar;
private int numeroDeParticionesDeDatos;
private boolean esperandoDesconexion =  false;
private boolean protocoloLectura = false;
private boolean comunicacionTerminada = false;
private boolean retry = true;
private int contadorRetrys = 0;
private int iteracionesLectura = 0;
private String idMotivo;
private int vecesOnChanged = 0;
private int nSerie;

private Intent intentError = new Intent("errorFirmado");
public ServicioFirmadoNuevo(){}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {


    return START_STICKY;

}
public void onStartCommand2(Intent intent, BluetoothDevice device, String motivoCodigo, String motivoLetra, int nserie) {

    Log.i("INICIOSERVICIOFIRMADO", "TRUE");
    mGatt = null;
    handler = new Handler();
    datosAJuntar = new ArrayList<byte[]>();
    contadorRetrys = 0;
    Log.d("pruebitas", motivoCodigo+motivoLetra);
    mBluetoothDevice = device;
    nSerie = nserie;
    Log.d("NSERIEAFIRMAR", nserie+"");


    /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        if (device.getBondState() == BluetoothDevice.BOND_NONE){
            Log.d("BOUNDING??? ", device.createBond()+"");
        }
    }
    final String motCod = motivoCodigo;
    new android.os.Handler().postDelayed(
            new Runnable() {
                public void run() {
                    conectaConEsteMotivo(motCod);
                }
            },
            4000);*/
    conectaConEsteMotivo(motivoCodigo);

}
public void setServiceConn(ServiceConnection serviceConn) {
    this.serviceConn = serviceConn;
}
public class LocalBinder extends Binder {
    public ServicioFirmadoNuevo getServiceInstance(){

        return ServicioFirmadoNuevo.this;

    }
}
public void conectaConEsteMotivo(String idmotivo){

    handler.postDelayed(timeOutFirmado, 10000);
    handler.postDelayed(runnableCodeTimeOutConversacion, 9000);
    this.idMotivo = idmotivo;

    if (mGatt == null) {
        Log.e("mGATT", "IS NULL");
        try {

            Handler mHandler = new Handler(getApplicationContext().getMainLooper());
            mHandler.post(new Runnable() {

                @Override
                public void run() {

                    Log.e("TRY", "1");
                    if (mBluetoothDevice!=null){

                        /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                            Log.d("BOUNDING??? ", mBluetoothDevice.createBond()+"");
                        }*/
                        Log.d("mBluetoothDevice", "mBluetoothDevice.connectGatt called...");
                        mGatt = mBluetoothDevice.connectGatt(getApplicationContext(), false, gattCallback);

                        /*new Handler().postDelayed(
                                new Runnable() {
                                    public void run() {
                                        Log.d("mBluetoothDevice", "mBluetoothDevice.connectGatt called...");
                                        mGatt = mBluetoothDevice.connectGatt(getApplicationContext(), false, gattCallback);
                                    }
                                },
                                1000);*/

                    }

                }

            });



        }catch (Throwable e){

            e.printStackTrace();

            if (mGatt != null){

                mGatt.disconnect();
                mGatt.close();

            }

            if (!retry){

                Log.e("ERROR","ERROR");
                //presenter.escribirEnToast("Problema Null Pointer en método : conectaConEsteMotivo(String a) ");
                //presenter.pararServicioFirmado();

            }

        }

    } else {

        Log.i("MGATTISNOTNULL","MGATT NO ES NULL");

    }

}
private Runnable runnableCodeTimeOutConversacion = new Runnable() {

    @Override
    public void run() {

        //contadorRetrys = (int) NUMEROS_DE_RETRYS;

        if (!esperandoDesconexion){

            Log.e("TIMEOUTCONVERSACION", "TRUE");

            if(mGatt != null){

                mGatt.disconnect();
                mGatt.close();

            }

            //presenter.escribirEnToast("TIMEOUT Conversación");
            //presenter.setServicioEnEjecucion(false);
            //presenter.pararServicioFirmado();
            retrySameMotivo();

        }

    }
};
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {

    @Override
    public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {

        Log.i("onConnectionStateChange", "Status: " + status);

        switch (newState) {

            case BluetoothProfile.STATE_CONNECTED:

                Log.i("gattCallback", "STATE_CONNECTED");

                boolean discover_services = gatt.discoverServices();

                if (discover_services) {

                    Log.i("Hadescubiertoservicios", "TRUE");

                } else {

                    Log.i("Hadescubiertoservicios", "FALSE");

                }

                break;

            case BluetoothProfile.STATE_DISCONNECTED:

                Log.e("gattCallback", "STATE_DISCONNECTED STATUS: "+ status);
                //gatt.disconnect();
                //gatt.close();
                //mGatt.disconnect();
                //mGatt.close();

                if(esperandoDesconexion){

                    if (mGatt != null){

                        mGatt.disconnect();
                        mGatt.close();

                    }

                    //presenter.setServicioEnEjecucion(false);
                    //presenter.pararServicioYReiniciar();
                    sendBroadcast(intentError);

                }

                else {

                    if (idMotivo == null){

                        Log.e("ERRORIDMOTIVONULL", " IDMOTIVO ES NULL");
                        gatt.disconnect();
                        gatt.close();

                        if (mGatt != null){

                            mGatt.disconnect();
                            mGatt.close();

                        }

                        //presenter.escribirEnToast("IDMOTIVO ES NULL");
                        esperandoDesconexion = true;
                        sendBroadcast(intentError);


                    }else {

                        if(contadorRetrys < NUMEROS_DE_RETRYS ){

                            retrySameMotivo();

                        }else {

                            Log.e("LimiteRetrysSuperado", " Ya se han hecho suficientes retrys y no se ha logrado firmar");

                            gatt.disconnect();
                            gatt.close();

                            if (mGatt != null){

                                mGatt.disconnect();
                                mGatt.close();

                            }

                            Log.e("retrys", "Límite Retrys alcanzado.");
                            //presenter.setServicioEnEjecucion(false);
                            //presenter.pararServicioYReiniciar();
                            esperandoDesconexion = true;
                            sendBroadcast(intentError);

                        }

                    }

                }

                break;

            default:

                Log.e("gattCallback", "STATE_OTHER");

        }

    }


    @Override
    public void onServicesDiscovered(final BluetoothGatt gatt, int status) {

        Log.i("onServicesDiscovered", "enter");


        List<BluetoothGattService> services = gatt.getServices();

        if (services.size() == 0) {

            Log.i("ServiciosDeLaBaliza=0","el sice de los servicios entontrados es = 0    :"+ services.toString());

        }

        Log.i("onServicesDiscovered", services.toString());

        //Muestreo de Servicios con sus respectivas Characteristics
        for (BluetoothGattService servicio : services) {

            Log.i("Service", servicio.getUuid().toString());

            for (BluetoothGattCharacteristic characteristic : servicio.getCharacteristics()) {

                Log.i("Char", characteristic.getUuid().toString());

            }

        }

        Log.d("PASAMITADonSERVICEDISCD","-----");

        try {

            BluetoothGattCharacteristic characteristic = gatt.getServices().get(2).getCharacteristics().get(0);//todo: CAMBIAR get 2 por su uuid
            Log.d("CHARACTERISTIC -->", characteristic!= null ? "NO ES NULL": "ES NULL");
            //habilitar notificaciones
            gatt.setCharacteristicNotification(characteristic, true);
            BluetoothGattDescriptor desc = characteristic.getDescriptors().get(0);
            desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            gatt.writeDescriptor(desc);

        }catch (Exception e){

            sendBroadcast(intentError);
            e.printStackTrace();
            Log.e("ERRORDESCUBRIENDO", "TRUE");

        }

    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

        Log.e("ENTRA EN LEERCHAR", characteristic.getValue()[0]+"");
        protocolo(gatt, characteristic);

    }

    //Cuando se escribe una caracteristica lanza esto
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

        Log.e("ENTRAONWRITE", "STATUS: "+status);

        if (status == BluetoothGatt.GATT_SUCCESS) {

            handler.postDelayed(runnableCodeTimeOutTransmisiones, 1000);
            Log.i("ESCRIBIR","OK");
            Log.i("bytesescritos", characteristic.getValue().length+""+ "////////"+ new String(characteristic.getValue(), Charset.forName("UTF-8")));
            Log.i("1stEscrito", (char) characteristic.getValue()[0] + "");

            if(new String(characteristic.getValue(), Charset.forName("UTF-8")).equals(Constantes.PM_END_ACK+"")){

                characteristic.setValue(Constantes.PM_END_COM+"");
                boolean porcentaje;
                porcentaje = gatt.writeCharacteristic(characteristic);
                Log.w("LOQUEESCRIBO: ", BateriaDeMetodosUtiles.bytesToHex(characteristic.getValue())+ " : "+porcentaje);
                Log.w("ESCPORCENT",  porcentaje+"");

            }else {

                if (new String(characteristic.getValue(), Charset.forName("UTF-8")).equals(Constantes.PM_END_COM + "")) {

                    byteFinal = BateriaDeMetodosUtiles.juntarBytesDeUnArrayListDeBytes(datosAJuntar);
                    Log.e("FINALBYTE", new String(byteFinal, Charset.forName("UTF-8")));
                    Log.e("FINALBYTEHEX", BateriaDeMetodosUtiles.bytesToHex(byteFinal));
                    protocoloLectura = false;
                    iteracionesLectura = 0;
                    esperandoDesconexion = true;
                    Log.e("VamosASalirDelProcess", "Deberíamos salir de la conexión al haber escrito esto: " + new String(characteristic.getValue(), Charset.forName("UTF-8")));

                    Intent intentBD =  new Intent("fichajeCompletado");
                    Log.d("PRUEBABYTEEE", BateriaDeMetodosUtiles.bytesToHex(byteFinal));
                    intentBD.putExtra("byteFinal", byteFinal);
                    sendBroadcast(intentBD);
                    //presenter.pararServicioEscaneo();

                }

            }

            if (vecesOnChanged == 2){

                gatt.readCharacteristic(characteristic);

            }

            vecesOnChanged = 0;

        } else {

            Log.e("ESCRIBIRERROR","ERROR Lo que intentaste escribir era : "+characteristic.getValue() + "O en otras palabras: "+ BateriaDeMetodosUtiles.bytesToHex(characteristic.getValue())+" STATUS = "+status);
            gatt.disconnect();
            gatt.close();

            if (mGatt != null){

                mGatt.disconnect();
                mGatt.close();

            }

            //presenter.escribirEnToast("ERROR ESCRIBIENDO");
            Log.e("ERROR","ESCRIBIENDO");
            sendBroadcast(intentError);

        }

    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {

        Log.i("onDescriptorWrite","enter");

        byte[] paraLaBaliza ;//= BateriaDeMetodosUtiles.creacionDeRespuestaParaLaBaliza(idMotivo);

        //nuevoMETODOO//////////
        BaseDeDatos mBaseDeDatos = Room.databaseBuilder(getApplicationContext(), BaseDeDatos.class, Constantes.nombreBaseDeDatos).fallbackToDestructiveMigration().allowMainThreadQueries().build();
        ControlHoras controlHoras = mBaseDeDatos.controlHorasDao().seleccionarTodasControlHoras();
        paraLaBaliza = BateriaDeMetodosUtiles.creacionDeRespuestaParaBaliza2(idMotivo, controlHoras.getHoraPasada(), controlHoras.getHash(), controlHoras.getUpTimePasada(), nSerie);

        Log.d("QUEENVIOBALIZA", ""+idMotivo);
        //presenter.setFHDispositivo(BateriaDeMetodosUtiles.obtenerFH(paraLaBaliza)); LO HAGO CUANDO FICHO
        Log.e("DatosQueRecibeBaliza", BateriaDeMetodosUtiles.bytesToHex(paraLaBaliza));
        for (int i = 0; i < paraLaBaliza.length; i++){

            Log.d("paraLabaliza", i+ " "+paraLaBaliza[i]);

        }
        ArrayList<byte[]> tmp = BateriaDeMetodosUtiles.particionDeBytes(paraLaBaliza);
        arrayDatosPartidos = BateriaDeMetodosUtiles.creacionBytesDelProtocoloTam20(tmp);
        Log.i("LENGTHESCRITURA", arrayDatosPartidos.get(0).length+"IS LEN");
        numeroDeParticionesDeDatos = arrayDatosPartidos.size();
        Log.i("DESCRIPTORWRITE","YES");
        descriptor.getCharacteristic().setValue(Constantes.PM_START+"");

        if ( gatt.writeCharacteristic( descriptor.getCharacteristic()) ) {

            Log.i("ESCRIBECHARINONDESCRIPT","TRUE");

        } else {

            Log.i("ESCRIBECHARINONDESCRIPT","FALSE");

        }

    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        Log.i("onCharacteristicChanger", "enter");

        vecesOnChanged++;
        char charrr = (char) characteristic.getValue()[0];
        Log.e("QUEESCHANGE1st", charrr+"");

        if (vecesOnChanged == 2 && charrr == '$'){

            Log.e("RESTAONCHANGE","TRUE");
            vecesOnChanged --;

        }

        byte[] valorCambiado = characteristic.getValue();
        Log.i("CHANGED", "TRUE");
        Log.i("itera", iteracionesLectura+"");
        Log.i("VALORCHANGED",new String(characteristic.getValue(), Charset.forName("UTF-8")));
        Log.i("VALORCHANGEDLEN",characteristic.getValue().length+"");

        if ((!protocoloLectura) || (protocoloLectura && (valorCambiado[0] != Constantes.PM_ACK))) {

            Log.d("C_PROTOCOLO_ON_CHANGED", "TRUE");
            protocolo(gatt, characteristic);

        }

    }
};

private void protocolo(final BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

    Log.w("ENTRAPROTOCOLO", "TRUE");
    try {

        handler.removeCallbacks(runnableCodeTimeOutTransmisiones);

    }catch (NullPointerException e) {

        e.printStackTrace();

    }

    byte[] valorLeido = characteristic.getValue();
    Log.i("Lectura: ", new String(characteristic.getValue(), Charset.forName("UTF-8")));
    String resultadoLegible = "";

    for (int i = 0; i < valorLeido.length; i++) {

        resultadoLegible += valorLeido[i] +"";
        //Log.i("Legible", resultadoLegible);

    }

    String valorEnHex = BateriaDeMetodosUtiles.bytesToHex(valorLeido);
    Log.i("VALORREADED:",resultadoLegible);
    Log.i("VALORHEX", valorEnHex);
    Log.i("ValorString", new String (characteristic.getValue(),Charset.forName("UTF-8")));
    Log.i("VALORLENGTH:",""+characteristic.getValue().length);

    if (iteracionesLectura <= numeroDeParticionesDeDatos) {// es menor o igual porque la primera vez lees solo para empezar la comunicacion, si no sería menor estrícto

        if(valorLeido[0] == Constantes.PM_ACK) {

            if (iteracionesLectura == numeroDeParticionesDeDatos) {

                Log.i("ESCRIBODESPEDIDA","TRUE");
                characteristic.setValue(Constantes.PM_END+"");

            } else {

                Log.i("LENGTHESCRITURA", arrayDatosPartidos.get(iteracionesLectura).length+"IS LEN");
                characteristic.setValue(arrayDatosPartidos.get(iteracionesLectura));


            }

            Log.e("LENGTHCHARESCRI", characteristic.getValue().length+"");
            boolean porcentaje;
            porcentaje = gatt.writeCharacteristic(characteristic);
            Log.w("LOQUEESCRIBO: ", BateriaDeMetodosUtiles.bytesToHex(characteristic.getValue())+ " : "+porcentaje);
            iteracionesLectura++;

        }else {

            Log.e("ERRORHEADER","no me ha devuelto un +");
            //gatt.disconnect();
            //gatt.close();
            //mGatt = null;
            iteracionesLectura = 0;
            sendBroadcast(intentError);
        }

    } else {

        protocoloLectura = true;

        if(!comunicacionTerminada){

            if(valorLeido[0] != Constantes.PM_END_ACK){

                if (valorLeido[0] ==  Constantes.PM_START) {

                    characteristic.setValue(Constantes.PM_ACK+"");

                    boolean porcentaje;
                    porcentaje = gatt.writeCharacteristic(characteristic);
                    Log.w("LOQUEESCRIBO: ", BateriaDeMetodosUtiles.bytesToHex(characteristic.getValue())+ " : "+porcentaje);

                }else if (valorLeido[0] == Constantes.PM_END){

                    characteristic.setValue(Constantes.PM_END_ACK+"");
                    boolean porcentaje;
                    porcentaje = gatt.writeCharacteristic(characteristic);
                    Log.w("LOQUEESCRIBO: ", BateriaDeMetodosUtiles.bytesToHex(characteristic.getValue())+ " : "+porcentaje);

                } else {

                    if (valorLeido[1] > 0 && valorLeido[1] <= 18) {

                        datosAJuntar.add(BateriaDeMetodosUtiles.addByteAlArrayFinal(valorLeido));//almaceno en un arrayList todos los datos que leo para después juntarlo.
                        characteristic.setValue(Constantes.PM_ACK+"");
                        boolean porcentaje;
                        porcentaje = gatt.writeCharacteristic(characteristic);
                        Log.w("LOQUEESCRIBO: ", BateriaDeMetodosUtiles.bytesToHex(characteristic.getValue())+ " : "+porcentaje);

                    }

                }

            }

        }else {

            //presenter.escribirEnToast("Valor leído en el Value de la Característica: " + new String(characteristic.getValue(), Charset.forName("UTF-8")));
            //gatt.disconnect();
            //gatt.close();
            //mGatt = null;
            iteracionesLectura = 0;
            retry = false;
            Log.i("Comunicacion terminada", "TRUE");

        }

    }
}

private void retrySameMotivo() {

    contadorRetrys++;
    Log.e("RetryMOTIVOSAME", "TRUE");
    //mGatt = null;
    try {

        mGatt.disconnect();
        mGatt.close();
        conectaConEsteMotivoRetry(idMotivo);

    }catch (NullPointerException e){

        e.printStackTrace();
        sendBroadcast(intentError);

    }

}

public void conectaConEsteMotivoRetry(String idmotivo){

    this.idMotivo = idmotivo;
    handler.removeCallbacks(runnableCodeTimeOutConversacion);
    //handler.postDelayed(timeOutFirmado, 10000);
    if (mGatt != null) {

        try{

            //myTimerProtocolo = null;
            handler.removeCallbacks(runnableCodeTimeOutTransmisiones);
            Log.d("mBluetoothDevice", "mBluetoothDevice.connectGatt called in the retry...");
            /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                            Log.d("BOUNDING??? ", mBluetoothDevice.createBond()+"");
                        }*/
            mGatt = mBluetoothDevice.connectGatt(getApplicationContext(), false, gattCallback);
            //stopScan();// will stop after first device detection

        }catch (NullPointerException e){

            e.printStackTrace();

        }

    } else {

        Log.i("MGATTISNULL","MGATT ES NULL");

    }

}

private Runnable runnableCodeTimeOutTransmisiones = new Runnable() {
    @Override
    public void run() {

        if (!esperandoDesconexion) {

            //contadorRetrys = (int) NUMEROS_DE_RETRYS;

            try {

                Log.e("TIMERPROTOCOLO", "TRUE");
                if(mGatt!= null){

                    mGatt.disconnect();
                    mGatt.close();

                }

                if (!retry){


                    Log.e("TIMEOUT","TRANSMISIONES");
                    // presenter.escribirEnToast("TIMEOUT Transmisiones");
                    sendBroadcast(intentError);
                }/*else {

                retrySameMotivo();

            }*/

            }catch (NullPointerException e){

                e.printStackTrace();

            }

        }

    }
};

private Runnable timeOutFirmado = new Runnable() {

    @Override
    public void run() {

        try {

            Log.e("TIMEOUTGLOBALMAXFIRMADO", "TRUE");
            //presenter.escribirEnToast("TIMEOUT Global FIRMANDO");
            //PRUEBA LISTASCAN
            sendBroadcast(intentError);
            mGatt.disconnect();
            mGatt.close();
        }catch (Exception e){

            e.printStackTrace();

            try {

                Log.e("HACER DESCONAMANO","TRUE");
                mGatt.disconnect();
                mGatt.close();


            }catch (Exception exc){

                exc.printStackTrace();

            }

        }

    }
};

@Nullable
@Override
public IBinder onBind(Intent intent) {

    return mBinder;

}

@Override
public boolean onUnbind(Intent intent) {

    try{
        mGatt.disconnect();
        mGatt.close();
        Log.e("UNBINDFirmado", "UNBIND");
        //presenter.lanzarServicioFirmado();

        try {

            handler.removeCallbacks(runnableCodeTimeOutTransmisiones);
            handler.removeCallbacks(runnableCodeTimeOutConversacion);
            handler.removeCallbacks(timeOutFirmado);

            /*if (presenter.getErrorFirmando() && presenter.getNumeroIntentosFirmar() <= 2){

                presenter.setNumeroIntentosFirmar(presenter.getNumeroIntentosFirmar() + 1);
                presenter.setFlagScanDevice(true);
                presenter.escribirEnToast("Reintento...");
                presenter.connectToDeviceServicio(presenter.getActualDevice(), presenter.getNserieString());

            }else {


                presenter.setNumeroIntentosFirmar(0);
                //presenter.desaparecerBotonesMotivos();
                presenter.setVisibilityMensajeDespuesDeFirmar(View.VISIBLE);
                presenter.setVisibilityBotonAceptarDespuesDeFirmar(View.VISIBLE);
                presenter.setIconFirmadoEstado(R.drawable.check_gif);

                if(presenter.getTextDespuesFirmado().equals("Ha ocurrido un problema con su fichaje, vuelva a intentarlo.")){

                    presenter.setVisibilityBotonReintentar(View.VISIBLE);

                }

            }*/

        }catch (NullPointerException e){

            Log.e("ERROR IN UNBIND", "A NULLPOINT");
            e.printStackTrace();

        }

    }catch (Exception e){

        e.printStackTrace();

    }

    return super.onUnbind(intent);

}

}

1 ответ

Может возвращать false, потому что в BLE вы можете выполнять одну операцию за раз. Если вы выполняете множественную запись одновременно, тогда выполняется только последняя запись.

Итак, вам нужно подождать, пока один из них напишет, тогда вы можете написать другой.

Другие вопросы по тегам