Bluetooth-соединения Android

Я пытаюсь передать данные со своего телефона Android на Glass.

Я нашел это: https://stackoverflow.com/a/20414642/318800 и перенес его в небольшое приложение.

Однако, когда я запускаю свое приложение, поток поиска зависает на

socket = mmServerSocket.accept();

Поэтому я не получаю никаких связей. Что-то изменилось, что это больше не работает для подключения/обнаружения соединений Bluetooth?

Может ли кто-нибудь указать мне на что-то, что может помочь мне получить данные с устройства Android 4.4 на стекло?


person N_tro_P    schedule 06.06.2014    source источник


Ответы (1)


Я могу заставить свой планшет Nexus 7 под управлением Android 4.4.2 и Glass XE 17.2 обмениваться данными без проблем. Вы можете запустить ClassicBluetoothServer.java либо на Glass, либо на другом устройстве Android, а затем запустить ClassicBluetoothClient.java на другом устройстве. В клиентском коде вам нужно изменить значение CBT_SERVER_DEVICE_NAME на имя сопряженного устройства Glass или Android (как показано в настройках Bluetooth устройства).

Код клиента:

public class ClassicBluetoothClient extends Activity {

    public final static String TAG = "ClassicBluetoothClient";
    public static final int REQUEST_TO_ENABLE_BT = 100;
    private BluetoothAdapter mBluetoothAdapter;
    private TextView mTvInfo;
    private UUID MY_UUID = UUID.fromString("D04E3068-E15B-4482-8306-4CABFA1726E7"); 
    private final static String FILE_PATH_RECEIVED = Environment.getExternalStorageDirectory().getPath()  +"/filefromCBTserver"; 

    // replace this with your own device names  
    private final static String CBT_SERVER_DEVICE_NAME = "Jeff Tang's Glass"; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTvInfo = (TextView) findViewById(R.id.info);
        mTvInfo.setText("Classic Bluetooth Client");
        //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();      

