意図的に複数のデバイスに接続する方法について多くの質問を見てきました。しかし、私の状況では、1 つのハードウェア デバイスにのみ接続しようとしています。
同じことをするはずの 2 つのハードウェア デバイスがあります。BLE 経由でアプリに接続すると、単色に変わる LED が表示されます。これは、デバイスが 1 つしかオンになっていない場合でも、すべて正常に動作します。ただし、2 つのデバイスの電源を入れてから、1 つだけに接続しようとすると. 両方のデバイスの LED が点灯します。接続するつもりがなかったものから着信データを取得していないようですが。
端末のせいではないと思います。iOSではこの問題が発生していないためです。電話は、以前に接続したデバイスをどこかに記憶している可能性があると思いますか?
すみません、これはたくさんのコードです。でも、このクラス全体を持つことが重要だと感じています。どんな助けでも大歓迎です。
package com.roberts.croberts.orange;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.bluetooth.le.BluetoothLeScanner;
import java.util.ArrayList;
import java.util.List;
@TargetApi(21)
public class BluetoothRegulator {
private static BluetoothRegulator instance = null;
private Context context;
private BluetoothLeScanner mLEScanner;
private BluetoothDevice orangeDevice;
//scanner stuff
private Handler mHandler;
// Stops scanning after 3 seconds.
private static final long SCAN_PERIOD = 3000;
//connected stuff
private android.bluetooth.BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
public ArrayList<BluetoothDevice> devices = new ArrayList<>();
private Handler foundHandler = new Handler();
private Handler servicesHandler = new Handler();
private ScanCallback mScanCallback;
public static BluetoothRegulator sharedInstance(){
if(instance == null) {
instance = new BluetoothRegulator();
Log.i("chase", "created new instance");
}
return instance;
}
// 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) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mBluetoothGatt.discoverServices();
Log.i(TAG, "BR: onconnectionsStateChanged Connected to GATT server.");
// Attempts to discover services after successful connection.
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// Loops through available GATT Serviceokay so ees.
for (BluetoothGattService gattService : mBluetoothGatt.getServices()) {
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
mBluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);
Log.i(TAG, mBluetoothGatt == null ? "mbluetooth is null" : "should be subscribed");
}
}
Log.i("chase", "did connect and discover devices");
} else {
Log.w(TAG, "Not Success onServicesDiscovered received: " + status);
connect(orangeDevice);
}
}
private Object getFieldFromObject(Object obj, String name){
try {
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
}catch(Exception e){
Log.i("chase", "e: "+e);
return null;
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.i("BR: chase", "received data!");
}
};
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
public boolean initialize(android.bluetooth.BluetoothManager btmanager, Context ctx) {
mBluetoothManager = btmanager;
context = ctx;
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
if (Build.VERSION.SDK_INT >= 21) {
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
setUpCallBack();
}
return true;
}
public void scan() { //we call scan when they hit the connect button...
// Stops scanning after a pre-defined scan period.
Log.i("chase", "start scanning");
devices = new ArrayList<>();
if (mHandler == null) mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(mScanCallback);
}
}
private void foundDevice(BluetoothDevice device){
final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 5 && (deviceName.substring(0, 6).equals("orange") || deviceName.substring(0, 6).equals("smartb"))) {
for (BluetoothDevice d : devices){
if (d.getAddress().equals(device.getAddress())){
return;
}
}
mHandler.removeCallbacksAndMessages(null);
devices.add(device);
if (devices.size() == 1) { //wait one second and then assume there aren't any more devices named "orange"
foundHandler.postDelayed(new Runnable() {
public void run() {
doneSearching();
}
}, 1000);
}
}
}
private void doneSearching(){
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
if (devices.size() == 1){
BluetoothDevice device = devices.get(0);
connect(device);
}else{
//normally this displays a list and the user can choose which device. But this works just as well for now.
BluetoothDevice device = devices.get(0);
connect(device);
}
}
//connect method
public boolean connect(BluetoothDevice btdevice) {
orangeDevice = btdevice;
if (mBluetoothAdapter == null || btdevice == null || btdevice.getAddress() == null) {
return false;
}
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
devices = new ArrayList<>();
mBluetoothGatt = orangeDevice.connectGatt(context, true, mGattCallback);
return true;
}
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) return;
mBluetoothGatt.disconnect();
mBluetoothGatt = null;
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
foundDevice(device);
}
};
public void setUpCallBack(){
mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice device = result.getDevice();
foundDevice(device);
}
@Override
public void onScanFailed(int errorCode) {
Log.e("Chase", "Scan Failed Error Code: " + errorCode);
}
};
}
}
アップデート
Galaxy タブレットで遊んでいましたが、問題を再現できませんでした。だから私はそれがデバイスに依存していると思います。この問題は Galaxy S3 で発生します。他のデバイスをまとめてテストしようとしています。
また、私はいくつかの新しいデバイスを手に入れることができました。そのデバイスが以前に電話に接続されたことがない場合 (処女デバイス)、そのデバイスは混同されず、接続されていないときに接続されていると見なされるようです。そのため、検索すると表示されますが、実際に接続するまで、私が接続しているとは決して考えません。その後、私が話していないのに話しかけようとしていると半分の確率で考えます。それが理にかなっていることを願っています。これは、電話が何らかの形で古いデバイスをキャッシュしているという理論を裏付けています. アプリをアンインストールして再インストールして、未使用のデバイスを使用した場合と同じ効果があるかどうかを確認してみましたが、アプリは関係ないようです。アプリの新規インストールを行った場合でも、デバイスが電話に導入された後も、デバイスは接続されます (想定されていない場合)。