gatt.writeCharacteristic()可能返回false的原因是什么?

时间:2018-02-22 09:48:03

标签: java android bluetooth-lowenergy gatt

我正在开发Android BLE应用程序。我在某些Android设备中面临的问题是,当我使用writeCharacteristic()方法在特征中写入数据时,它返回false并且不写入。 你知道为什么它会返回虚假的情况吗? 使用我的BQ Aquaris U Plus它不会发生,只是成功写入并返回true。但是对于我的华为Y6,它发生了很多次。也许7/10个案例它会返回false。 这是我的代码,是如此之大,但可以提供帮助:

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 个答案:

答案 0 :(得分:1)

它可能返回false,因为在BLE中你可以一次执行一个操作。如果您同时执行多次写入,则它只执行最后一次写入。

所以,你必须等到一个人写,然后你可以写另一个。