Log
クラスを使用してランタイムを追跡すると、onReceive()
メソッドが呼び出されないことがわかります。なぜですか?
放送受信機を動的に登録
private void discoverDevices () {
Log.e("MOHAB","BEFORE ON RECEIVE");
mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Log.e("MOHAB","ON RECEIVE");
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
Bluetooth b = new Bluetooth(device.getName(),device.getAddress());
list.add(b);
}
}
};
Log.e("MOHAB","create intentFilter");
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
}
あなたが逃したのは、デバイスの回復を開始する必要があるということです
まず、Bluetoothアダプターを入手します
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
その後、あなたは電話で発見を開始します
mBtAdapter.startDiscovery();
ここでも詳細を読む必要があります。約cancelDiscovery()
http://developer.Android.com/reference/Android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29
P.S。また、公式ドキュメントによると、context.getSystemService(Context.BLUETOOTH_SERVICE)
を使用してAPI 18以降でBluetoothAdapterを取得することをお勧めします。
ローカルのBluetoothアダプターを表すBluetoothAdapterを取得するには、JELLY_BEAN_MR1以下で実行しているときに、静的なgetDefaultAdapter()メソッドを呼び出します。 JELLY_BEAN_MR2以上で実行している場合は、BLUETOOTH_SERVICEを指定したgetSystemService(Class)で取得します。
編集:startDiscovery()
への BLUETOOTH_ADMIN 権限が必要であることを思い出してください
Android 6.0で始まる という事実は別として、_ACCESS_COARSE_LOCATION
_ を受け取るには_ACTION_FOUND
_権限が必要です(@としてsiniuxは既に言及されています)、別の関連するものがあり:
_ACCESS_COARSE_LOCATION
_は、 危険な権限 の中にあり、実行時にユーザーから明示的に要求する必要があります(6.0で導入された別のセキュリティ改善)。
診断するには、_adb logcat | grep BroadcastQueue
_を実行して、次のように表示できます。
_W/BroadcastQueue: Permission Denial: receiving Intent {
act=Android.bluetooth.device.action.FOUND flg=0x10 (has extras) }
to ProcessRecord{9007:com.examplepackage} (pid=9007, uid=10492)
requires Android.permission.ACCESS_COARSE_LOCATION due to sender
com.Android.bluetooth (uid 1002)
_
したがって、MarshmallowでのBTデバイス検出の正しい手順は次のようになります。
通常のBluetoothアクセス許可とともに、マニフェストに_ACCESS_COARSE_LOCATION
_アクセス許可の要件があります。
_<uses-permission Android:name="Android.permission.BLUETOOTH" />
<uses-permission Android:name="Android.permission.BLUETOOTH_ADMIN" />
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
_
_ACCESS_COARSE_LOCATION
_の実行時権限 があることを確認してください
_protected void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_COARSE_LOCATION);
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_COARSE_LOCATION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
proceedDiscovery(); // --->
} else {
//TODO re-request
}
break;
}
}
_
}
_ACTION_FOUND
_のブロードキャストレシーバーを登録し、BluetoothAdapter.startDiscovery()
を呼び出します。
_protected void proceedDiscovery() {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery();
}
_
_ACTION_NAME_CHANGED
_の面白い点。 6.0はおおまかな場所の許可なしに_ACTION_FOUND
_を提供しませんが、デバイスが検出されると、通常_ACTION_NAME_CHANGED
_と連携して_ACTION_FOUND
_イベントを取得します。つまり両方のイベントを取得するため、許可がなくても、ほぼ同じ動作で_ACTION_NAME_CHANGED
_を処理できます。 (達人、私が間違っていれば訂正してください)
ブロードキャストレシーバーにも同様の問題がありました。それから私はこれを見つけました: https://developer.Android.com/about/versions/Marshmallow/Android-6.0-changes.html#behavior-hardware-id
基本的に、6.0では、Bluetoothデバイスをスキャンするには、位置情報の権限を使用する必要があります。
Android 6以降、1。)でACTION_FOUNDを機能させるには、専門家からの回答に従って次の点を確認してください。BLUETOOTHとBLUETOOTH_ADMINの権限を設定することに加えて、
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
時々これら二つは必要とされないかもしれませんが、それは私のために働きました。また、コードを使用して動的にユーザー権限を求める必要があります
int MY_PERMISSIONS_REQUEST = 200;
int permissions=ContextCompat.checkSelfPermission (this,Manifest.permission.ACCESS_FINE_LOCATION);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST);
次に、必要な操作を実行するためのコードを記述します。この直後に1つのstartDiscovery()メソッドを追加しました。確かに、これはあなたのために働くでしょう...ハッピーコーディング...
あなたのコードがBluetoothデバイスを取得するのに正しいかどうか私は知りません。これがあなたのコードについて私が感じることです。関数内でのBroadcastReceiverの初期化と登録はお勧めできません。 onCreate()
メソッドの外で行う必要があります。これがコードで行う必要があることです
このようにonCreate()
で行わなければならないReciverの登録について
_registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
_
初期化または受信者を伴う
_private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("MOHAB","ON RECEIVE");
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
Bluetooth b = new Bluetooth(device.getName(),device.getAddress());
list.add(b);
}
}
};
_
onPause()
で受信者の登録を解除することを忘れないでください
discoverDevices()
では、その機能の呼び出しごとに、受信者によって追加されたデバイスのlist
を返すだけです。
私が開発していたデバイス(Galaxy S4)は、ブロードキャストを受信し続ける前に再起動する必要があることがわかりました。
しかし、私の場合、私はそれらが(ランダムに?)受信を停止するまで問題なく受信し、私が何をしたにも関わらず(アプリを閉じ、アプリを再インストール)ブロードキャストが受信されませんでした。
現在の担当者レベルではコメントできないため、これを回答として投稿します。
AndroidManifest.xmlにBluetoothパーミッションが含まれていますか?
<uses-permission Android:name="Android.permission.BLUETOOTH"/>
<uses-permission Android:name="Android.permission.BLUETOOTH_ADMIN"/>
そうでない場合は、それぞれの重要性を思い出せないため、それぞれを個別に試してみてください。
これらをお持ちの場合は、より多くのコードを含めてください。問題を診断できるようになります。