Wifi Direct - This device address not work on android 10 - android

I use this method to get the MAC address of my device. This works well in Android 9 and below. But in Android 10, the MAC address is not given correctly and it gives this value every time: 02: 00: 00: 00: 00: 00
public class WifiDirectBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION:
WifiP2pDevice device = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
Log.i("My device wifi direct Mac address", device.deviceAddress);
break;
}
}
}

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 (byte b : byteMac) {
strBuilder.append(String.format("%02X:", b));
}
if (strBuilder.length() > 0) {
strBuilder.deleteCharAt(strBuilder.length() - 1);
}
return strBuilder.toString();
}
}
} catch (Exception ignored) {
}
return null;
}

Related

Android USB Accessory to Host Communication Truncation

This is my first experience working with USB communication and an android app.
I'm using https://github.com/felHR85/UsbSerial to create a application that will allow tablets/phones to use USB OTG to act as a host and communicate with an accessory. I have gotten to the point where I'm using the SerialInputStreams and SerialOutputStreams to send and receive with the device.
This is about the maximum packet size a USB can send being 64 bytes with the cable I'm using. On my application, the accessory is sending data that is larger than 64 bytes. If the accessory does not have code that sends the data over in 64 byte packages, but instead all of it at once. Will any data that comes after 64 bytes be lost?
I'm receiving the first 64 bytes of the message from the accessory to the host and then host times out as it doesn't receive the full message and resends to the accessory. The first 64 bytes of the message are always what show up, that way I know the other parts of the message aren't waiting to be polled.
EDIT
The device I'm connecting to is a datalogger that is taken as a CDC device. I know that the connection I'm using has a maximum packet size of 64.
The USBConnectActivity happens whenever a usb device is attached and passes the filter that I have set up, and the interface and endpoints are correct.
public class USBConnectActivity extends Activity
{
public UsbDevice device = null;
public UsbManager manager = null;
public UsbDeviceConnection usbDeviceConnection = null;
public UsbSerialDevice serialPort = null;
public String deviceID = "";
public boolean isUSBConnected = false;
private PendingIntent mPermissionIntent;
private final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
stopUsbConnection();
unregisterReceiver(usbReceiver);
}
if(ACTION_USB_PERMISSION.equals(action))
{
setupCom();
}
}
};
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
USBConnection.getInstance().setManager(manager);
mPermissionIntent = PendingIntent.getBroadcast(
this,0,new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter mfilter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(usbReceiver,mfilter);
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(usbReceiver, filter);
findDevice(mPermissionIntent);
finish();
}
private void findDevice(PendingIntent i)
{
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
boolean found = false;
UsbDevice xDevice = null;
while (deviceIterator.hasNext()) {
UsbDevice tDevice = deviceIterator.next();
// Loop through the interfaces of the attached USB device
for (int count = 0; count < tDevice.getInterfaceCount(); count++) {
if (found) break;
// Use temp variables to check and then match with the private variables
UsbInterface inter = tDevice.getInterface(count);
UsbEndpoint tOut = null;
UsbEndpoint tIn = null;
if (inter.getEndpointCount() >= 2) {
for (int end_count = 0; end_count < inter.getEndpointCount(); end_count++) {
UsbEndpoint end = inter.getEndpoint(end_count);
if (end.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (end.getDirection() == UsbConstants.USB_DIR_OUT) tOut = end;
else if (end.getDirection() == UsbConstants.USB_DIR_IN) tIn = end;
}
}
}
if (tOut != null && tIn != null) {
device = tDevice; manager.requestPermission(device, i); found = true;
isUSBConnected = true;
USBConnection.getInstance().setDevice(device);
USBConnection.getInstance().attach();
}
}
}
if(usbDeviceConnection == null) setupCom();
}
#Override
protected void onStop()
{
super.onStop();
unregisterReceiver(usbReceiver);
}
private void setupCom()
{
deviceID = device.getDeviceName();
if(usbDeviceConnection == null) usbDeviceConnection = manager.openDevice(device);
if(serialPort == null)
{
serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
if(serialPort != null && serialPort.open())
{
serialPort.setBaudRate(115200);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
USBConnection.getInstance().setSerialPort(serialPort);
USBConnection.getInstance().setUsbDeviceConnection(usbDeviceConnection);
}
}
}
private void stopUsbConnection(){
manager = null;
device = null;
isUSBConnected = false;
USBConnection.getInstance().detach();
deviceID = "";
try
{
if(serialPort != null)
serialPort.close();
if(usbDeviceConnection != null)
usbDeviceConnection.close();
}
finally
{
serialPort = null;
usbDeviceConnection = null;
}
}
}
This class holds all the USB info
public class USBConnection
{
// USB information
public boolean isConnected;
public UsbDevice device;
public UsbManager manager;
public UsbSerialDevice serialPort;
public UsbDeviceConnection usbDeviceConnection;
public String deviceName;
public boolean waitForReading;
private static USBConnection instance;
public static USBConnection getInstance()
{
if(instance == null)
instance = new USBConnection();
return instance;
}
public void setDevice(UsbDevice device_)
{
device = device_;
deviceName = device.getDeviceName();
}
public void setManager(UsbManager manager_)
{
manager = manager_;
}
public void attach()
{
isConnected = true;
}
public void detach()
{
isConnected = false;
}
public void setSerialPort(UsbSerialDevice serialPort_)
{
serialPort = serialPort_;
}
public void setUsbDeviceConnection(UsbDeviceConnection usbDeviceConnection_)
{
usbDeviceConnection = usbDeviceConnection_;
}
public void writing() {
waitForReading = true;
}
public void reading(){
waitForReading = false;
}
public boolean waitingForRead()
{
return waitForReading;
}
}
This is the code I use to set up the input and output streams
else if(USBConnection.getInstance().isConnected) // check if usb is connected
{
manager = USBConnection.getInstance().manager;
device = USBConnection.getInstance().device;
// Attempt at setting up a USB input and output stream
if (manager != null) {
if(usbDeviceConnection == null) usbDeviceConnection = manager.openDevice(device);
if(serialPort == null)
{
serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
if(serialPort != null && serialPort.open())
{
serialPort.setBaudRate(115200);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
input = new SerialInputStream(serialPort);
output = new SerialOutputStream(serialPort);
Log.d("Direct", "Connected to the USB socket");
}
}
}
} // else there is no usb connected
This is in felHR85 UsbSerialDevice, in his ReadThread, and what is commented out is what I included thinking it would grab the data if it was larger than 64 bytes
int numberBytes, bytes;
if(inEndpoint != null) {
bytes = numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(),
SerialBuffer.DEFAULT_READ_BUFFER_SIZE, 100);
}/*while(numberBytes >= 64) {
numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(), bytes,
124, 100);
bytes += numberBytes;
Log.i("Bytes", " : " + bytes);
}*/
else
bytes = numberBytes = 0;
This is in his WriteThread
while(working.get())
{
byte[] data = serialBuffer.getWriteBuffer();
if(data.length > 0)
connection.bulkTransfer(outEndpoint, data, data.length, USB_TIMEOUT);
}
EDIT
This solved my problem but I'm still not sure what the answer is to my original question
if(serialPort == null)
{
usbDeviceConnection.claimInterface(USBConnection.getInstance().usbInterface, true);
usbDeviceConnection.controlTransfer(64,0,1,0,null,0,0); // clear tx
usbDeviceConnection.controlTransfer(64,0,2,0,null,0,0); // clear rx
serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
Please put up your code. Please specify any device that you are using as accessory(Arduino, FPGA, etc) so that finding solution becomes easier. It is difficult to tell what is going wrong. I suggest you to do the following -
1)Check the device descriptor of the accessory where it is clearly mentioned the maximum bytes the USB endpoint can transfer at a time. Here I have it for my Arduino Uno
2)I request you to go through this instead of using a library.
3)There is a DTR signal which must be sent form host to accessory to indicate that data transfer is complete; so that the next data can be sent.Check this
4)You should be using a ring buffer for the receiving stream so that the data is not lost.

