Bluetooth: Wie schaffe ich eine ausgehende Verbindung?

L

Lybrial

Neues Mitglied
0
Hallo,

ich kämpfe nun seit zwei Tagen mit Android und Bluetooth. In dieser Zeit
habe ich folgendes erreicht:

  1. Ich kann Bluetooth aus meiner App heraus aktivieren
  2. Ich kann gekoppelte Bluetooth Geräte finden
  3. Ich kann neue Bluetooth Geräte finden

Das finden der gekoppelten bzw. der neuen Geräte habe ich wie folgt realisiert:

Code:
public class BluetoothFragment extends BaseFragment implements OnItemClickListener, OnClickListener {
    public static String EXTRA_DEVICE_NAME = "device_name";
    public static String EXTRA_DEVICE_ADDRESS = "device_address";
    private TextView textViewPairedDevices = null;
    private ListView listViewPairedDevices = null;
    private ArrayAdapter<String> adapterPairedDevices = null;
    private TextView textViewNewDevices = null;
    private ListView listViewNewDevices = null;
    private ArrayAdapter<String> adapterNewDevices = null;
    private Button buttonScan = null;
    private BluetoothBroadcastReceiver bluetoothBroadcastReceiver = null;
    private BluetoothAdapter bluetoothAdapter = null;
    private Set<BluetoothDevice> pairedDevices = null;
    private Set<String> newDevices = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.activity_bluetooth_fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        this.getActivity().setResult(Activity.RESULT_CANCELED);

        this.adapterPairedDevices = new ArrayAdapter<String>(this.getActivity(), R.layout.activity_bluetooth_fragment_device);
        this.adapterNewDevices = new ArrayAdapter<String>(this.getActivity(), R.layout.activity_bluetooth_fragment_device);

