Хобрук: Ваш путь к мастерству в программировании

Отображение последовательных данных Bluetooth

Я новичок в разработке Android и работаю с Bluetooth-связью на своем планшете под управлением 4.2.2. Я хочу получать данные, отправленные с модуля Bluetooth на мой планшет. Я хорошо понимаю, как настроить сокеты Bluetooth через веб-сайт Android, однако мне нужна помощь в получении входящих последовательных данных. Используя приведенный ниже код, я могу найти модуль, открыть соединение сокета и подключиться к нему (на что указывает зеленый свет на модуле), однако мне нужна помощь в отображении переданных данных в пользовательском интерфейсе через TextView. Модуль отправляет 2 байта данных каждую секунду со скоростью 9600 бод. Насколько я понимаю, run() считывает 2 байта данных и сохраняет их в буфере. Затем эти байты передаются обработчику, который отображает их на экране через «case MESSAGE_READ;». Может кто-нибудь, пожалуйста, дайте мне знать, что я делаю неправильно?

package com.example.bluetoothtest;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnItemClickListener {

TextView mTextView;
ArrayAdapter<String> listAdapter;
ListView listView;
BluetoothAdapter btAdapter;
Set<BluetoothDevice> devicesArray;
ArrayList<String> pairedDevices;
ArrayList<BluetoothDevice> devices;
public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
protected static final int SUCCESS_CONNECT = 0;
protected static final int MESSAGE_READ = 1;
IntentFilter filter;
BroadcastReceiver receiver;
String tag = "debugging";
Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        // TODO Auto-generated method stub
        Log.i(tag, "in handler");
        super.handleMessage(msg);
        switch(msg.what){
        case SUCCESS_CONNECT:

            ConnectedThread connectedThread = new     ConnectedThread((BluetoothSocket)msg.obj);
            Toast.makeText(getApplicationContext(), "CONNECT", 0).show();
            String s = "successfully connected";
            connectedThread.write(s.getBytes());
            Log.i(tag, "connected");
            break;
        case MESSAGE_READ:
            String str = (String)msg.obj;
            mTextView.setText(str); 
        }
        super.handleMessage(msg); 
        }
};
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView=(TextView)findViewById(R.id.txtData);
    init();
    if(btAdapter==null){
        Toast.makeText(getApplicationContext(), "No bluetooth detected", 0).show();
        finish();
    }
    else{
        if(!btAdapter.isEnabled()){
            turnOnBT();
        }

        getPairedDevices();
        startDiscovery();
    }


}
private void startDiscovery() {
    // TODO Auto-generated method stub
    btAdapter.cancelDiscovery();
    btAdapter.startDiscovery();

}
private void turnOnBT() {
    // TODO Auto-generated method stub
    Intent intent =new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(intent, 1);
}
private void getPairedDevices() {
    // TODO Auto-generated method stub
    devicesArray = btAdapter.getBondedDevices();
    if(devicesArray.size()>0){
        for(BluetoothDevice device:devicesArray){
            pairedDevices.add(device.getName());

        }
    }
}
private void init() {
    // TODO Auto-generated method stub
    listView=(ListView)findViewById(R.id.listView);
    listView.setOnItemClickListener(this);
    listAdapter= new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,0);
    listView.setAdapter(listAdapter);
    btAdapter = BluetoothAdapter.getDefaultAdapter();
    pairedDevices = new ArrayList<String>();
    filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    devices = new ArrayList<BluetoothDevice>();
    receiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Auto-generated method stub
            String action = intent.getAction();

            if(BluetoothDevice.ACTION_FOUND.equals(action)){
                BluetoothDevice device =     intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                devices.add(device);
                String s = "";
                for(int a = 0; a < pairedDevices.size(); a++){
                       if(device.getName().equals(pairedDevices.get(a))){
                        //append 
                        s = "(Paired)";
                        break;
                    }
                }

                listAdapter.add(device.getName()+" "+s+" "+"\n"+device.getAddress());
            }

            else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){

            }
            else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){

            }

            else if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){
                if(btAdapter.getState() == btAdapter.STATE_OFF){
                    turnOnBT();
                }
            }

        }
    };

    registerReceiver(receiver, filter);
     filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    registerReceiver(receiver, filter);
     filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    registerReceiver(receiver, filter);
     filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
    registerReceiver(receiver, filter);
}


