Search code examples
androidbluetoothdelayhandler

set delay between send and receive data from bluetooth


I set a program to send data from the android app to a microcontroller through bluetooth using SPP. mentioned microcontroller device sends a response back after 150 milisec as processing time. My app receives an appropriate response by bluetooth response handler as RecieveBuffer.And application must send data again for the case when the microcontroller doesn't send an appropriate. I used a while conditional statement like below to send data alternatively until getting a response (send flag is true after app gets an appropriate response by bluetooth response handler class).

while(!SendFlag) SendData( SendBuffer+"\r" );

there is a program that my program sends data consecutively and Bluetooth response handler never gets any response since while statement that checks send flag(send flag is true after app gets an appropriate response).

How can I set a delay that makes my app waiting for the response? I mean I have to send data and wait for the response and if response is inacceptable I have to send data again.

without while statement, I can send data and get a response. but I have to check whether received data are acceptable too.

package com.np.schoolbell;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.icu.text.SimpleDateFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import ir.mirrajabi.persiancalendar.PersianCalendarView;
import ir.mirrajabi.persiancalendar.core.PersianCalendarHandler;
import ir.mirrajabi.persiancalendar.core.models.PersianDate;


public class ledControl extends AppCompatActivity {

    EditText et_SendData;
    static TextView tv_DataReaded;

    PersianCalendarView persianCalendarView;
    PersianCalendarHandler calendar;
    PersianDate today;
    PersianDate sampleday;

    List days;

    String address = null;
    static String TransmiterCode="999";
    static String SendBuffer=null;
    static String RecieveBuffer=null;
    static int Counter=0;
    static boolean SendFlag=false;

