Automatische Verbindung zu einem Gerät BLE
Ich arbeite auf eine Anwendung, um coommunicate gegen eine BLE-Gerät, derzeit bin ich versucht
erstellen eines Dienstes, der beginnt mit der Anwendung und die automatische Verbindung zu TI CC2541
Schlüsselanhänger.
Problem ist, das gatt-server scheinen zu scheitern JEDES MAL....
Ich habe keine Ahnung, was falsch mit meinem code, da durch die google API ' s und einige tutorials, die ich sah
Es scheint, dass alle Teile an Ihrem Platz, aber trotzdem funktioniert nichts... =(
Hier ist mein service -
package com.example.bluetoothgatt;
import java.util.UUID;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
public class BLE extends Service implements BluetoothAdapter.LeScanCallback {
private final IBinder mBinder = new BluetoothLeBinder();
private final static String TAG = "BLE";
private static final String DEVICE_NAME = "Keyfobdemo";
private BluetoothManager mBluetoothManager;
public BluetoothGatt mConnectedGatt;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mDevice;
private String mDeviceAddress;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
/*******************************
*******************************
****** Service Inherited ****** Methods **********
*******************************/
@Override
public void onCreate() {
super.onCreate();
mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
Thread discoverDevices = new Thread(mStartRunnable);
discoverDevices.setPriority(discoverDevices.MAX_PRIORITY);
discoverDevices.start();
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
//Implements callback methods for GATT events that the app cares about.
//For example, connection change and services discovered.
private final BluetoothGattExecutor mExecutor = new BluetoothGattExecutor() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
mConnectedGatt = gatt;
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
}
};
/**
* Return a reference for the current class
*/
public class BluetoothLeBinder extends Binder {
BLE getService() {
return BLE.this;
}
}
private Runnable mStartRunnable = new Runnable() {
@Override
public void run() {
startScan();
}
};
private void startScan() {
if (mConnectionState == STATE_DISCONNECTED) {
mBluetoothAdapter.startLeScan(this);
mHandler.postDelayed(mStopRunnable, 2500);
}
}
private Runnable mStopRunnable = new Runnable() {
@Override
public void run() {
stopScan();
}
};
private void stopScan() {
mBluetoothAdapter.stopLeScan(this);
}
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
/*
* We are looking for SensorTag devices only, so validate the name that
* each device reports before adding it to our collection
*/
if (DEVICE_NAME.equals(device.getName())) {
mDevice = device;
mDeviceAddress = mDevice.getAddress();
connect(mDeviceAddress);
mConnectionState = STATE_CONNECTING;
if(device.getBondState() == BluetoothDevice.BOND_BONDED) {
} else if (device.getBondState() == BluetoothDevice.BOND_BONDING) {
} else if(device.getBondState() == BluetoothDevice.BOND_NONE) {
connect(device.getAddress());
}
}
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address
* The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The
* connection result is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG,
"BluetoothAdapter not initialized or unspecified address.");
return false;
}
//Previously connected device. Try to reconnect.
if (mDeviceAddress != null && address.equals(mDeviceAddress)
&& mConnectedGatt != null) {
Log.d(TAG,
"Trying to use an existing BluetoothGatt for connection.");
if (mConnectedGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter
.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
//We want to directly connect to the device, so we are setting the
//autoConnect
//parameter to false.
mConnectedGatt = device.connectGatt(this, false, mExecutor);
Log.d(TAG, "Trying to create a new connection.");
mDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The
* disconnection result is reported asynchronously through the
* BluetoothGattCallback >>
* onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mConnectedGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mConnectedGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure
* resources are released properly.
*/
public void close() {
if (mConnectedGatt == null) {
return;
}
mConnectedGatt.close();
mConnectedGatt = null;
}
private final UUID IMMEDIATE_ALERT_UUID = UUID
.fromString("00001802-0000-1000-8000-00805f9b34fb");
private final UUID ALERT_LEVEL_UUID = UUID
.fromString("00002a06-0000-1000-8000-00805f9b34fb");
public void Buzz(BluetoothGatt gatt, int level) {
BluetoothGattService alertService = gatt
.getService(IMMEDIATE_ALERT_UUID);
if (alertService == null) {
Log.d(TAG, "Immediate Alert service not found!");
return;
}
BluetoothGattCharacteristic alertLevel = alertService
.getCharacteristic(ALERT_LEVEL_UUID);
if (alertLevel == null) {
Log.d(TAG, "Alert Level charateristic not found!");
return;
}
alertLevel.setValue(level, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
gatt.writeCharacteristic(alertLevel);
Log.d(TAG, "Alert");
}
private final UUID BATTERY_SERVICE_UUID = UUID
.fromString("0000180F-0000-1000-8000-00805f9b34fb");
private final UUID BATTERY_LEVEL_UUID = UUID
.fromString("00002a19-0000-1000-8000-00805f9b34fb");
public int getbattery(BluetoothGatt mBluetoothGatt) {
BluetoothGattService batteryService = mConnectedGatt
.getService(BATTERY_SERVICE_UUID);
if (batteryService == null) {
Log.d(TAG, "Battery service not found!");
return 0;
}
BluetoothGattCharacteristic batteryLevel = batteryService
.getCharacteristic(BATTERY_LEVEL_UUID);
if (batteryLevel == null) {
Log.d(TAG, "Battery level not found!");
return 0;
}
mBluetoothGatt.readCharacteristic(batteryLevel);
return batteryLevel.getIntValue(
BluetoothGattCharacteristic.FORMAT_SINT8, 0);
}
/*
* We have a Handler to process event results on the main thread
*/
private static final int MSG_PROGRESS = 201;
private static final int MSG_DISMISS = 202;
private static final int MSG_CLEAR = 301;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
BluetoothGattCharacteristic characteristic;
switch (msg.what) {
case MSG_PROGRESS:
break;
case MSG_DISMISS:
break;
case MSG_CLEAR:
break;
}
}
};
public void MakeBuzz() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
mConnectedGatt = mDevice.connectGatt(getApplicationContext(),
true, mExecutor);
BluetoothGattService alertService = mConnectedGatt
.getService(IMMEDIATE_ALERT_UUID);
int x = getbattery(mConnectedGatt);
Buzz(mConnectedGatt, 2);
}
});
t.start();
}
}
Das man die Application-Klasse -
package com.example.bluetoothgatt;
import android.app.Application;
import android.content.Intent;
public class ApplicationBleTest extends Application {
//Application variables
public final String SMOKE_TALK_PACKAGE_NAME = "com.smoketalk";
private BluetoothLEService mBleService;
private static int MODE_PRIVATE;
/**
* Application OnCreate event initiate the class parameters
*/
public void onCreate() {
super.onCreate();
getApplicationContext().startService(new Intent(this, BLE.class));
}
}
- Und das ist die Haupt-Aktivität (ich bin versuchen, um den keyfob alaram buzz auf eine Schaltfläche klicken)
package com.example.bluetoothgatt;
import com.example.bluetoothgatt.BluetoothLowEnergyService.BluetoothLeBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* Created by Dave Smith Double Encore, Inc. MainActivity
*/
public class MainActivity extends Activity {
BluetoothLowEnergyService mBluetoothService;
boolean isBound = false;
Button buzz;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, BluetoothLowEnergyService.class);
bindService(intent, mBleServiceConnection, Context.BIND_AUTO_CREATE);
buzz = (Button) findViewById(R.id.btn1);
buzz.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mBluetoothService.MakeBuzz();
}
});
}
private ServiceConnection mBleServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
BluetoothLeBinder binder = (BluetoothLeBinder) service;
mBluetoothService = binder.getService();
isBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
}
Und die menifest Datei -
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluetoothgatt"
android:versionCode="1"
android:versionName="1.0" >
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<uses-sdk
android:minSdkVersion="18"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/>
<application
android:name="com.example.bluetoothgatt.ApplicationBleTest"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="SensorTag Weather" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.bluetoothgatt.BLE" />
</application>
</manifest>
und das Letzte layout für die Haupt-Aktivität -
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="@dimen/activity_horizontal_margin"
android:text="Android BLE Test"
android:textSize="42sp" />
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="56dp"
android:text="Buzz" />
</RelativeLayout>
JEDE Hilfe wird geschätzt, da ich rellay habe keine Ahnung, was schief geht... =(
Im mit ein galaxy S4 mit android 4.3 Meine Absicht ist, den Dienst zu starten, sobald Sie die Anwendung starten und eine Verbindung mit dem ersten BLE-Gerät entdeckt (vorausgesetzt, der Benutzer ist in einer "sauberen" Umgebung) können Sie mir bitte sagen, was das sein soll rechts fließen (pseudo-code?) da nach meinem Verständnis brauche ich, um zu starten entdecken und auf ein entdecken (also ich habe das Gerät UUID) kann ich eine Verbindung zu dem Gerät - sollte ich auch eine Verbindung zum GATT-server? kann ich die Dienste direkt nachdem ich mit dem Gerät verbunden?
schauen Sie mal hier stackoverflow.com/q/21398766/2624806 ...auch autoConnect = true in ConnectedGatt = Gerät.connectGatt(this, false, mExecutor). Denken Sie daran autoConnect arbeiten bis in Paketen broadcast(d.h. Gerät ist noch Rundfunk), sobald es in der Nähe (also broadcast-Gerät aus)...die automatische Verbindung wird nicht funktionieren.
für die ur-Referenz tinyurl.com/lholf6q
Hi hast du die Lösung
InformationsquelleAutor crazyPixel | 2014-02-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Für den Anfang würde ich empfehlen auskommentieren der Anleihe-code (Alles nach if(device.getBondState().. in der onLeScan-Methode) Die gesamte bonding-Prozess war instabil auf 4.3 (Nexus-Geräte zumindest) und wurde mehr stabil auf 4.4.
Sie sollten in der Lage sein, um Geräte zu finden, und mit der BluetoothDevice der Benutzer auswählt, sollten Sie rufen ConnectGatt nach Beendigung der Entdeckung. Diese versuchen, eine Verbindung zu den Gatt-server auf dem Gerät. Wenn die Verbindung erfolgreich ist, erhalten Sie einen Rückruf auf Ihre connectionStateChange angibt, dass die Verbindung erfolgreich war.
Das Konzept hinter der Verklebung wird bezogen auf den Verbindungsaufbau mit dem Gerät und den Austausch von Tasten, wenn Ihre Merkmale verschlüsselt sind. Normalerweise sollten Sie in der Lage sein, eine Verbindung zu den Gatt-server, ohne Bindung, aber sobald Sie verbunden sind, wenn Sie versuchen zu Lesen, eine verschlüsselte Merkmal, es wird scheitern.
InformationsquelleAutor Zomb
Ich versuchte Ihren code, und es funktioniert. Sie benötigen, um diesen Prozess zu Folgen:
BluetoothAdapter.startLeScan(leCallback)
In der onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) in leCallback, rufen Sie btDevice.connectGatt(Context context, Boolean Auto, BluetoothGattCallback gattCallback);
In der onConnectionStateChange(BluetoothGatt gatt, int status, int newState) in gattCallBack, überprüfen Sie, ob newState ist BluetoothProfile.STATE_CONNECTED, wenn ja, nennen gatt.discoverServices();
In der onServicesDiscovered(BluetoothGatt gatt, int status) in gattCallBack, überprüfen Sie, ob der status ist BluetoothGatt.GATT_SUCCESS, wenn ja, den Dienst mittels UUID wie hier: BluetoothGattService service = gatt.getService(YOUR_SERVICE_UUID);
Wenn der service null ist, bedeutet es, dass der Dienst noch nicht entdeckt worden ist, müssen Sie erneut zu prüfen, Wann der nächste service ist entdeckt, und die onServicesDiscovered wird erneut aufgerufen werden.
Durch die Zeit, die alle Dienstleistungen, die entdeckt worden ist, sollten Sie schon Ihren Dienst, es sei denn, das Gerät Sie nicht unterstützt.
Jetzt können Sie Ihren service in Ihre Buzz-Methode.
Punkt 5 ist nicht wahr.
onServicesDiscovered
wird aufgerufen mit des Liste der Dienste, die Merkmale und Deskriptoren, die Ihr Gerät unterstützt. Quelle: developer.android.com/reference/android/bluetooth/..., int).Auch Hugo Vysser recomends schließen der Verbindung, wenn die Leistungen nicht abgerufen werden können, Sie können sehen, seine ausgezeichneten Vortrag über das Thema hier (link verweist auf den amtierenden Wörter und code) youtu.werden/1C1bKrzVHTM?t=12m54s
InformationsquelleAutor user1527786
Erwähnenswert ist auch, dass die BLE Aktionen alle müssen serialisiert werden, indem Sie. ZB, wenn Sie einen lese - /Schreibzugriff auf eine Eigenschaft, die Sie brauchen, zu warten, für den Rückruf, bevor Sie tun eine andere. Wenn nicht, wird dies zu einem Fehler führen.
InformationsquelleAutor AllDayAmazing
Da Sie von einem service, den Sie können versuchen, eine Verbindung auf der main-thread wie diesem:
Hoffe, es hilft.
InformationsquelleAutor TacoEater