        if (mBluetoothAdapter == null) {
            Log.v(TAG, "Device does not support Bluetooth");
            Toast.makeText(ClassicBluetoothClient.this, "Device does not support Bluetooth", Toast.LENGTH_LONG).show();         
            return;
        }
        else { 
            if (!mBluetoothAdapter.isEnabled()) {
                Log.v(TAG, "Bluetooth supported but not enabled");
                Toast.makeText(ClassicBluetoothClient.this, "Bluetooth supported but not enabled", Toast.LENGTH_LONG).show();                           
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_TO_ENABLE_BT); 
            }else{
                Log.v(TAG, "Bluetooth supported and enabled");
                // discover new Bluetooth devices
                discoverBluetoothDevices();

                // find devices that have been paired 
                getBondedDevices();
            }           
        }        

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_TO_ENABLE_BT) { 
            discoverBluetoothDevices();
            getBondedDevices();
            return;
        }
    }   

    void discoverBluetoothDevices () {
        // register a BroadcastReceiver for the ACTION_FOUND Intent 
        // to receive info about each device discovered.
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);       
        registerReceiver(mReceiver, filter); 
        mBluetoothAdapter.startDiscovery();
    }

    // for each device discovered, the broadcast info is received
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Log.v(TAG, "BroadcastReceiver on Receive - " + device.getName() + ": " + device.getAddress());
                String name = device.getName();

                // found another Android device of mine and start communication
                if (name != null && name.equalsIgnoreCase(CBT_SERVER_DEVICE_NAME)) {
                    new ConnectThread(device).start();
                }
            }           
        }
    };

    protected void onDestroy() {
        unregisterReceiver(mReceiver);
        super.onDestroy();
    }   

    // bonded devices are those that have already paired with the current device sometime in the past (and have not been unpaired)  
    void getBondedDevices () {
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                Log.v(TAG, "bonded device - " + device.getName() + ": " + device.getAddress());
                if (device.getName().equalsIgnoreCase(CBT_SERVER_DEVICE_NAME)) {
                    Log.d(TAG, CBT_SERVER_DEVICE_NAME);
                    new ConnectThread(device).start();
                    break;
                }
            }
        }       
        else {
            Toast.makeText(ClassicBluetoothClient.this, "No bonded devices", Toast.LENGTH_LONG).show();         
        }
    }

    private class ConnectThread extends Thread {
        int bytesRead;
        int total;      
        private final BluetoothSocket mmSocket;
        public ConnectThread(BluetoothDevice device) {
            BluetoothSocket tmp = null;
            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                Log.v(TAG, "before createRfcommSocketToServiceRecord");
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
                Log.v(TAG, "after createRfcommSocketToServiceRecord");
            } catch (IOException e) { 
                Log.v(TAG, " createRfcommSocketToServiceRecord exception: "+ e.getMessage());
            }
            mmSocket = tmp;
        }
        public void run() {
            // Cancel discovery because it will slow down the connection
            mBluetoothAdapter.cancelDiscovery();
            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
            } catch (IOException e) {
                Log.v(TAG, e.getMessage());
                try {
                    mmSocket.close();
                } catch (IOException closeException) { }
                return;
            }
            manageConnectedSocket(mmSocket);
        }   

        private void manageConnectedSocket(BluetoothSocket socket) {
            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];
            FileOutputStream fos = null;
            BufferedOutputStream bos = null;

            try {
                InputStream instream = socket.getInputStream();
                fos = new FileOutputStream( FILE_PATH_RECEIVED );
                bos = new BufferedOutputStream(fos);
                bytesRead = -1;
                total = 0;
                while ((bytesRead = instream.read(buffer)) > 0) {
                    total += bytesRead;
                    bos.write(buffer, 0, bytesRead);
                    Log.i(TAG, "bytesRead="+bytesRead+",bufferSize="+bufferSize+",total="+total);
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mTvInfo.setText("bytesRead="+bytesRead+", total="+total);
                        }
                    });                     
                }
                runOnUiThread(new Runnable() {
                    public void run() {
                        mTvInfo.setText(total + " bytes of file " + FILE_PATH_RECEIVED + "has been received");
                    }
                });                             
                bos.close();
                socket.close();
            } catch (IOException e) {
                try {
                    socket.close(); 
                    bos.close();}
                catch (IOException e2) {
                    Log.e(TAG, "socket close exception:", e2);
                }
            }
        }   
    }
}

Код сервера:

public class ClassicBluetoothServer extends Activity {

    public final static String TAG = "ClassicBluetoothServer";
    BluetoothAdapter mBluetoothAdapter;
    BluetoothServerSocket mBluetoothServerSocket;
    public static final int REQUEST_TO_START_BT = 100;
    public static final int REQUEST_FOR_SELF_DISCOVERY = 200;
    private TextView mTvInfo;

    UUID MY_UUID = UUID.fromString("D04E3068-E15B-4482-8306-4CABFA1726E7");

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTvInfo = (TextView) findViewById(R.id.info);

        // initialize Bluetooth and retrieve info about the BT radio interface
        //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();      

