我构建了一个Android应用程序,我的移动设备与蓝牙设备连接。我有一个建立连接的服务,以及从我的设备获得的四个值(温度,灯电池和状态)。我的目标是每次收到值时发送值。在onCharacteristicChanged方法中接收值,我想将它们发送到DeviceControlActivity并在文本视图中显示它们。怎么可能实现这一目标?提前谢谢。
BluetoothLeService:
package com.example.drodo.diamondbeacons;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.util.List;
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
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;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
setPuckCharacteristicNotification();
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.i(TAG, "onCharacteristicRead");
//broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//Log.i(TAG, "onCharacteristicChanged");
byte[] dataBytes = characteristic.getValue();
String puckData = null;
try {
puckData = new String(dataBytes, "UTF-8");
puckData = puckData.replaceAll("[\u001Ba-zA-Z>\\[\\]\\s+]","");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unable to convert message bytes to string");
}
assert puckData != null;
final String[] data = puckData.split("-");
Log.e("D@T@-->", "LIGHT: " + data[0] + "%" + " " + "TEMP: " + data[1] + "\u2103" + " " + "BATTERY: " + data[2]
+ " " + "ALERT: " + data[3]);
double light = Double.parseDouble(data[0]);
int temperature = Integer.parseInt(data[1]);
double battery = Double.parseDouble(data[2]);
int myState = Integer.parseInt(data[3]);
//broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
if (battery <= 2.7) {
try {
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Puck.js Device - Replace the Battery")
.setContentText("Battery Level: " + battery + " V")
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),R.drawable.icons8_charged_battery_96))
.setAutoCancel(true)
//.setDefaults(Notification.DEFAULT_ALL)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC); //to show content in lock screen
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, builder.build());
PowerManager.WakeLock screenLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
screenLock.acquire(10000);
//later
screenLock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.i(TAG, "onCharacteristicWrite");
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
Log.i(TAG, "onDescriptorWrite");
BluetoothGattService service = gatt.getService(PuckConstants.PUCK_SERVICE_UUID);
if (service != null) {
BluetoothGattCharacteristic characteristic =
service.getCharacteristic(PuckConstants.PUCK_TX_UUID);
if (characteristic != null) {
Log.i(TAG, "Writing to characteristic " + characteristic.getUuid());
//String msg = "getMy()\n";
//byte[] data = msg.getBytes();
//characteristic.setValue(data);
if (gatt.writeCharacteristic(characteristic)) {
characteristic.getValue();
Log.i(TAG, "writeCharacteristic OK");
} else {
Log.i(TAG, "writeCharacteristic FAIL");
}
}
}
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
public boolean initialize() {
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
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 (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.i(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.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.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.i(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
/**
* Enables notification on a given characteristic.
**/
public void setPuckCharacteristicNotification() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
//Start getting data
BluetoothGattService gattService = mBluetoothGatt.getService(PuckConstants.PUCK_SERVICE_UUID);
if (gattService != null) {
BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(PuckConstants.PUCK_RX_UUID);
if (gattCharacteristic != null) {
Log.i(TAG, "Setting Characteristic " + gattCharacteristic.getUuid());
mBluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);
BluetoothGattDescriptor clientDescriptor = gattCharacteristic.getDescriptor(PuckConstants.CLIENT_CHARACTERISTIC_CONFIG);
clientDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(clientDescriptor);
}
}
}
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null;
return mBluetoothGatt.getServices();
}
}
DeviceControlActivity:
package com.example.drodo.diamondbeacons;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class DeviceControlActivity extends AppCompatActivity {
private final static String TAG = DeviceControlActivity.class.getSimpleName();
public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
private Toolbar bleToolbar;
private TextView mConnectionState;
private TextView mDataField;
private Button mainBtn;
private String mDeviceName;
private String mDeviceAddress;
private BluetoothLeService mBluetoothLeService;
private boolean mConnected = false;
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
mConnectionState.setTextColor(getResources().getColor(R.color.colorAccent));
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
mConnectionState.setTextColor(getResources().getColor(R.color.colorOrange));
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
//displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
private void clearUI() {
mDataField.setText(R.string.no_data);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gatt_services_characteristics);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
// Sets up UI references.
((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
mConnectionState = findViewById(R.id.connection_state);
mDataField = findViewById(R.id.data_value);
mainBtn = findViewById(R.id.main_btn);
bleToolbar = (Toolbar) findViewById(R.id.ble_toolbar);
setSupportActionBar(bleToolbar);
getSupportActionBar().setTitle("Ble Devices");
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
mainBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mainActivity = new Intent(DeviceControlActivity.this, MainActivity.class);
startActivity(mainActivity);
//finish();
}
});
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.gatt_services, menu);
if (mConnected) {
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
} else {
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_connect:
mBluetoothLeService.connect(mDeviceAddress);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(() -> mConnectionState.setText(resourceId));
}
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
}
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
}
答案 0 :(得分:0)
嘿,您可以使用LocalBroadcast()将数据从服务发送到活动。
答案 1 :(得分:0)
使用广播接收器进行服务活动通信。
如果要将数据发送回活动,请在onCharacteristicChanged方法结束时发送广播,如下所示:
Intent intent = new Intent("IntentFilterSendData");
intent.putExtra("tempKey", temperature);
intent.putExtra("lightKey", light);
intent.putExtra("batteryKey", battery);
intent.putExtra("stateKey", myState);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
您可以通过
接收活动中的数据private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Double temperature = intent.getDoubleExtra("tempKey", 20);
Double light = intent.getDoubleExtra("lightKey", 0);
Double battery = intent.getDoubleExtra("batteryKey", 0);
Double state = intent.getDoubleExtra("batteryKey", 0);
//Use the data
}
};
并通过以下方式在onResume中动态注册接收器:
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("IntentFilterSendData"));
并在onPause中取消注册:
LocalBroadcastManager.unregisterReceiver(myBroadcastReceiver);