设置从蓝牙发送和接收数据之间的延迟

set delay between send and receive data from bluetooth

我设置了一个程序,使用 SPP 通过蓝牙将数据从 android 应用程序发送到微控制器。提到的微控制器设备在处理时间为 150 毫秒后发回响应。我的应用程序通过蓝牙响应处理程序收到适当的响应,因为 RecieveBuffer.And 应用程序必须再次发送数据以防微控制器未发送适当的数据。我使用如下的 while 条件语句交替发送数据,直到获得响应(在应用程序通过蓝牙响应处理程序 class 获得适当响应后,发送标志为真)。

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

有一个程序,我的程序连续发送数据,蓝牙响应处理程序从未收到任何响应,因为 while 语句检查发送标志(send flag 在应用程序获得适当响应后为真)。

如何设置让我的应用程序等待响应的延迟?我的意思是我必须发送数据并等待响应,如果响应不可接受我必须再次发送数据。

没有while语句,我可以发送数据并得到响应。但我也必须检查接收到的数据是否可以接受。

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

非常感谢您。

我找到了解决上述问题的方法,因此我应用了一个 CountDownTimer,它每 1 秒到 3 秒发送一次数据,如果发送的数据和响应都正常,定时器将被取消以避免浪费时间。在正常情况下,此计时器会在应用程序收到适当的响应后发送一次数据。

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