I'm a newbie on Android BLE programming.
So, I need a people who have a professional skills on a BLE concept :)
I made a app which connect between apple device and android phone.
apple device is slave, so apple send advertise message to android periodically.
But I have a little confused how to find my bluetooth device between scan results.
m_lescanner.startScan(filters, new ScanSettings.Builder().setScanMode(2).build(), m_scan_callback);
My app enroll broadcast receiver to listen bluetooth events.
If the events occurs, app start scanStart function to gathering BLE device near by android phone.
private ScanCallback m_scan_callback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
After that, I got a many BLE device results including my BLE device(apple device) But I don't know what BLE results is mine....
all MAC address is different, and all UUID is null(I'm also confused why this flags is different and results is null).
Thank you for reading my question.
PLEASE HELP!!!
The ScanFilter android man page mentions that you can do filtering based on MAC addresses of remote devices "Current filtering on the following fields are supported: Mac address of the remote device.". AFAIK, the address broadcasted in the advertisement is a "Private Resolvable Address" which is an address that changes periodically in order to avoid device tracking attacks. So, how does a ScanFilter know about the mac address of the remote device to do the filter. I've added the Bluetooth mac address for a remote device as a filter as in the following code snippet but scanning did not yield any results:
List<ScanFilter> listFilter = new ArrayList<>();
ScanFilter scanFilterMac = new ScanFilter.Builder().setDeviceAddress("88:88:88:B0:03:DB").build();
listFilter.add(scanFilterMac);
bluetoothLeScanner.startScan(listFilter, scanSettings, scanCallback);
However, when I scan for a service based on UUID as in the following code snippet, the filtering works:
List<ScanFilter> listFilter = new ArrayList<>();
ScanFilter scanFilterService = new ScanFilter.Builder().setServiceUuid(SERVICE_ID).build();
listFilter.add(scanFilterService);
bluetoothLeScanner.startScan(listFilter, scanSettings, scanCallback);
Any idea how to make ScanFilter based on remote device MAC address work? Is the MAC address mentioned in the man page is the same Bluetooth MAC address that you can get programmatically print on the other device using the following code:
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
Log.i(TAG, "MAC: "+bluetoothAdapter.getAddress());
The addresses you can get when you scan devices are the mac addresses of BT devices which do not change. In the filtering you use this same address which is in format 12:34:56:78:9A:BC.
Your code:
ScanFilter scanFilterMac = new ScanFilter.Builder().setDeviceAddress("88:88:88:B0:03:DB")
is correct.
Most likely the problem you are facing that the filtered scan is not giving any result is because there is a bug in certain Android devices where the MAC address filtering does not work. I don't know exactly how many percentage of Android devices do not work since I have only access to about 10 different device models. If you want to verify that your code works I recommend using any Nexus device with latest firmware update.
Summary
I recommend to not use this mac address filtering and make the filtering code yourself on onScanResult function to support all Android 5.0+ devices.
I try to build a project that can get Bluetooth rssi from specific devices. However, I'm stuck on that. Is there any way to filter and specify the scanning results and then continuously get information from the chosen Bluetooth devices?
Many thanks.
Yes
You can filter using device MAC address in android
//lets say i have a device i got by searching BT devices
BluetoothDevice device;
String mac = "00:11:22:AA:BB:CC"
if(mac.equals(device.getAddress)){
// my device found
}
public String getAddress ()
Added in API level 5
Returns the hardware address of this BluetoothDevice.
Bluetooth hardware address as string
for more see Android BluetoothDevice doc
Is it possible to connect with other Bluetooth LE device with out scanning.
I am working on app when bluetooth is ON and then automatically received the notification when I enter in any marketPlace that Beacon device(basically Bluetooth LE) is in your range. without my scanning Bluetooth Le. My Bluetooth is just ON. no scanning.
Because our requirements are that bluetooth doesn't scan just on, when ever new BLE is in range show alert or any notification.
I implement some scan method
startScan(){}
stopScan(){}
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {}
but i don't want that i directly want to get connection message.
Please help me in form of pieces of code and also with little bit explanation
Thanks
You can use BluetoothAdapter.
BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(mac);
device.connectGatt(mContext, false, mGattCallback);
// TODO your code
If the bluetooth device is not around, in BluetoothGattCallback's onConnectionStateChange will report BluetoothGatt.STATE_DISCONNECTED.
BluetoothDevice's creator has packages scope. But the source code of BluetoothAdapter's getRemoteDevice is:
public BluetoothDevice getRemoteDevice(String address) {
return new BluetoothDevice(address);
}
Do you just want to discover devices that support a particular service? There is an overload startLeScan(UUID[], ...), where you can pass the UUID's of the services that you are interested in.
Otherwise, if you just want to connect to a device of a known BT address, you maybe able to create a Bluetooth device object with that address and call connectGatt() on it. Just an idea, not sure if this would work :-)
Creating a bluetooth device object with address is not possible!
BluetoothDevice's creator has packages scope. so you can not create BluetoothDevice.
And although BluetoothDevice implements Parcelable, it cannot be created from a file.
I'm currently trying to connect two phones which know each other's MAC address via Wi-Fi Direct, and stumbled upon the following problem:
The MAC address, which I receive from
WifiManager wifiMan = (WifiManager) this
.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInf = wifiMan.getConnectionInfo();
MAC_ADDRESS = wifiInf.getMacAddress();
is slightly different than the one I receive from the WifiP2pManager when discovering and requesting peers. Example: a0:xx:xx:... turns into a2:xx:xx....
Does anyone know why? I did not find any way to get the "Wi-Fi Direct MAC address", and as I thought the MAC address should be unique, and it's the same Wi-Fi module that handles both (normal Wi-Fi and P2P/Direct). This is very weird..
What should I do? For the two devices (Galaxy Nexus) I've got, it's always only the first two characters that differ in the MAC addresses - should I simply discard them? Is the probability to encounter problems (two devices which only differ in the first part of MAC address) too high?
Thanks.
Reading about the MAC address on wikipedia.
Addresses can either be universally administered addresses or locally administered addresses.
Universally administered and locally administered addresses are distinguished by setting the second-least-significant bit of the most significant byte of the address. This bit is also referred to as the U/L bit, short for Universal/Local, which identifies how the address is administered. If the bit is 0, the address is universally administered. If it is 1, the address is locally administered.
Since Wi-Fi Direct is just another stack on top of MAC, you should also check what that bit can mean for it. I've found some mail discussion shedding some light on this. Apparently quote below is from a WFA spec.
The P2P Device shall assign a P2P Interface Address, corresponding to
the format as described in §7.1.3.3.1 of IEEE Std 802.11‑2007 1, which
is used to communicate with the P2P Group Owner or Clients within a P2P
Group. A P2P Interface Address is not required to be globally unique and
may be locally administered. A P2P Interface Address may be the same as
the P2P Device Address provided the requirements for P2P Interface
Address in this clause are satisfied.
So I believe answer to this question is, you shouldn't take MAC address from WifiManager and use it with Wi-Fi P2P connections.
I had been searching for this during my project. My requirements were to uniquely identify devices in an adhoc P2p network formed with WiFi Direct. Each device should identify its friend device the next time when it comes into proximity. I needed my own WiFi (Direct) MAC and my friends' to create a Key for this friend zone creation.
My Research: The design is in such a way that there is an Unique Universal ID and a Local ID. Reason: Universal ID can only be used to connect to Infrastructure mode Networks. Local ID could be used for "ad-hoc" mode networks(device to device). In this ad-hoc mode, there are possibilities that a single device might simultaneosly belong to several ad-hoc groups.
Hence to support this concurrent operations, P2p devices support
Multiple MAC entities, possibly on different channels.
For each session, a persistent group MAY use a different channel and device
MAC for each session.
P2P devices use their global MAC address as Device ID during discovery and negotiation, and a temporary local MAC address for all frames within a group. Understood from here
However, there is NO straight forward way to obtain one's own WiFi P2p MAC address. Issue 53437: Android.
In this issue discussion, the project member from google has suggested this is possible and just that it hasn't been documented
Solution: Using intent filter WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION and the extra
from the intent WifiP2pManager.EXTRA_WIFI_P2P_DEVICE
This is how I have used it in my project:
#Override
public void onReceive(Context context, Intent intent) {
....
....
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
.equals(action)) {
WifiP2pDevice device = (WifiP2pDevice) intent
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
String myMac = device.deviceAddress;
Log.d(TAG, "Device WiFi P2p MAC Address: " + myMac);
/* Saving WiFi P2p MAC in SharedPref */
sharedPref = context.getSharedPreferences(context.getString(R.string.sp_file_name), Context.MODE_PRIVATE);
String MY_MAC_ADDRESS = sharedPref.getString(context.getString(R.string.sp_field_my_mac), null);
if (MY_MAC_ADDRESS == null || MY_MAC_ADDRESS != myMac) {
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(context.getString(R.string.sp_field_my_mac), myMac);
editor.commit();
}
Hope this helps someone!
iFixit says that the Galaxy Nexus uses the BCM4330 for its MAC, Baseband, and PHY, so if you have any friends at Broadcom you could ask them.
Sadly, the datasheet is not public; the best I can do is link you to a block diagram.
I was struggling all night to figure out a way to retrieve WiFi Direct mac address instead, since my requirements were drafted around the assumption that it's feasible.
It's kind of round about, you create a single device group and get the owner and the device address along with it.
Here's the code,
final WifiP2pManager p2pManager = (WifiP2pManager) getSystemService(WIFI_P2P_SERVICE);
final WifiP2pManager.Channel channel = p2pManager.initialize(this, getMainLooper(), null);
p2pManager.createGroup(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
p2pManager.requestGroupInfo(channel, new WifiP2pManager.GroupInfoListener() {
#Override
public void onGroupInfoAvailable(WifiP2pGroup wifiP2pGroup) {
Log.i("", wifiP2pGroup.getOwner().deviceAddress);
// Following removal necessary to not have the manager busy for other stuff, subsequently
p2pManager.removeGroup(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Log.i("", "Removed");
}
#Override
public void onFailure(int i) {
Log.i("", "Failed " + i);
}
});
}
});
}
#Override
public void onFailure(int i) {
Log.i("", String.valueOf(i));
}
});
Forget Wifi manager. Wifi direct address does not equals to MAC address. Wifi direct address uses for wifi direct connection. You can not use to anything else.
To connect two device with wifi direct device, you have to create a WifiP2pGroup with one of your device. With your another device, you have to search the WifiP2pGroups, select yours, and connect.
You can get WiFi direct address using next code:
public String getWFDMacAddress(){
try {
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface ntwInterface : interfaces) {
if (ntwInterface.getName().equalsIgnoreCase("p2p0")) {
byte[] byteMac = ntwInterface.getHardwareAddress();
if (byteMac==null){
return null;
}
StringBuilder strBuilder = new StringBuilder();
for (int i=0; i<byteMac.length; i++) {
strBuilder.append(String.format("%02X:", byteMac[i]));
}
if (strBuilder.length()>0){
strBuilder.deleteCharAt(strBuilder.length()-1);
}
return strBuilder.toString();
}
}
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
return null;
}