How to detect MIUI ROM programmatically in android?

How can I detect the device run under Xiomi's MIUI ROM? I'm able to detect Xiomi device with the following code.
String manufacturer = "xiaomi";
if (manufacturer.equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
}
But how can I detect its MIUI?
Get device properties:
adb shell getprop
should result with:
[ro.miui.cust_variant]: [x]
[ro.miui.has_cust_partition]: [x]
[ro.miui.has_handy_mode_sf]: [x]
[ro.miui.has_real_blur]: [x]
[ro.miui.mcc]: [xxx]
[ro.miui.mnc]: [xxx]
[ro.miui.region]: [x]
[ro.miui.ui.version.code]: [x]
[ro.miui.ui.version.name]: [x]
[ro.miui.version.code_time]: [xxx]
And a few more consisting MIUI specific properties
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
String miui = (String) get.invoke(c, "ro.miui.ui.version.code"); // maybe this one or any other
// if string miui is not empty, bingo
Or, get list of packages:
adb shell pm list packages
should result with
package:com.miui.system
package:com.android.calendar
package:com.miui.translation.kingsoft
package:com.miui.virtualsim
package:com.miui.compass
...
So you could check with this piece of code:
//installedPackages - list them through package manager
for (String packageName : installedPackages) {
if (packageName.startsWith("com.miui.")) {
return true;
}
}
private static boolean isIntentResolved(Context ctx, Intent intent ){
return (intent!=null && ctx.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null);
}
public static boolean isMIUI(Context ctx) {
return isIntentResolved(ctx, new Intent("miui.intent.action.OP_AUTO_START").addCategory(Intent.CATEGORY_DEFAULT))
|| isIntentResolved(ctx, new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")))
|| isIntentResolved(ctx, new Intent("miui.intent.action.POWER_HIDE_MODE_APP_LIST").addCategory(Intent.CATEGORY_DEFAULT))
|| isIntentResolved(ctx, new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.powercenter.PowerSettings")));
}
Itents list from taken from https://github.com/dirkam/backgroundable-android
Detect android device info, MIUI version :
public static boolean isMiUi() {
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
}
public static String getSystemProperty(String propName) {
String line;
BufferedReader input = null;
try {
java.lang.Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return line;
}
Credits goes to Muyangmin

android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED alternative

I'm trying to implement a way to listen to a client's connection event on the smartphone hotspot. I see that android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED is no longer avaible. How can i do this? I think that this is possible because the smartphone notify me when i client make a connection to the smartphone hotspot.
You can't use the Intent Action...You have to use a custom method, i'l suggest you create a background thread that checks/reads the I.P table (/proc/net/arp) constantly and update you...here's a snippet I've used.
Read i.p list table
public ArrayList<String> getConnectedDevices() {
ArrayList<String> arrayList = new ArrayList();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));
while (true) {
String readLine = bufferedReader.readLine();
if (readLine == null) {
break;
}
String[] split = readLine.split(" +");
if (split != null && split.length >= 4) {
arrayList.add(split[0]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return arrayList;
}
Create runnable to check
class CheckHotSpotConnection implements Runnable {
private CheckHotSpotConnection() {
}
public void run() {
int i = 0;
while (discoverClient()) {
i = getConnectedDevices().size();
if (i > 1) {
//client discovered
//disable client discovery to end thread
} else {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Start Thread
new Thread(new CheckHotSpotConnection()).start();

Getting MAC address in Android 6.0

I'm developing an app that gets the MAC address of the device, but since Android 6.0 my code doesn't work, giving me an incorrect value.
Here's my code...
public String ObtenMAC()
{
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
return(info.getMacAddress().toUpperCase());
}
Instead of the real MAC address, it returns an strange code: 02:00:00:00:00:00.
Please refer to Android 6.0 Changes.
To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.
To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions.
Use below code to get Mac address in Android 6.0
public static String getMacAddr() {
try {
List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(Integer.toHexString(b & 0xFF) + ":");
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
} catch (Exception ex) {
//handle exception
}
return "";
}
I didn't get the above answer to work, but stumbled upon another answer.
Here is a complete and simple method on getting the IPv6 address and then getting the mac address from it.
How to get Wi-Fi Mac address in Android Marshmallow
public static String getMacAddr() {
try {
List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(String.format("%02X:",b));
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
} catch (Exception ex) {
}
return "02:00:00:00:00:00";
}
Tested it already and it works. Many thanks to Rob Anderson!
this is the complete 2 ways code of getting it successfully on Marshmallow , just copy past this and it will work !
//Android 6.0 : Access to mac address from WifiManager forbidden
private static final String marshmallowMacAddress = "02:00:00:00:00:00";
private static final String fileAddressMac = "/sys/class/net/wlan0/address";
public static String recupAdresseMAC(WifiManager wifiMan) {
WifiInfo wifiInf = wifiMan.getConnectionInfo();
if(wifiInf.getMacAddress().equals(marshmallowMacAddress)){
String ret = null;
try {
ret= getAdressMacByInterface();
if (ret != null){
return ret;
} else {
ret = getAddressMacByFile(wifiMan);
return ret;
}
} catch (IOException e) {
Log.e("MobileAccess", "Erreur lecture propriete Adresse MAC");
} catch (Exception e) {
Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
}
} else{
return wifiInf.getMacAddress();
}
return marshmallowMacAddress;
}
private static String getAdressMacByInterface(){
try {
List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (nif.getName().equalsIgnoreCase("wlan0")) {
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(String.format("%02X:",b));
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
}
} catch (Exception e) {
Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
}
return null;
}
private static String getAddressMacByFile(WifiManager wifiMan) throws Exception {
String ret;
int wifiState = wifiMan.getWifiState();
wifiMan.setWifiEnabled(true);
File fl = new File(fileAddressMac);
FileInputStream fin = new FileInputStream(fl);
StringBuilder builder = new StringBuilder();
int ch;
while((ch = fin.read()) != -1){
builder.append((char)ch);
}
ret = builder.toString();
fin.close();
boolean enabled = WifiManager.WIFI_STATE_ENABLED == wifiState;
wifiMan.setWifiEnabled(enabled);
return ret;
}
manifest :
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
Summary : this code will try to get the MAC address first by Interface and if its failed it get it by file system.
Note:for file System way, you need to enable WIFI to access the file.
thnx to Sam's answer here https://stackoverflow.com/a/39288868/3818437
You can get the MAC address from the IPv6 local address. E.g., the IPv6 address "fe80::1034:56ff:fe78:9abc" corresponds to the MAC address "12-34-56-78-9a-bc". See the code below. Getting the WiFi IPv6 address only requires android.permission.INTERNET.
See the Wikipedia page IPv6 address, particularly the note about "local addresses" fe80::/64 and the section about "Modified EUI-64".
/**
* Gets an EUI-48 MAC address from an IPv6 link-local address.
* E.g., the IPv6 address "fe80::1034:56ff:fe78:9abc"
* corresponds to the MAC address "12-34-56-78-9a-bc".
* <p/>
* See the note about "local addresses" fe80::/64 and the section about "Modified EUI-64" in
* the Wikipedia article "IPv6 address" at https://en.wikipedia.org/wiki/IPv6_address
*
* #param ipv6 An Inet6Address object.
* #return The EUI-48 MAC address as a byte array, null on error.
*/
private static byte[] getMacAddressFromIpv6(final Inet6Address ipv6)
{
byte[] eui48mac = null;
if (ipv6 != null) {
/*
* Make sure that this is an fe80::/64 link-local address.
*/
final byte[] ipv6Bytes = ipv6.getAddress();
if ((ipv6Bytes != null) &&
(ipv6Bytes.length == 16) &&
(ipv6Bytes[0] == (byte) 0xfe) &&
(ipv6Bytes[1] == (byte) 0x80) &&
(ipv6Bytes[11] == (byte) 0xff) &&
(ipv6Bytes[12] == (byte) 0xfe)) {
/*
* Allocate a byte array for storing the EUI-48 MAC address, then fill it
* from the appropriate bytes of the IPv6 address. Invert the 7th bit
* of the first byte and discard the "ff:fe" portion of the modified
* EUI-64 MAC address.
*/
eui48mac = new byte[6];
eui48mac[0] = (byte) (ipv6Bytes[8] ^ 0x2);
eui48mac[1] = ipv6Bytes[9];
eui48mac[2] = ipv6Bytes[10];
eui48mac[3] = ipv6Bytes[13];
eui48mac[4] = ipv6Bytes[14];
eui48mac[5] = ipv6Bytes[15];
}
}
return eui48mac;
}
I try to get mac address with 2 methods, first by Interface and if its failed, i get it by file system, but you need to enable wifi to access the file.
//Android 6.0 : Access to mac address from WifiManager forbidden
private static final String marshmallowMacAddress = "02:00:00:00:00:00";
private static final String fileAddressMac = "/sys/class/net/wlan0/address";
public static String recupAdresseMAC(WifiManager wifiMan) {
WifiInfo wifiInf = wifiMan.getConnectionInfo();
if(wifiInf.getMacAddress().equals(marshmallowMacAddress)){
String ret = null;
try {
ret= getAdressMacByInterface();
if (ret != null){
return ret;
} else {
ret = getAddressMacByFile(wifiMan);
return ret;
}
} catch (IOException e) {
Log.e("MobileAccess", "Erreur lecture propriete Adresse MAC");
} catch (Exception e) {
Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
}
} else{
return wifiInf.getMacAddress();
}
return marshmallowMacAddress;
}
private static String getAdressMacByInterface(){
try {
List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (nif.getName().equalsIgnoreCase("wlan0")) {
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(String.format("%02X:",b));
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
}
} catch (Exception e) {
Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
}
return null;
}
private static String getAddressMacByFile(WifiManager wifiMan) throws Exception {
String ret;
int wifiState = wifiMan.getWifiState();
wifiMan.setWifiEnabled(true);
File fl = new File(fileAddressMac);
FileInputStream fin = new FileInputStream(fl);
ret = convertStreamToString(fin);
fin.close();
boolean enabled = WifiManager.WIFI_STATE_ENABLED == wifiState;
wifiMan.setWifiEnabled(enabled);
return ret;
}
Add this line to your manifest.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
I recommend you to persist your mac address in your preferences like here
mac = activity.getSharedPreferences("MAC_ADDRESS", Context.MODE_PRIVATE).getString("MAC_ADDRESS", "");
if(mac == null || mac.equals("")){
WifiManager wifiMan = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
mac = MobileAccess.recupAdresseMAC(wifiMan);
if(mac != null && !mac.equals("")){
SharedPreferences.Editor editor = activity.getSharedPreferences("MAC_ADDRESS", Context.MODE_PRIVATE).edit();
editor.putString("MAC_ADDRESS", mac).commit();
}
}
Its Perfectly Fine
package com.keshav.fetchmacaddress;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("keshav","getMacAddr -> " +getMacAddr());
}
public static String getMacAddr() {
try {
List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(Integer.toHexString(b & 0xFF) + ":");
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
} catch (Exception ex) {
//handle exception
}
return "";
}
}
First you need to add Internet user permission.
<uses-permission android:name="android.permission.INTERNET" />
Then you can find the mac over the NetworkInterfaces API.
public static String getMacAddr() {
try {
List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
return "";
}
StringBuilder res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(String.format("%02X:",b));
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
return res1.toString();
}
} catch (Exception ex) {
}
return "02:00:00:00:00:00";
}
The answers are mostly correct, but keep care, that there is a change in android 7. You will need to use the
DevicePolicyManager and the Method getWifiMacAddress. The official docs has a typo, which means that you shouldnt copy/paste it from there.
DevicePolicyManager.getWifiMacAddress()
Refs:
https://developer.android.com/about/versions/nougat/android-7.0-changes.html
Get Device mac adress in Android Nougat and O programmatically
Use wifiInfo.getBSSID() to get Mac Address of AccessPoint instead of getMacAddress method.
This is a more kotlin way to get Mac Address
fun getMacAddress(): String =
NetworkInterface.getNetworkInterfaces().toList()
.firstOrNull { it.name.equals("wlan0", ignoreCase = true) }?.let {
it.hardwareAddress?.let { macBytes ->
StringBuilder().apply {
for (b in macBytes) {
append(String.format("%02X:", b))
}
if (isNotEmpty()) {
deleteCharAt(lastIndex)
}
}
}.toString()
} ?: "02:00:00:00:00:00"

android Bluetooth crash when connection is stopped

I am writing an app on Android Studio.
I communicate from an Android device to an arduino board via Bluetooth.
For now everything works but i am starting a new Activity and i need to stop the actual BT connection. so i want to call a stop method.
The problem is that it crash when i call it.
here is the code
public class BtInterface {
private BluetoothDevice device = null;
private BluetoothSocket socket = null;
private InputStream receiveStream = null;
private OutputStream sendStream = null;
String GlobalBuff="";
String Right_Buff="";
private ReceiverThread receiverThread;
Handler handler;
public BtInterface(Handler hstatus, Handler h,String Device_Name) {
Set<BluetoothDevice> setpairedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
BluetoothDevice[] pairedDevices = (BluetoothDevice[]) setpairedDevices.toArray(new BluetoothDevice[setpairedDevices.size()]);
for(int i=0;i<pairedDevices.length;i++) {
if(pairedDevices[i].getName().contains(Device_Name)) {
device = pairedDevices[i];
try {
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
receiveStream = socket.getInputStream();
sendStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
handler = hstatus;
receiverThread = new ReceiverThread(h);
}
public void sendData(String data) {
sendData(data, false);
}
public void sendData(String data, boolean deleteScheduledData) {
try {
sendStream.write(data.getBytes());
sendStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void connect() {
new Thread() {
#Override public void run() {
try {
socket.connect();
Message msg = handler.obtainMessage();
msg.arg1 = 1;
handler.sendMessage(msg);
receiverThread.start();
} catch (IOException e) {
Log.v("N", "Connection Failed : " + e.getMessage());
e.printStackTrace();
}
}
}.start();
}
public void close() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
socket=null; //???
}
public BluetoothDevice getDevice() {
return device;
}
private class ReceiverThread extends Thread {
Handler handler;
ReceiverThread(Handler h) {
handler = h;
}
#Override public void run() {
while(true) {
try {
if(receiveStream.available() > 0) {
byte buffer[] = new byte[1000];
int k = receiveStream.read(buffer, 0, 1000);
if(k > 0) {
byte rawdata[] = new byte[k];
for(int i=0;i<k;i++)
rawdata[i] = buffer[i];
String data = new String(rawdata);
GlobalBuff= GlobalBuff+data;
Right_Buff= GlobalBuff.substring(GlobalBuff.length()-1,GlobalBuff.length());
if(Right_Buff.equals("\n")){
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("receivedData", GlobalBuff);
msg.setData(b);
handler.sendMessage(msg);
GlobalBuff="";
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
i try some extra code :
receiverThread.interrupt();
receiverThread=null;
if (receiveStream != null) {
try {receiveStream.close();} catch (Exception e) {}
receiveStream = null;
}
if (sendStream != null) {
try {sendStream.close();} catch (Exception e) {}
sendStream = null;
}
before closing but the result is the same , it crash.
The strange behavior is that it didn't crash immediately as it could happen with a type error or else ( i am talking of the behavior in debug mode...)
If anybody got an idea.
Googling this bring me to people with this issue but no solution that works for my case.
Thanks
UPDATE
what i found as a trace when it crash is that :
06-02 07:45:27.369 9025-9133/fr.icservice.sechage A/libc? Fatal signal 11 (SIGSEGV) at 0x00000008 (code=1), thread 9133 (Thread-1436)
I also made a test on a sony Z3 phone under 5.0.2 (compare to my T210 samsung galaxy tab3 under 4.4.2)and it not crash..!
maybe it's a ROM bug?! or a android version problem...
This is a known problem (or bug?) on Android. If you close the Bluetooth socket and then access it later on, some devices will crash with a segmentation fault (like yours). A common workaround is to check socket.isConnected() before or to synchronize the access to close(), write(), read(), ... by setting a flag like closeWasCalled = true and prevent any further calls to methods of this socket in your code after a close() call.
The problem comes with Socket Input/Output. I faced this problem when disconnecting with peer bluetooth device.
Reason :
From code, we are trying to read() , write() from socket object/connection which is closed.
Solution :
Add checking socket.isConnected() before above operations
You can read more about this problem on Stack Overflow question : Here

Categories

Resources