@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    unregisterReceiver(receiver);
}

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_CANCELED){
            Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
            long arg3) {
        // TODO Auto-generated method stub

        if(btAdapter.isDiscovering()){
            btAdapter.cancelDiscovery();
        }
        if(listAdapter.getItem(arg2).contains("Paired")){

            BluetoothDevice selectedDevice = devices.get(arg2);
            ConnectThread connect = new ConnectThread(selectedDevice);
            connect.start();
            Log.i(tag, "in click listener");
        }
        else{
            Toast.makeText(getApplicationContext(), "device is not paired", 0).show();
        }
    }

    private class ConnectThread extends Thread {

        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;
            Log.i(tag, "construct");
            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) { 
                Log.i(tag, "get socket failed");

            }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it will slow down the connection
            btAdapter.cancelDiscovery();
            Log.i(tag, "connect - run");
            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
                Log.i(tag, "connect - succeeded");
            } catch (IOException connectException) {    Log.i(tag, "connect failed");
                // Unable to connect; close the socket and get out
                try {
                    mmSocket.close();
                } catch (IOException closeException) { }
                return;
            }

            // Do work to manage the connection (in a separate thread)

            mHandler.obtainMessage(SUCCESS_CONNECT, mmSocket).sendToTarget();
        }

        /** Will cancel an in-progress connection, and close the socket */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }

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

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
            Log.i(tag, "socket connect success");
            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                Log.i(tag, "socket success");
                tmpOut = socket.getOutputStream();
            } catch (IOException e) { }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {  
            Log.i(tag, "run success");
            byte[] buffer = new byte[2];
            int bytes; // bytes returned from read() 

            // Keep listening to the InputStream until an exception occurs 
            while (true) {
                try {
                    // Read from the InputStream 
                    bytes = mmInStream.read(buffer);
                    Log.i(tag, "buffer read OK");
                    // Send the obtained bytes to the UI activity 
                    String str = new String(buffer); 
                    mHandler.obtainMessage(MESSAGE_READ, bytes, -1, str).sendToTarget();
                }catch (Exception e) {
                    Log.i(tag, "buffer read failed");
                    System.out.print("read error"); 
                    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) { }
        }

        /* Call this from the main activity to shutdown the connection */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }
}

  • Чем результат отличается от ожидаемого? Какова природа данных? Он уже состоит из печатных кодов символов? Или это число, которое вам нужно преобразовать в текстовое представление для отображения? 03.03.2014
  • @ChrisStratton пользовательский интерфейс ничего не отображает. Мой Bluetooth передает результат 2-байтового АЦП. В частности, он отправляет 03 FF (1023 в десятичном формате). Я подтвердил это, получив 03 FF на гипертерминале на моем компьютере. Я займусь форматированием, как только смогу заставить пользовательский интерфейс что-то отображать. Есть ли что-то особенное в моем коде, из-за чего он не работает? Если это выглядит нормально, я могу устранить это из проблемы и опубликовать остальную часть кода. 04.03.2014
  • Возможно, проблема с вашим обработчиком. Вы можете попробовать регистрировать полученные символы сразу после их получения. Кроме того, то, как вы это написали, если оно когда-либо терпит неудачу, похоже, что оно может сдаться навсегда и никогда (повторно подключиться и?) не начать пытаться снова. 04.03.2014
  • @ChrisStratton Я думаю, что, возможно, происходит что-то еще, поэтому я опубликовал полный код. Если бы была ошибка чтения в байтах, я должен был получить ошибку чтения от улова. Я думаю, что run() никогда не выполняется, но я не уверен, где ошибка в коде. 04.03.2014
  • Вместо того, чтобы делать предположения, просто внесите журнал, чтобы проверить, работают ли различные части, а затем проверьте журналы. 04.03.2014
  • @ChrisStratton спасибо. Я реализовал отладку, войдя в LogCat, и обнаружил, что поток run() в «частном классе ConnectedThread extends Thread {», который содержит прочитанный код, не выполняется. Все, что предшествует run(), выполняется так, как должно, т. е. 'tmpIn = socket.getInputStream();' выполняет. Я также одновременно запускаю поток в «частном классе ConnectThread extends Thread {», который используется для подключения к сокету, и это нормально. Почему эта часть кода не работает? 08.03.2014
  • Попробуйте сделать ваше сообщение журнала абсолютным первым, что произойдет в методе run(). Также поместите сообщение журнала в конец конструктора. Вы уверены, что в logcat нет исключений? 08.03.2014
  • Я сделал это, и сообщение журнала не появляется в logcat. Я добавил Log.i (тег, успешное выполнение); прямо под public void run() {. Я обновил полный код. 08.03.2014
  • У вас есть какая-то ошибка, но вы не можете ее увидеть, так как ваши обработчики исключений молча проглатывают исключения. Каждому нужен e.printStackTrace(), чтобы вы могли видеть, что происходит не так. 10.04.2014

Ответы:


1

Пытаться:

случай SUCCESS_CONNECT:

    ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
    Toast.makeText(getApplicationContext(), "CONNECT", 0).show();
    String s = "successfully connected";
    connectedThread.write(s.getBytes());
    Log.i(tag, "connected");
    connectedThread.run();

    break;
04.04.2014

2

На самом деле вам следует звонить connectedThread.start(), а НЕ connectedThread.run(). Метод start() заставляет connectedThread выполнять свой метод run() в отдельном потоке. Если вы напрямую вызываете run(), как это предлагается выше, то только этот метод run() (который обычно представляет собой бесконечный цикл) заблокирует весь остальной код, включая поток пользовательского интерфейса.

03.09.2016
Новые материалы

Учебные заметки JavaScript Object Oriented Labs
Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

Разбор строк запроса в vue.js
Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
«Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..

Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

Как настроить Selenium в проекте Angular
Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

Введение в Джанго Фреймворк
Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..