Эй, я работаю над приложением, в котором я использую BLE для передачи идентификатора пользователя с мобильного телефона на мобильное, используя мое приложение, когда они взаимодействуют друг с другом, что означает, что в одном мобильном устройстве мое приложение будет работать как периферийный режим, а в другом - будет работать как центральный режим. Итак, я открыл свое первое приложение как Периферийный режим, который запускает рекламу, а также как Центральный, который запускает службу в фоновом режиме для сканирования устройства и устанавливает соединение для чтения данных. Эта функция работает нормально. Я отправляю сообщение (идентификатор пользователя) с периферийного устройства на центральное устройство, которое появляется на центральном устройстве. Теперь я хочу отправить идентификатор пользователя устройства центрального режима на периферию.
Насколько я понимаю, в BLE мы не можем отправлять данные с центрального на периферийное устройство, мы можем только сканировать с центрального. Но я слышал, что мы можем написать характеристики от Периферийного устройства, чтобы получить некоторый ответ в ответ. Так возможно ли, что я могу отправить свой Использованный идентификатор с центрального на Периферийный через ответ, или возможен любой другой альтернативный способ? Я хочу сделать это
Я просто новичок в BLE, поэтому я не знаю, как выполнить эту функцию. Я делюсь своим кодом, что я делаю ниже:
SO Central Mode, или вы говорите, что сканирование, которое я запускаю в фоновом режиме:
Служба GATT
public class GattService extends Service {
private static int NOTIFICATION_ID = 0;
public static final ParcelUuid UUID = ParcelUuid.fromString("0000FED8-0000-1000-8000-00805F9B34FB");
public static final java.util.UUID SERVICE_UUID = java.util.UUID.fromString("00001111-0000-1000-8000-00805F9B34FB");
public static final java.util.UUID CHAR_UUID = java.util.UUID.fromString("00002222-0000-1000-8000-00805F9B34FB");
private BluetoothAdapter bluetoothAdapter;
private BluetoothGattServer server;
private BluetoothLeAdvertiser bluetoothLeAdvertiser;
private boolean start;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
setupBluetooth();
return Service.START_STICKY;
}
private void setupBluetooth() {
BluetoothManager bluetoothManager = (BluetoothManager) this.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE);
server = bluetoothManager.openGattServer(this, serverCallback);
initServer();
bluetoothAdapter = bluetoothManager.getAdapter();
advertise();
}
private void initServer() {
BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(CHAR_UUID, BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
service.addCharacteristic(characteristic);
server.addService(service);
}
private void advertise() {
bluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
AdvertiseData advertisementData = getAdvertisementData();
AdvertiseSettings advertiseSettings = getAdvertiseSettings();
bluetoothLeAdvertiser.startAdvertising(advertiseSettings, advertisementData, advertiseCallback);
start = true;
}
private AdvertiseData getAdvertisementData() {
AdvertiseData.Builder builder = new AdvertiseData.Builder();
builder.setIncludeTxPowerLevel(true);
builder.addServiceUuid(UUID);
bluetoothAdapter.setName("BLE client");
builder.setIncludeDeviceName(true);
return builder.build();
}
private AdvertiseSettings getAdvertiseSettings() {
AdvertiseSettings.Builder builder = new AdvertiseSettings.Builder();
builder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);
builder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
builder.setConnectable(true);
return builder.build();
}
private final AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
@SuppressLint("Override")
@Override
public void onStartSuccess(AdvertiseSettings advertiseSettings) {
final String message = "Advertisement successful";
sendNotification(message);
}
@SuppressLint("Override")
@Override
public void onStartFailure(int i) {
final String message = "Advertisement failed error code: " + i;
sendNotification(message);
}
};
private BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
sendNotification("Client connected");
}
}
@Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
server.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, 0, null);
}
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
byte[] bytes = value;
String message = new String(bytes);
sendNotification(message);
if (characteristic.getUuid().equals(CHAR_UUID)) {
server.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
}
int length = value.length;
byte[] reversed = new byte[length];
for (int i = 0; i < length; i++) {
reversed[i] = value[length - (i + 1)];
}
characteristic.setValue(reversed);
server.notifyCharacteristicChanged(device, characteristic, true);
}
@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
}
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
}
@Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
super.onExecuteWrite(device, requestId, execute);
}
@Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
}
@Override
public void onMtuChanged(BluetoothDevice device, int mtu) {
super.onMtuChanged(device, mtu);
}
};
@Override
public void onDestroy() {
if (start) {
bluetoothLeAdvertiser.stopAdvertising(advertiseCallback);
}
super.onDestroy();
}
private void sendNotification(String message) {
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 1;
String channelId = "channel-01";
String channelName = "Channel Name";
int importance = NotificationManager.IMPORTANCE_HIGH;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText(message)
.setAutoCancel(true);
Intent intent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(notificationId, mBuilder.build());
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
И мое периферийное устройство, которое отправляет Characteristi c после успешного подключения:
public class ServicesList extends AppCompatActivity implements AdapterView.OnItemClickListener {
private ListView servicesList;
private LinearLayout messageContainer;
private BluetoothDevice device;
private List<String> servicesListNames;
private ArrayAdapter<String> servicesAdapter;
private Handler handler;
private List<BluetoothGattService> services;
private BluetoothGatt currentGatt;
private EditText message;
private Button send;
private BluetoothGattCharacteristic characteristic;
private ProgressDialog dialog;
public static final java.util.UUID DES_UUID = java.util.UUID.fromString("00003333-0000-1000-8000-00805F9B34FB");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.services_list);
handler = new Handler();
dialog = new ProgressDialog(this);
dialog.setCancelable(false);
dialog.setMessage("Loading");
device = getIntent().getExtras().getParcelable("device");
servicesList = (ListView) findViewById(R.id.services_list);
messageContainer = (LinearLayout) findViewById(R.id.message_container);
message = (EditText) findViewById(R.id.message);
send = (Button) findViewById(R.id.send);
currentGatt = device.connectGatt(this, false, gattCallback);
dialog.show();
servicesListNames = new ArrayList<>();
servicesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, servicesListNames);
servicesList.setAdapter(servicesAdapter);
servicesList.setOnItemClickListener(this);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!message.getText().toString().trim().isEmpty()) {
characteristic.setValue(message.getText().toString().getBytes());
currentGatt.writeCharacteristic(characteristic);
message.setText("");
}
}
});
}
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if(newState == BluetoothProfile.STATE_CONNECTED) {
currentGatt.discoverServices();
}else{
if(dialog.isShowing()){
handler.post(new Runnable() {
@Override
public void run() {
dialog.hide();
}
});
}
}
}
@Override
public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
services = currentGatt.getServices();
for(BluetoothGattService service : services){
Log.d("Khurram", "Uuid = " + service.getUuid().toString());
servicesListNames.add(Helper.getServiceName(service.getUuid().toString()));
handler.post(new Runnable() {
@Override
public void run() {
servicesAdapter.notifyDataSetChanged();
}
});
}
if (dialog.isShowing()){
handler.post(new Runnable() {
@Override
public void run() {
dialog.hide();
}
});
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
// log("Characteristic read successfully");
readCharacteristic(characteristic);
} else {
// logError("Characteristic read unsuccessful, status: " + status);
// Trying to read from the Time Characteristic? It doesnt have the property or
permissions
// set to allow this. Normally this would be an error and you would want to:
// disconnectGattServer();
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
gatt.executeReliableWrite();
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic
characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
readCharacteristic(characteristic);
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
{
super.onDescriptorRead(gatt, descriptor, status);
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
{
super.onDescriptorWrite(gatt, descriptor, status);
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
}
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
}
};
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(services != null){
BluetoothGattService notificationService = services.get(position);
if(notificationService.getUuid().equals(GattService.SERVICE_UUID)){
characteristic = notificationService.getCharacteristic(GattService.CHAR_UUID);
if(characteristic != null) {
messageContainer.setVisibility(View.VISIBLE);
}
}else{
Toast.makeText(this, "Testing", Toast.LENGTH_SHORT).show();
}
}
}
private void readCharacteristic(BluetoothGattCharacteristic characteristic) {
byte[] messageBytes = characteristic.getValue();
log("Read: " + StringUtils.byteArrayInHexFormat(messageBytes));
String message = StringUtils.stringFromBytes(messageBytes);
if (message == null) {
logError("Unable to convert bytes to string");
Toast.makeText(this, "Unable to convert bytes to string", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
Так что я делаю, у меня есть EditText на периферии, в котором я ввожу текст, как идентификатор пользователя, и я возвращаю его вернитесь из сервиса в качестве ответа после его изменения и покажите уведомление в центральном режиме.
Но я не могу получить ответ Можете ли вы, ребята, помочь мне, пожалуйста?
Если вы, ребята, знаете мой сценарий, вы может также помочь мне с новым способом через BLE, с помощью которого я могу обмениваться данными между 2 android телефонами.
Спасибо,