        if (mBluetoothAdapter == null) {
            mTvInfo.setText("Device does not support Bluetooth");
            return;
        } else {
            if (!mBluetoothAdapter.isEnabled()) {
                mTvInfo.setText("Bluetooth supported but not enabled");
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_TO_START_BT);
            } else {
                mTvInfo.setText("Bluetooth supported and enabled");             
                new AcceptThread().start();
            }
        }
    }

    private class AcceptThread extends Thread {
        private BluetoothServerSocket mServerSocket;

        public AcceptThread() {
            try {
                mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("ClassicBluetoothServer", MY_UUID);
            } 
            catch (IOException e) {
                final IOException ex = e;
                runOnUiThread(new Runnable() {
                    public void run() {
                        mTvInfo.setText(ex.getMessage());
                    }
                });
            }
        }

        public void run() {
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned
            while (true) {
                try {
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mTvInfo.setText(mTvInfo.getText() + "\n\nWaiting for Bluetooth Client ...");
                        }
                    });

                    socket = mServerSocket.accept(); // blocking call

                } catch (IOException e) {
                    Log.v(TAG, e.getMessage());
                    break;
                }
                // If a connection was accepted
                if (socket != null) {
                    // Do work in a separate thread
                    new ConnectedThread(socket).start();

                    try {
                        mServerSocket.close();                      
                    } catch (IOException e) {
                        Log.v(TAG, e.getMessage());
                    }
                    break;
                }
            }
        }
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mSocket;
        private final OutputStream mOutStream;
        private int bytesRead;
        final private String FILE_TO_BE_TRANSFERRED = "marchmadness.png";
        final private String PATH = Environment.getExternalStorageDirectory().toString() + "/nbsocial/";        

        public ConnectedThread(BluetoothSocket socket) {
            mSocket = socket;
            OutputStream tmpOut = null;

            try {
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, e.getMessage());
            }
            mOutStream = tmpOut;
        }

        String copyAsset(String filename) {
            File dir = new File(PATH);
            if (!dir.exists()) {
                if (!dir.mkdirs()) {
                    return null;
                }
            }

            if (!(new File( PATH + filename).exists())) {
                try {

                    AssetManager assetManager = getAssets();
                    InputStream in = assetManager.open(filename);
                    OutputStream out = new FileOutputStream(PATH + filename);

                    // Transfer bytes from in to out
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.close();

                } catch (IOException e) {
                    Log.e(TAG, "Was unable to copy " + filename + e.toString());
                    return null;
                }
            }       
            return PATH + filename; 
        }       


        public void run() {
            byte[] buffer = new byte[1024];

            // transfer a file
            if (mOutStream != null) {
                File myFile = new File( copyAsset("test.png") );
                FileInputStream fis = null;

                try {
                    fis = new FileInputStream(myFile);
                } catch (FileNotFoundException e) {
                    Log.e(TAG, e.getMessage());
                }
                BufferedInputStream bis = new BufferedInputStream(fis);
                runOnUiThread(new Runnable() {
                    public void run() {
                        mTvInfo.setText(mTvInfo.getText() + "\nbefore sending file "+  PATH + FILE_TO_BE_TRANSFERRED + " of " + new File(  PATH + FILE_TO_BE_TRANSFERRED ).length() + " bytes");
                    }
                });
                try {
                    bytesRead = 0;
                    for (int read = bis.read(buffer); read >= 0; read = bis.read(buffer))
                    {
                        mOutStream.write(buffer, 0, read);
                        bytesRead += read;
                    }

                    mSocket.close();
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mTvInfo.setText(bytesRead + " bytes of file " +  PATH + FILE_TO_BE_TRANSFERRED + " has been sent.");
                        }
                    });                 

                } catch (IOException e) {
                    Log.e(TAG, e.getMessage());
                }
            }

            new AcceptThread().start();             
        }
    }
}
person Jeff Tang    schedule 07.06.2014
comment
Выглядит отлично! У меня все еще есть некоторые проблемы :-( В частности, я думал, что мой телефон был 4.4 (упс), но это 4.3, и бомбы клиентского кода на copyAsset (я сделал фиктивное изображение test.png с возможностью рисования в моем каталоге ресурсов) , Я не уверен, что это бомбит из-за версии. Кроме того, у меня есть Nexus с версией 4.4, но я даже не могу выполнить сопряжение. Я загрузил MyGLass на свой нексус и отключил его от своего телефона, но он все еще не может его найти. Есть идеи?Я бы предпочел клиентский код на моем телефоне 4.3. - person N_tro_P; 10.06.2014
comment
На данный момент, что я действительно хочу сделать, это просто отправить числовое значение, которое я ввожу на своем телефоне, на стекло для стекла, чтобы сделать график. Поэтому, если проще не отправлять файловый поток и отправлять строку, я был бы очень признателен, если бы вы объяснили это. - person N_tro_P; 10.06.2014