    BluetoothAdapter bAdapter = null;
    BluetoothDevice  bDevice  = null;
    BluetoothSocket  bSocket = null;
    static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //SPP UUID. Look for it
    ConnectedThread cThread;
    private static BluetoothResponseHandler brHandler;
    private final static int DataIsReady = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_led_control);
        persianCalendarView  = (PersianCalendarView)findViewById(R.id.persian_calendar2);
        calendar = persianCalendarView.getCalendar();
        today = calendar.getToday();
        //days=calendar.getDays(1);
        //Toast.makeText(this, days.toString(), Toast.LENGTH_LONG).show();
        //today.setDate(1398,05,01);
        //Toast.makeText(this, today.toString(), Toast.LENGTH_LONG).show();

        et_SendData = (EditText) findViewById(R.id.et_SendData);
        tv_DataReaded = (TextView) findViewById(R.id.tv_DataReaded);

        address = getIntent().getStringExtra( "device_address" );

        bAdapter = BluetoothAdapter.getDefaultAdapter();

        try {
            Toast.makeText(getApplicationContext(), "Connecting...", Toast.LENGTH_SHORT).show();

            if( bSocket == null ) {
                bDevice = bAdapter.getRemoteDevice(address);
                bSocket = bDevice.createInsecureRfcommSocketToServiceRecord(myUUID);
                bAdapter.cancelDiscovery();
                bSocket.connect();
            }

            Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show();
        }
        catch (Exception e) {
            Toast.makeText(getApplicationContext(), "Connection Failed. Is it a SPP Bluetooth? Try again.", Toast.LENGTH_SHORT).show();
            finish();
        }

        cThread = new ConnectedThread(bSocket);
        cThread.start();

        if (brHandler == null) brHandler = new BluetoothResponseHandler(this);
        else brHandler.setTarget(this);


    }

    public void onClick_btn_SendData( View v ) {
        SendBuffer=LoadDateTimeBuffer();
        while(!SendFlag) SendData( SendBuffer+"\r" );
        SendBuffer=LoadAZanSetting();
        while(!SendFlag) SendData( SendBuffer+"\r" );

        et_SendData.setText("");
    }
    public String LoadDateTimeBuffer(){
        SendFlag=false;
        TransmiterCode="420";
        SimpleDateFormat sdf = new SimpleDateFormat("HHmmss", Locale.getDefault());
        String currentTime = sdf.format(new Date());
        String currentDate=ParseFaDigits.convert(calendar.formatNumber(today.getYear()))+ParseFaDigits.convert(calendar.formatNumber(today.getMonth()))+ParseFaDigits.convert(calendar.formatNumber(today.getDayOfMonth()));
        return TransmiterCode+currentTime+currentDate;
    }
    public String LoadAZanSetting(){
        SendFlag=false;
        TransmiterCode="421";
        boolean fajrflag=true;boolean tolueflag=true;boolean zuhrflag=true;boolean maghribflag=true;boolean ishaflag=true;
        String FajrFlagString = (fajrflag) ? "1" : "0";
        String TolueFlagString = (tolueflag) ? "1" : "0";
        String ZuhrFlagString = (zuhrflag) ? "1" : "0";
        String MaghribFlagString = (maghribflag) ? "1" : "0";
        String IshaFlagString = (ishaflag) ? "1" : "0";
        return TransmiterCode+FajrFlagString+TolueFlagString+ZuhrFlagString+MaghribFlagString+IshaFlagString;
    }

    public void SendData(String Data) {

        if( bSocket != null ) {
            try {
                bSocket.getOutputStream().write(Data.getBytes());
            }
            catch (Exception e) {
                Toast.makeText(getApplicationContext(), "Error in Send Data", Toast.LENGTH_LONG).show();
            }
        }
        else {
            Toast.makeText(getApplicationContext(), "Bluetooth is Not Connected", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if( bSocket == null ) return;

        if( bSocket.isConnected() ) {
            Disconnect();
        }
    }
    public void onClick_Bluetooth_btn_Disconnect( View v ) {
        Disconnect();
    }
    public void Disconnect() {

        if ( bSocket != null && bSocket.isConnected() ) {
            try  {
                bSocket.close();
                Toast.makeText(getApplicationContext(), "Disconnected", Toast.LENGTH_SHORT).show();
            }
            catch( IOException e ) {
                Toast.makeText(getApplicationContext(), "Error in Disconnecting ", Toast.LENGTH_SHORT).show();
            }
        }
        finish();
    }

    public static class ConnectedThread extends Thread {
        private BluetoothSocket mmSocket;
        private InputStream mmInStream;
        private OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the input and output streams, using temp objects because member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;

            //Tell other phone that we have connected
            write("connected".getBytes());
        }

        public void run() {
            byte[] buffer = new byte[512];
            int bytes;
            StringBuilder readMessage = new StringBuilder();

            while( !this.isInterrupted() ) {
                try {
                    bytes = mmInStream.read(buffer);
                    String readed = new String(buffer, 0, bytes);
                    readMessage.append(readed);

                    if (readed.contains("\r")) {
                        brHandler.obtainMessage(ledControl.DataIsReady, bytes, -1, readMessage.toString()).sendToTarget();
                        readMessage.setLength(0);
                    }
                } catch (Exception e) {
                    break;
                }
            }
        }

        // Call this from the main activity to send data to the remote device
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // Call this from the main activity to shutdown the connection
        public void cancel() {
            if (mmInStream != null) {
                try {mmInStream.close();} catch (Exception e) {}
                mmInStream = null;
            }

            if (mmOutStream != null) {
                try {mmOutStream.close();} catch (Exception e) {}
                mmOutStream = null;
            }

            if (mmSocket != null) {
                try {mmSocket.close();} catch (Exception e) {}
                mmSocket = null;
            }

            this.interrupt();
        }
    }

    private static class BluetoothResponseHandler extends Handler {
        private WeakReference<ledControl> mActivity;

        public BluetoothResponseHandler(ledControl activity) {
            mActivity = new WeakReference<ledControl>(activity);
        }

        public void setTarget(ledControl target) {
            mActivity.clear();
            mActivity = new WeakReference<ledControl>(target);
        }

        @Override
        public void handleMessage(Message msg) {
            ledControl activity = mActivity.get();
            String Data =  (String)msg.obj;

            if (activity != null) {
                switch (msg.what) {
                    case DataIsReady :
                        if( Data == null ) return;
                        RecieveBuffer=Data;

                        if(RecieveBuffer.contains(SendBuffer))
                        {
                            tv_DataReaded.append(Data);
                            SendFlag=true;
                            TransmiterCode="";
                            SendBuffer="";
                            RecieveBuffer="";
                        }
                        else
                        {
                            SendFlag=false;
                        }
                        break;
                }
            }
        }
    }
}

Thank you a lot in advance.


Solution

  • I found a way to solve the mentioned problem so that I applied a CountDownTimer which sends data every 1 sec through 3 sec and the timer will be canceled due to avoid wasting time if sent data and response are ok both. in regular conditions, this timer sends data once since the application receives an appropriate response.

    SendBuffer=LoadDateTimeBuffer();
    CountDownTimer yourCountDownTimer=new CountDownTimer(3000, 1000) {
            public void onFinish() {
                Toast.makeText(ledControl.this, "Error", Toast.LENGTH_SHORT).show();
            }
            public void onTick(long millisUntilFinished) {
                // millisUntilFinished    The amount of time until finished.
                if(!SendFlag)SendData( SendBuffer+"\r" );
                else {Toast.makeText(ledControl.this, "sent", Toast.LENGTH_SHORT).show();this.cancel();}
    
            }
        }.start();