        this.textViewPairedDevices = (TextView) view.findViewById(R.id.bluetooth_textview_paired_devices);
        this.textViewNewDevices = (TextView) view.findViewById(R.id.bluetooth_textview_new_devices);
        this.listViewPairedDevices = (ListView) view.findViewById(R.id.bluetooth_listview_paired_devices);
        this.listViewPairedDevices.setAdapter(this.adapterPairedDevices);
        this.listViewPairedDevices.setOnItemClickListener(this);
        this.listViewNewDevices = (ListView) view.findViewById(R.id.bluetooth_listview_new_devices);
        this.listViewNewDevices.setAdapter(this.adapterNewDevices);
        this.listViewNewDevices.setOnItemClickListener(this);
        this.buttonScan = (Button) view.findViewById(R.id.bluetooth_button_scan);
        this.buttonScan.setOnClickListener(this);
    }

    /**
     * 
     */
    @Override
    public void onResume() {
        super.onResume();

        this.init();

        if (this.bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
            this.getActivity().finish();
        }
    }

    /**
     * 
     */
    @Override
    public void onPause() {
        super.onPause();

        if (this.bluetoothAdapter != null) {
            this.bluetoothAdapter.cancelDiscovery();
        }

        this.getActivity().unregisterReceiver(this.bluetoothBroadcastReceiver);
    }

    /**
     * 
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        this.bluetoothAdapter.cancelDiscovery();

        String info = ((TextView) view).getText().toString();

        if (info != null) {
            String[] infos = info.split("\n");
            String name= infos[0];
            String address = infos[1];

            Intent intent = new Intent();
            intent.putExtra(EXTRA_DEVICE_NAME, name);
            intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

            this.getActivity().setResult(Activity.RESULT_OK, intent);
            this.getActivity().finish();
        }
    }

    @Override
    public void onClick(View view) {
        switch(view.getId()) {
        case R.id.bluetooth_button_scan : {
            this.startDiscovery();
            this.buttonScan.setVisibility(View.GONE);
        } break;
        }
    }

    private void init() {
        this.bluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();

        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

        this.getActivity().registerReceiver(this.bluetoothBroadcastReceiver, filter);

        this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        this.newDevices = new HashSet<String>();
        this.pairedDevices = this.bluetoothAdapter.getBondedDevices();

        if(this.pairedDevices != null && !this.pairedDevices.isEmpty()) {
            this.textViewPairedDevices.setVisibility(View.VISIBLE);

            for(BluetoothDevice bluetoothDevice : this.pairedDevices) {
                this.adapterPairedDevices.add(bluetoothDevice.getName() + "\n" + bluetoothDevice.getAddress());
            }
        } else {
            this.adapterPairedDevices.add(this.getResources().getText(R.string.text_no_paired_devices).toString());
        }
    }

    private void startDiscovery() {
        this.adapterNewDevices.clear();
        this.newDevices.clear();

        this.getActivity().setProgressBarIndeterminateVisibility(true);
        this.getActivity().setTitle(this.getStringScanning());
        this.textViewNewDevices.setVisibility(View.VISIBLE);

        if (this.bluetoothAdapter.isDiscovering()) {
            this.bluetoothAdapter.cancelDiscovery();
        }

        this.bluetoothAdapter.startDiscovery();
    }

    private class BluetoothBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
                    getActivity().finish();
                }
            } else if(action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)){
                getActivity().setProgressBarIndeterminateVisibility(false);
                getActivity().setTitle(getStringSelect());

                if (newDevices.isEmpty()) {
                    adapterNewDevices.clear();
                    adapterNewDevices.add(getStringNoDevices());
                }

                buttonScan.setVisibility(View.VISIBLE);
            } else if(action.equals(BluetoothDevice.ACTION_FOUND)) {
                BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                if (bluetoothDevice != null) {
                    String address = bluetoothDevice.getAddress();

                    if (!newDevices.contains(address)) {
                        newDevices.add(address);
                        adapterNewDevices.add(bluetoothDevice.getName() + "\n" + bluetoothDevice.getAddress());
                    }
                } else {}
            }
        }
    };  
}

Nun bekomme ich also in meiner aufrufenden Activity den Namen und
die Adresse des gewählten Bluetooth Gerätes:

Code:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == ENABLE_BLUETOOTH_REQUEST) {
        if (this.bluetoothAdapter.isEnabled()) {
            this.startDeviceListActivity();
        } else {
            if(!bluetoothDialog) {
                this.showBluetoothEnableDialog();
            }
        }
    } else if(requestCode == CONNECT_BLUETOOTH_REQUEST) {
        if (resultCode == Activity.RESULT_OK) {
            String name = data.getStringExtra(BluetoothFragment.EXTRA_DEVICE_NAME);
            String address = data.getStringExtra(BluetoothFragment.EXTRA_DEVICE_ADDRESS);

            Log.v("MainFragment", name + ": " + address);
        }
    }
}

Nur von hier aus weiß ich leider nicht mehr weiter. Das Gerät mit dem meine
App verbunden werden soll ist ausgewählt, nur weiß ich leider nicht wie ich
jetzt von meiner App aus eine Verbindung zu dem gewählten Gerät erzeuge.

Außerdem möchte ich das Gerät dann auch irgendwie speichern können und
eventuell automatisch verbinden, immer dann, wenn das Gerät wieder in
Reichweite ist.

Ich muss an das Gerät dann Nachrichten schicken, immer zwei Strings im
Abstand von 500ms.

Wie kann ich diese Dinge erreichen?
 
Hallo,
habe mal etwas ähnliches mit einem Arduino gemacht. Mir hat die Doku damals sehr geholfen.
Bluetooth | Android Developers
Gerade der Punkt Managing a Connection sollte dir weiterhelfen.

Habe meinen Code leider gerade nicht zur Verfügung, reiche ihn aber nach, wenn dir das Tutorial nicht hilft.
 
Ich habs mit dem BluetoothService versucht:

Code:
public class BluetoothService extends Thread {
	private static final String TAG = BluetoothService.class.getSimpleName();
	private static final String NAME_SECURE = TAG + "Secure";
    private static final String NAME_INSECURE = TAG + "Insecure";
    private static final UUID MY_UUID_SECURE = UUID.fromString("a6fb84f6-20b3-477f-9160-bcd028bddc99");
    private static final UUID MY_UUID_INSECURE = UUID.fromString("7dd8441a-1d4b-42f1-9996-a7d507548dfc");
    public static final int STATE_NONE = 0;  
    public static final int STATE_LISTEN = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;
    private BluetoothAdapter bluetoothAdapter = null;
    private Handler handler = null;
    private AcceptThread secureAcceptThread = null;
    private AcceptThread insecureAcceptThread = null;
    private ConnectThread connectThread = null;
    private ConnectedThread connectedThread = null;
    private int bluetoothState = STATE_NONE;

    public BluetoothService(Handler handler) {
        this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        this.bluetoothState = STATE_NONE;
        this.handler = handler;
    }
    
    public synchronized void startConnection() {
        Log.d(TAG, "start");

        if (this.connectThread != null) {
        	this.connectThread.cancel();
        	this.connectThread = null;
        }

        if (this.connectedThread != null) {
        	this.connectedThread.cancel();
        	this.connectedThread = null;
        }

        this.setBluetoothState(STATE_LISTEN);

        if (this.secureAcceptThread == null) {
        	this.secureAcceptThread = new AcceptThread(true);
        	this.secureAcceptThread.start();
        }
        if (this.insecureAcceptThread == null) {
        	this.insecureAcceptThread = new AcceptThread(false);
        	this.insecureAcceptThread.start();
        }
    }
    
    public synchronized void connect(BluetoothDevice device, boolean secure) {
        if (this.bluetoothState == STATE_CONNECTING) {
            if (this.connectThread != null) {
            	this.connectThread.cancel();
            	this.connectThread = null;
            }
        }

        if (this.connectedThread != null) {
        	this.connectedThread.cancel();
        	this.connectedThread = null;
        }

       	this.connectThread = new ConnectThread(device, secure);
       	this.connectThread.start();
            
       	this.setBluetoothState(STATE_CONNECTING);
    }

    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) {
        if (this.connectThread != null) {
        	this.connectThread.cancel();
        	this.connectThread = null;
        }

        if (this.connectedThread != null) {
        	this.connectedThread.cancel();
        	this.connectedThread = null;
        }

        if (this.secureAcceptThread != null) {
        	this.secureAcceptThread.cancel();
        	this.secureAcceptThread = null;
        }
        
        if (this.insecureAcceptThread != null) {
            this.insecureAcceptThread.cancel();
            this.insecureAcceptThread = null;
        }

        this.connectedThread = new ConnectedThread(socket, socketType);
        this.connectedThread.start();

        Message msg = this.handler.obtainMessage(Globals.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        
        bundle.putString(Globals.DEVICE_NAME, device.getName());
        msg.setData(bundle);

        this.handler.sendMessage(msg);
        this.setBluetoothState(STATE_CONNECTED);
    }

    public synchronized void stopConnection() {
        if (this.connectThread != null) {
        	this.connectThread.cancel();
        	this.connectThread = null;
        }

        if (this.connectedThread != null) {
        	this.connectedThread.cancel();
        	this.connectedThread = null;
        }
        
        if (this.secureAcceptThread != null) {
        	this.secureAcceptThread.cancel();
        	this.secureAcceptThread = null;
        }
        
        if (this.insecureAcceptThread != null) {
            this.insecureAcceptThread.cancel();
            this.insecureAcceptThread = null;
        }
        
        this.setBluetoothState(STATE_NONE);
    }

    public void write(byte[] out) {
        ConnectedThread connectedThread = null;

        synchronized (this) {
            if (this.bluetoothState != STATE_CONNECTED) {
            	return;
            }
            
            connectedThread = this.connectedThread;
        }

        connectedThread.write(out);
    }
    
    private void connectionFailed() {
        Message msg = this.handler.obtainMessage(Globals.MESSAGE_TOAST);
        
        Bundle bundle = new Bundle();
        bundle.putString(Globals.TOAST, "Unable to connect device");
        
        msg.setData(bundle);
        
        this.handler.sendMessage(msg);

        BluetoothService.this.start();
    }

    private void connectionLost() {
        Message msg = this.handler.obtainMessage(Globals.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        
        bundle.putString(Globals.TOAST, "Device connection was lost");
        msg.setData(bundle);
        
        this.handler.sendMessage(msg);

        BluetoothService.this.start();
    }

    public synchronized int getBluetoothState() {
        return this.bluetoothState;
    }

    private synchronized void setBluetoothState(int bluetoothState) {
    	this.bluetoothState = bluetoothState;
    }
    
    private class AcceptThread extends Thread {
        private BluetoothServerSocket serverSocket = null;
        private String socketType = null;

        public AcceptThread(boolean secure) {
            BluetoothServerSocket tempServerSocket = null;
            
            this.socketType = secure ? "Secure" : "Insecure";

            try {
                if (secure) {
                    tempServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE);
                } else {
                    tempServerSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + socketType + "listen() failed", e);
            }
            
            this.serverSocket = tempServerSocket;
        }

        public void run() {
            this.setName("AcceptThread" + socketType);

            BluetoothSocket socket = null;

            while (bluetoothState != STATE_CONNECTED) {
                try {
                    socket = this.serverSocket.accept();
                } catch (IOException e) {
                    break;
                }

				if (socket != null) {
					synchronized (BluetoothService.this) {
						switch (bluetoothState) {
						case STATE_LISTEN:
						case STATE_CONNECTING:
							connected(socket, socket.getRemoteDevice(), socketType);
							break;
						case STATE_NONE:
						case STATE_CONNECTED:
							try {
								socket.close();
							} catch (IOException e) {
								Log.e(TAG, "Could not close unwanted socket", e);
							}
							break;
						}
					}
				}
            }
        }

        public void cancel() {
            try {
                this.serverSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Socket Type" + socketType + "close() of server failed", e);
            }
        }
    }

    private class ConnectThread extends Thread {
        private BluetoothSocket bluetoothSocket = null;
        private BluetoothDevice bluetoothDevice = null;
        private String socketType = null;

        public ConnectThread(BluetoothDevice bluetoothDevice, boolean secure) {
            this.bluetoothDevice = bluetoothDevice;
            this.socketType = secure ? "Secure" : "Insecure";
            
            BluetoothSocket tempBluetoothSocket = null;

            try {
                if (secure) {
                	tempBluetoothSocket = this.bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
                } else {
                	tempBluetoothSocket = this.bluetoothDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + this.socketType + "create() failed", e);
            }
            
            this.bluetoothSocket = tempBluetoothSocket;
        }

        public void run() {
            Log.i(TAG, "BEGIN mConnectThread");
            
            this.setName("ConnectThread");

            bluetoothAdapter.cancelDiscovery();

            try {
            	this.bluetoothSocket.connect();
            } catch (IOException e) {
                Log.e(TAG, e.getMessage(), e);
                
                connectionFailed();
                
                try {
                	this.bluetoothSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() socket during connection failure", e2);
                }
                
                return;
            }

            synchronized (BluetoothService.this) {
                connectThread = null;
            }

            connected(this.bluetoothSocket, this.bluetoothDevice, this.socketType);
        }

        public void cancel() {
            try {
            	this.bluetoothSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

    private class ConnectedThread extends Thread {
        private BluetoothSocket bluetoothSocket = null;
        private InputStream inputStream = null;
        private OutputStream outputStream = null;

        public ConnectedThread(BluetoothSocket bluetoothSocket, String socketType) {
            Log.d(TAG, "create ConnectedThread");
            
            this.bluetoothSocket = bluetoothSocket;
            
            InputStream tempInputStream = null;
            OutputStream tempOutputStream = null;

            try {
                tempInputStream = this.bluetoothSocket.getInputStream();
                tempOutputStream = this.bluetoothSocket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            this.inputStream = tempInputStream;
            this.outputStream = tempOutputStream;
        }

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

            while (true) {
                try {
                    bytes = this.inputStream.read(buffer);

                    handler.obtainMessage(Globals.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    
                    connectionLost();
                    
                    BluetoothService.this.start();
                    
                    break;
                }
            }
        }

        public void write(byte[] buffer) {
            try {
                this.outputStream.write(buffer);

                handler.obtainMessage(Globals.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {
            try {
                this.bluetoothSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }
}

Aber da bekomme ich dann beim connecten:

Code:
/**
	 * 
	 * @param data
	 * @param secure
	 */
    private void connectDevice(Intent data, boolean secure) {
        String address = data.getExtras().getString(BluetoothFragment.EXTRA_DEVICE_ADDRESS);
        
        BluetoothDevice device = this.bluetoothAdapter.getRemoteDevice(address);

       	this.bluetoothService.connect(device, secure);
    }

