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

私はBluetooth LEデバイスをスキャンし、周辺機器(Moto G 2nd GenでAndroid 6.0を実行)として実行しています。

私が抱えている問題は、時々(ランダムに見えますが、頻繁に)それが私の他の周辺機器のどれも見つけられないということです、他の回それはうまく働きます。

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

それは私の仲間のiOSデバイスを見つけられないだけでなく、どんなBluetoothデバイスも見つけません。それが動作すると、それは私の仲間のiOSデバイスだけでなく他のデバイスの束を見つけます。

私はScanFiltersの有無にかかわらずそれを試みました、そして同じ問題を得ます。 私はSDK 26に対して最小のSDK 23で構築しています。

それは時々うまくいくので、私は必要な許可を設定しています。

以下の関連コード:

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 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);
                }
            }
        }   
    }
}
8
はい、そして私が述べたようにそれはほとんどの時間うまくいくが、時折アプリを再実行すると何も見つからないでしょう。位置情報サービスが有効になっていないと、ほとんどの場合は機能しません。アプリを終了して再起動するだけで、デバイスを再度見つけることができますが、これは出荷用アプリでは受け入れられません。
追加された 著者 kdbdallas,
@eiran HIGH_PERFORMANCEの設定は何ですか? Androidはこれを「最高デューティサイクルを使用してスキャンする」と指定しているため、スキャンを実行するときにSCAN_MODE_LOW_LATENCYを使用しています。
追加された 著者 kdbdallas,
@eiranが示唆していることとやや関連しています。これは、省電力/スロットルが原因である可能性があります。私はAndroidには馴染みがありませんが、Bluetoothの "Inquiry SCAN"サブステートには比較的大きなエネルギーインパクトがあることを私は知っています。
追加された 著者 MarkM,
スキャンでデバイスが見つかったかどうかを検出し、見つからなかった場合は、ユーザーが別のスキャンを実行できるようにする(ダイアログのボタンを押すなど)か、単に自動的に別のスキャンを実行するかについてはどうですか。私たちのアプリでは、検出されたデバイスにリストされていると思われるデバイスが表示されていない場合は、再度スキャンするオプションをユーザーに常に提供します。
追加された 著者 hBrent,
あなたはあなたの位置情報サービスが有効になっている場合にのみあなたがデバイスを見つけることを知っていますか?
追加された 著者 Tim Castelijns,
設定でHIGH_PERFORMANCEを試してください..それは変更を加えるのですか?また、AlarmManagerのようなサービスを有効に使用しないと、BLEはバックグラウンドで動作しなくなります
追加された 著者 eiran,
私の悪い私はP2Pkitと呼ばれるライブラリを使用しています..それは実際にはOKです。しかし、私はあなたがここから取らMATCH_MODE_AGGRESSIVEを試してみるべきであると思います: .com/reference/android/bluetooth/le /…
追加された 著者 eiran,
@ kdbdallasライブラリを使ってスキャンしてみることをお勧めします
追加された 著者 Sundeep1501,
携帯を再起動してもう一度やり直してください。時にはBluetoothスタックがクラッシュすることがあります。
追加された 著者 Marcin Deszczynski,

4 答え

それは単にAndroid携帯電話が安っぽいブルートゥースチップを持っているという場合だけかもしれません。 hciログを見ましたか?それともlogcat?

Bluetooth 4.0チップ(これはあなたの目的です)には、スキャンを常に許可する必要があるとしても、同時に中央と周辺機器になることはできないという厳しい制限があります。したがって、BT 4.0が廃止されるまで、私はAndroidの周辺機能に依存する製品を作りません。

あなたは少なくともBluetooth 4.1チップを持っているより新しい電話でテストするべきです。

0
追加された
(それが動作するとき)私はちょうど罰金同時に中央と周辺の両方になることができます。残念ながら私は別のデバイスを持っていません(私はほとんどの場合iOS開発者です)が、別のデバイスを借りようとしていることを検討し、他のデバイスでそれを試してみるようにしています。ありがとう
追加された 著者 kdbdallas,

私は同じ問題に直面しています。これは、BLEユーザーが GPS をオンにする必要があるため、Googleのポリシーが Marshmallow API 23 以降のバージョンに変更されたためです。 Googleドキュメントの場合は、 Permission @ Runtime のリンクを確認してください。それを修正するには、電話の設定で "Location"を有効にすると共に、アプリケーションの 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.

Once the user has enabled the permission and started location services then you could start scanning for peripherals. I've noticed that if you are already scanning while you enable the permission/turn on the location service it will still not put anything in your onScanResults

これにより、企業はあなたの現在地を確認し、自分が望む場所にあなたを案内することができます。

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

0
追加された
問題は、私がすでにロケーション許可を設定し、それを要求していることです。問題は、許可を要求しても時々(ランダムに)機能しないことです。私が許可を要求していなければそれは決してうまくいかないでしょう。
追加された 著者 kdbdallas,

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

それはアンドロイドの古いバージョンでは、BLEと非BLEブルートゥースに加えて、P2P無線LAN接続を使用し、実際に近くの携帯電話の発見に素晴らしい結果を得ます。

逆にそれはIOSでも動作し、そしてそれはかなり単純なインターフェースを持っています。

欠点はあなたが支払わなければならない5Kユーザー以上です..

0
追加された
おかげでこれはその限界をはるかに超えている商用アプリのためのものです
追加された 著者 kdbdallas,

This question is related to something I post before. Check this link https://stackoverflow.com/a/39084810/3997720 and this one https://stackoverflow.com/a/39597845/3997720

1つは古いAPI用、もう1つは最新のAPI用の2つの方法が必要です。

SDK 23以降に関しては、ランタイムパーミッションを要求する必要があります。場所の許可を求めます。

0
追加された
私はより新しいAPIを使用するデバイスを実行していて、それが時々うまくいくように私がこれがどのように問題であるかもしれないかについて見ません。はい、これは古いデバイスには必要でしょうが、なぜ私の現在のコードが時々動くのか、そして同じデバイス上で他の時に動かないのかを説明していません
追加された 著者 kdbdallas,
だからそれはデバイス自体かもしれません。他の電話や製造業者でコードを試してください。
追加された 著者 Pedro Varela,
念のために、あなたはあなたのマニフェストにこれを持っていますか? <! - 自分のアプリをBLE対応の視聴者のみが利用できることを宣言するには、アプリのマニフェストに次の内容を含めます。 :required = "true" />
追加された 著者 Pedro Varela,