web-dev-qa-db-ja.com

Bluetooth LEスキャンでデバイスが見つからないことがある

Bluetooth LEデバイスをスキャンして、ペリフェラルとして実行しています(Moto G 2nd GenでAndroid 6.0を実行しています)

私が抱えている問題は、時々(ランダムに見えるが、多くの場合)、他の周辺機器が見つからないこともあれば、正常に動作することです。

類似のコードを実行しているコンパニオンiOSデバイス(周辺機器のスキャンと周辺機器の両方の動作)があります。AndroidスキャンでiOSデバイスが見つからない場合、私のiOSはAndroidデバイスが周辺機器は問題ありません。だからそれは物事のスキャン側の問題だけのようです。

私のコンパニオンiOSデバイスが見つからないだけでなく、Bluetoothデバイスも見つかりません。うまくいくと、私のコンパニオンiOSデバイスだけでなく、他の多くのデバイスも検出されます。

ScanFiltersを使用した場合と使用しない場合を試しましたが、同じ問題が発生します。最小SDK 23でSDK 26に対してビルドしています。

必要に応じて、必要な権限を設定しています。

以下の関連コード:

private void startScanning() {
    mHandler = new Handler(mContext.getMainLooper());

    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            ScanSettings settings = new ScanSettings.Builder()
                                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                                        .setReportDelay(0)
                                        .build();

            mBluetoothLeScanner.startScan(null, settings, mScanCallback);
        }
    }, 1000);
}

private ScanCallback mScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);

        if( result == null || result.getDevice() == null )
            return;

        Log.e("myTest", "Found Device");

        BluetoothDevice device = result.getDevice();
        final String deviceAddress = device.getAddress();

        List<ParcelUuid> parcel = result.getScanRecord().getServiceUuids();

        if (parcel != null) {
            String parcelUUID = parcel.toString().substring(1,37);

            if (parcelUUID.equalsIgnoreCase(mContext.getString(R.string.service_uuid))) {
                final BluetoothDevice bleDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(deviceAddress);

                if (!seenPeripherals.contains(deviceAddress)) {
                    stopScanning();

                    mHandler = new Handler(mContext.getMainLooper());

                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Log.e("AppToApp", "Trying to connect to device " + deviceAddress);

                            mGatt = bleDevice.connectGatt(mContext, false, mGattCallback);
                        }
                    }, 1000);
                }
            }
        }   
    }
}
15
kdbdallas

私も同じ問題に直面しています。これは、GoogleのポリシーがMarshmallow API 23以降のバージョンで変更されているため、BLEユーザーを使用するにはON GPS。 Googleドキュメントについては、この Permission @ Runtime リンクを確認してください。これを修正するには、電話の設定で「場所」を有効にするとともに、アプリの場所permissionをアプリのRuntimeでリクエストする必要があります。スキャンが正しく機能するためには、両方を実行する必要があります。

ロケーションのパーミッションをリクエストするには、ダイアログなどに以下を入力します。

myActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_COURSE_LOCATION}, yourPermissionRequestCode);

そして実装:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] Results){
    if(requestCode == yourPermissionRequestCode)
    {
        ... //Do something based on Results
    }
}

myActivityでは、ユーザーが選択したものをすべて処理します。また、デバイスの位置情報サービスをオンにするには、以下を実行する必要があります。

Intent enableLocationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
myActivity.startActivityForResult(enableLocationIntent, yourServiceRequestCode);

ユーザーが位置情報サービスをオンにしたかどうかを確認するには、以下を実装します。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if(requestCode == yourServiceRequestCode)
    {
        ...//Do whatever you need to
    }
}

myActivity。位置情報サービスを手動でオンにすることもできます。

Enter phone settings -> Select "Apps" -> Select your app -> Select the "Permissions" option -> Switch the "Location" permission on.

ユーザーが権限を有効にして位置情報サービスを開始したら、周辺機器のスキャンを開始できます。私は、位置情報サービスの許可/有効化を有効にしている間は、既にスキャンを行っていますが、onScanResultsには何も入力されません。

これにより、企業はあなたの場所を確認し、彼らが望む場所にあなたを導くことができます。

デバイスをスキャンしている間、BLEデバイスに接続すると、電話の位置情報サービスをオフにでき、引き続き周辺デバイスに接続したままになります。ただし、ファームウェア(ペリフェラル)に接続すると、ペアリングされたデバイスへの接続を切断するまで新しいペリフェラルに接続できなくなり、他のすべてのスキャンデバイス(モバイル)はスキャンリストにペリフェラルデバイス名を表示できません(ユーザーが周辺機器は一度に1つのデバイスにしか接続できないため、周辺機器が他のモバイルデバイスにすでに接続されている場合は、周辺機器で近くを検索します。 BLE基本サンプルについては、これを確認できます Truiton Bleチュートリアル 。このスニペットで問題が解決すると思います。幸せなコーディング:)

4
anand krish

アプリを非営利目的で使用している場合(つまり、5,000人未満のユーザーを想定している場合)、 P2Pkit を使用できます。

古いバージョンのAndroidでは、BLEおよび非BLE Bluetoothに加えてP2P wifi接続を使用し、実際に近くの電話の発見で素晴らしい結果を得ています。

利点は、IOSでも機能し、かなりシンプルなインターフェースを持っていることです。

欠点は、5Kを超えるユーザーが支払う必要があることです。

0
eiran

この質問は、以前に投稿したものに関連しています。このリンクをチェックしてください https://stackoverflow.com/a/39084810/399772 そしてこれは https://stackoverflow.com/a/39597845/399772 です

古いAPIと最新のAPIの2つのメソッドが必要です。

SDK 23以降については、ランタイム権限をリクエストする必要があります。位置情報の許可を求めてください。

0
Pedro Varela

Androidの電話にBluetoothチップが壊れている場合があります。hciログを確認しましたか?またはlogcat?

Bluetooth 4.0チップ(これはあなたのモトグラムにあります)には厳格な制限があり、常にスキャンを許可する必要がある場合でも、同時にセントラルとペリフェラルになることはできません。そのため、BT 4.0が段階的に廃止されるまで、Androidの周辺機能に依存する製品は作成しません。

少なくともBluetooth 4.1チップを搭載した新しい電話でテストする必要があります。

0
Emil