Diesen Fehler:

Code:
02-07 12:47:15.633: E/BluetoothService(17671): read failed, socket might closed or timeout, read ret: -1
02-07 12:47:15.633: E/BluetoothService(17671): java.io.IOException: read failed, socket might closed or timeout, read ret: -1
02-07 12:47:15.633: E/BluetoothService(17671): 	at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:512)
 
Ich möchte mit meiner App ja nur Ausgehende Verbindungen erzeugen.
Also ich suche ein Gerät und verbinde mich mit diesem.

Welche Rolle spielt dabei die UUID und warum crasht es jedesmal, wenn
ich mich mit einen Gerät verbinden möchte. Es gibt ja nicht mal eine richtige
Fehlermeldung, nur das der socket entweder closed oder timed out ist, beides
kann aber nicht der Fall sein.

Das war das offizielle Android Beispiel und es funktioniert nicht, sowas
frustriert!
 
Ich hab mal die App "Bluetooth Viewer Lite" runtergeladen und auf meine
Geräten installiert. Ich habe ein Nexus 7 und ein Nexus 4, diese versuche
ich zu verbinden. Beide haben die neueste Android Version und beide können
nicht per Bluetooth miteinander verbunden werden.

Ist es also vielleicht gar kein Code Problem sondern ein Nexus oder Android
Problem?
 

Ähnliche Themen

S
Antworten
4
Aufrufe
4.462
mblaster4711
mblaster4711
L
Antworten
15
Aufrufe
909
jogimuc
J
M
Antworten
3
Aufrufe
167
moin
M
Zurück
Oben Unten