This is my first app in Android. I am very new to Android and Java. I am kind of expert in iOS/ObjC though. I am learning by doing. So I jumped straight into making an app to connect to a bluetooth device. First step is of course to get a list of the bluetooth device available in range.
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest...>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application ...
Here is my Activity code:
private BluetoothAdapter btAdapter;
#Override
public void onDestroy() {
super.onDestroy();
// Unregister broadcast listeners
unregisterReceiver(mReceiver);
}
/*------------- ON CREATE ------------------------------*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
System.out.println ("Bluetooth non support");
} else {
System.out.println ("Bluetooth initialized");
}
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mReceiver, filter);
IntentFilter filterDevice = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filterDevice);
if (btAdapter.isEnabled()) {
String mydeviceaddress = btAdapter.getAddress();
String mydevicename = btAdapter.getName();
String status = mydevicename + " : " + mydeviceaddress;
System.out.println(status);
System.out.println ("Start discover");
btAdapter.startDiscovery();
} else {
System.out.println ("Not enabled");
Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBT, 1);
}
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
System.out.println("1");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
System.out.println("2");
break;
case BluetoothAdapter.STATE_ON:
System.out.println("3");
// SCAN HERE
btAdapter.startDiscovery();
break;
case BluetoothAdapter.STATE_TURNING_ON:
System.out.println("4");
break;
}
}
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
System.out.println(device.getName() + "\n" + device.getAddress());
} else {
System.out.println("What de fuq");
}
}
};
I turned on bluetooth on my android phone, and then running the app shows that log:
Bluetooth initialized
Start discover
And thats all. Other logs are not printing out. Any idea why? My code seems perfect idk.
EDIT: Screenshot of the Bluetooth module HC-05 being detected by Android.
The other devices may not be in discoverable mode. Make sure they are discoverable.
If your other device is a bluetooth module, in your case Arduino, right?
If so, check this tutorial describing connection between Android device and HC05 module.
bthc-05 to android tutorial
Also, based on this official sample: google sample - bluetooth chat
Alternatively, you could also have the following method that makes your device discoverable. And install it on two phones. Then you should be able to discover the phones on each other atleast.
protected void makeDiscoverable(){
// Make local device discoverable
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, DISCOVERABLE_DURATION);
startActivityForResult(discoverableIntent, DISCOVERABLE_BT_REQUEST_CODE);
}
Maybe these help!
Related
btAdapter.isDiscovering(),btAdapter.startDiscovery(); btAdapter.cancelDiscovery(); device.getName();
4four erros
Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException
Please solve this problem
public void onClickButtonSearch(View view){
// Check if the device is already discovering
if(btAdapter.*isDiscovering()*){
*btAdapter.cancelDiscovery()*;
} else {
if (btAdapter.isEnabled()) {
*btAdapter.startDiscovery();*
btArrayAdapter.clear();
if (deviceAddressArray != null && !deviceAddressArray.isEmpty()) {
deviceAddressArray.clear();
}
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(receiver, filter);
} else {
Toast.makeText(getApplicationContext(), "bluetooth not on", Toast.LENGTH_SHORT).show();
}
}
}
// Create a BroadcastReceiver for ACTION_FOUND.
private final BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.*getName();*
String deviceHardwareAddress = device.getAddress(); // MAC address
btArrayAdapter.add(deviceName);
deviceAddressArray.add(deviceHardwareAddress);
btArrayAdapter.notifyDataSetChanged();
}
}
};
protected void onDestroy() {
super.onDestroy();
// Don't forget to unregister the ACTION_FOUND receiver.
unregisterReceiver(receiver);
}
For apps targeting Android 11 or lower, calling BluetoothAdapter#startDiscovery() requires the Manifest.permission#BLUETOOTH_ADMIN permission which can be gained with a simple manifest tag.
For apps targeting API Level 31 or higher, this requires the Manifest.permission#BLUETOOTH_SCAN permission.
In addition, this requires either the Manifest.permission#ACCESS_FINE_LOCATION permission or a strong assertion that you will never derive the physical location of the device.
A permission can be gained with the following code:
getActivity().requestPermissions(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION},
YOUR_REQUEST_LOCATION_PERMISSION_CODE);
For more infos: https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#startDiscovery()
I'm learning about bluetooth apps and the first sample I've come across, seems to be well documented but I cannot for the life of me get it to reproduce the "Search Devices" part, any help would be greatly appreciated.
public class MainActivity extends AppCompatActivity {
private Button onBtn, offBtn, listBtn, findBtn;
private TextView text;
private ListView myListView;
// Bluetooth global variables
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter myBluetoothAdapter;
public Set<BluetoothDevice> pairedDevices;
private ArrayAdapter<String> BTArrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(myBluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"Your device does not support Bluetooth",
Toast.LENGTH_LONG).show();
}
else
{
text = (TextView) findViewById(R.id.text);
onBtn = (Button)findViewById(R.id.turnOn);
offBtn = (Button)findViewById(R.id.turnOff);
listBtn = (Button)findViewById(R.id.paired);
findBtn = (Button)findViewById(R.id.search);
myListView = (ListView)findViewById(R.id.listView1);
// create the arrayAdapter that contains the bluetooth d evices, and set it to the ListView
BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
myListView.setAdapter(BTArrayAdapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String selectedFromList =(String) (myListView.getItemAtPosition(i));
Toast.makeText(getApplicationContext(),"Bluetooth remote device : " + selectedFromList,
Toast.LENGTH_LONG).show();
}
});
}
} // onCreate
public void on(View view){
if (!myBluetoothAdapter.isEnabled()) {
Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOnIntent, REQUEST_ENABLE_BT);
Toast.makeText(getApplicationContext(),"Bluetooth turned on" ,
Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(getApplicationContext(),"Bluetooth is already on",
Toast.LENGTH_LONG).show();
}
}
public void off(View view){
myBluetoothAdapter.disable();
text.setText("Status: Disconnected");
Toast.makeText(getApplicationContext(),"Bluetooth turned off",
Toast.LENGTH_LONG).show();
}
public void list(View view){
// get paired devices
pairedDevices = myBluetoothAdapter.getBondedDevices();
// put it's one to the adapter
for(BluetoothDevice device : pairedDevices)
BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());
Toast.makeText(getApplicationContext(),"Show Paired Devices",
Toast.LENGTH_SHORT).show();
}
final BroadcastReceiver bReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
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 the MAC address of the object to the arrayAdapter
BTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
BTArrayAdapter.notifyDataSetChanged();
}
}
};
public void find(View view) {
if (myBluetoothAdapter.isDiscovering()) {
// the button is pressed when it discovers, so cancel the discovery
Toast.makeText(getApplicationContext(),"Bluetooth cancelled discovery" ,
Toast.LENGTH_LONG).show();
myBluetoothAdapter.cancelDiscovery();
} else {
BTArrayAdapter.clear();
Toast.makeText(getApplicationContext(),"Bluetooth discovery started" ,
Toast.LENGTH_LONG).show();
myBluetoothAdapter.startDiscovery();
registerReceiver(bReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
Using a Oneplus3 & 2 to test this, and neither device can find the other, unless already paired with each other. I want to see if I can search and get the device to populate in a list like the paired devices already do.
If there's anything else you need me to put in let me know, hope you don't mind taking the time to help out with this one!
You need to add one of the following permission to your Manifest.xml to find devices:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
or
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
If you are working on API 23 and higher you must ensure this permission is granted because it is a dangerous level permission.
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app
See this guide to request permission(s).
I'm trying to make an android app which has some issues about Bluetooth. I simply enable Bluetooth, find devices, connect one of the devices, send & receive data. First thing is done. But in second, there are some problems. I make a Broadcast Receiver to discover devices nearby my phone. But OnReceive method doesn't get called. The weird thing is, it was getting called at first and I was able to see devices nearby. Then something that I cannot figure out happened and now OnReceive method doesn't get called. I've searched topics about these but none of them could solve my problem. MyDevice and MyAdapter are my own classes to show Bluetooth devices in listview with my own layout. Here is my code:
public class FoundDevicesActivity extends AppCompatActivity {
BluetoothAdapter bluetoothAdapter;
ListView foundedDevicesListView;
MyDeviceAdapter deviceAdapter;
List<MyDevice> foundedDevicesList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_found_devices);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
foundedDevicesListView = (ListView) findViewById(R.id.foundDevicesListview);
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(receiver, filter);
bluetoothAdapter.startDiscovery();
deviceAdapter = new MyDeviceAdapter(this, foundedDevicesList);
foundedDevicesListView.setAdapter(deviceAdapter);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Toast.makeText(FoundDevicesActivity.this, "Discovery is started !!", Toast.LENGTH_SHORT).show();
Log.d("Found Devices Activity", "Discovery is started !!");
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
MyDevice dvc = new MyDevice();
if (device.getName().equals(null)) {
dvc.name = "UNDEFINED NAME";
} else {
dvc.name = device.getName();
}
if(device.getAddress().equals(null)) {
dvc.address = "UNDEFINED ADDRESS";
} else {
dvc.address = device.getAddress();
}
foundedDevicesList.add(dvc);
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
bluetoothAdapter.cancelDiscovery();
Toast.makeText(FoundDevicesActivity.this, "Discovery is finished !!", Toast.LENGTH_SHORT).show();
Log.d("Found Devices Activity", "Discovery is finished !!");
}
}
};
}
Any idea ?
I have read plenty of tutorial and posts here on SO regarding the use of WakeLock and WifiLock, but still didn't get to a solution of my issue.
I'm writing an app that has, when you start it, the only effect of creating and starting a (foreground) service. This service run two threads that are an UDP broadcast listener (using java.io) and a TCP server (using java.nio). In the onCreate of the service I acquire a wakelock and a wifilock, and I release them in the onDestroy.
Everything works fine as far as the phone is awake, but when the display goes off the UDP broadcast receiver stops receiving broadcast messages, and will not receive any until I switch on again the display. Practically, the locks are not working at all and there is no difference in put them...where am I wrong? I'm sure I'm doing something stupid somewhere, but can't find it by myself.
Here is some code:
This is what Activity does:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onlyStartService = true;
}#Override
protected void onStart() {
super.onStart();
Intent bIntent = new Intent(this, FatLinkService.class);
getApplicationContext().startService(bIntent);
getApplicationContext().bindService(bIntent, flConnection, BIND_AUTO_CREATE);
}
// service connection to bind idle service
private ServiceConnection flConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
linkService.MyLinkBinder flBinder = (LinkService.MylinkBinder) binder;
flServiceInstance = flBinder.getService();
if (onlyStartService) {
condLog("Service bound and finishing activity...");
finish();
}
}
public void onServiceDisconnected(ComponentName className) {
flServiceInstance = null;
}
};
#Override
protected void onStop() {
super.onStop();
if (fatFinish) {
Intent bIntent = new Intent(this, FatLinkService.class);
flServiceInstance.stopServices();
flServiceInstance.stopForeground(true);
flServiceInstance.stopService(bIntent);
condLog("Service stop and unbound");
flServiceInstance = null;
}
getApplicationContext().unbindService(flConnection);
}
This is how service is:
public class LinkService extends Service {
InetAddress iaIpAddr, iaNetMask, iaBroadcast;
private final IBinder mBinder = new MyLinkBinder();
private linklistenBroadcast flBroadServer = null;
private linkTCPServer flTCPServer = null;
private linkUDPClient flBroadClient = null;
List<String> tokens = new ArrayList<String>();
private PowerManager.WakeLock wakeLock;
private WifiManager.WifiLock wifiLock;
public class MylLinkBinder extends Binder {
lLinkService getService() { return LinkService.this; }
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
getLocks();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
instantiateServices();
// notifies presence to other fat devices
condLog("Service notifying fat presence...");
flBroadClient = new LinkUDPClient();
flBroadClient.startSending(LinkProtocolConstants.BRCMD_PRESENCE + String.valueOf(LinkProtocolConstants.tcpPort), iaBroadcast, LinkProtocolConstants.brPort);
return START_STICKY;
}
public void getLocks() {
// acquire a WakeLock to keep the CPU running
condLog("Acquiring power lock");
WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
wifiLock.acquire();
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
}
public void stopServices() {
if (flTCPServer != null)
flTCPServer.stopServer();
if (flBroadServer != null)
flBroadServer.stopSelf();
}
private void instantiateServices() {
populateAddresses(); // just obtain iaIpAddr
if (flTCPServer == null) {
condLog("Instantiating TCP server");
flTCPServer = new LinkTCPServer(iaIpAddr, FatLinkProtocolConstants.tcpPort);
flTCPServer.execute();
}
if (flBroadServer == null) {
condLog("Instantiating UDP broadcast server");
Intent notifyIntent = new Intent(this, LinkMain.class); // this is the main Activity class
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
notifyIntent.setAction("FROM_NOTIFICATION");
PendingIntent notifyPIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0);
Notification fixNotification = new Notification.Builder(getApplicationContext())
.setContentTitle("Link")
.setSmallIcon(R.mipmap.imgLink)
.setContentIntent(notifyPIntent)
.build();
startForeground(1234, fixNotification);
flBroadServer = new LinklistenBroadcast();
flBroadServer.start();
}
}
private final class LinklistenBroadcast extends Thread {
private boolean bStopSelf = false;
DatagramSocket socket;
public void stopSelf() {
bStopSelf = true;
socket.close();
}
#Override
public void run() {
condLog( "Listening broadcast thread started");
bStopSelf = false;
try {
//Keep a socket open to listen to all the UDP trafic that is destinated for this port
socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.setSoTimeout(LinkGeneric.BR_SOTIMEOUT_MILS);
socket.setBroadcast(true);
socket.bind(new InetSocketAddress(InetAddress.getByName("0.0.0.0"), FatLinkProtocolConstants.brPort));
while (true) {
condLog("Ready to receive broadcast packets...");
//Receive a packet
byte[] recvBuf = new byte[1500];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
try {
socket.receive(packet);
} catch (InterruptedIOException sException) {
condLog(sockExcept.toString());
break;
} catch (SocketException sockExcept) {
condLog(sockExcept.toString());
}
if (bStopSelf) {
condLog("Broadcast server stopped...");
break;
}
int len = packet.getLength();
String datarecvd = new String(packet.getData()).trim();
//datarecvd = datarecvd.substring(0, len);
//Packet received
String message = new String(packet.getData()).trim();
condLog("<<< broadcast packet received from: " + packet.getAddress().getHostAddress() + " on port: " + packet.getPort() + ", message: " + message);
if (packet.getAddress().equals(iaIpAddr)) {
condLog("Ooops, it's me! discarding packet...");
continue;
}
else
condLog("<<< Packet received; data size: " + len + " bytes, data: " + datarecvd);
//See if the packet holds the right command (message)
// protocol decode
// here do some tuff
} catch (IOException ex) {
condLog(ex.toString());
}
if (socket.isBound()) {
condLog( "Closing socket");
socket.close();
}
condLog( "UDP server thread end.");
flTCPServer = null;
flBroadServer = null;
}
public boolean isThreadRunning() {
return !bStopSelf;
};
}
// Utility functions
public boolean checkBroadcastConnection (DatagramSocket socket, int timeOutcycles) {
int tries = 0;
while (!socket.isConnected()) {
tries++;
if (tries >= timeOutcycles)
return false;
}
return true;
}
#Override
public void onDestroy() {
super.onDestroy();
if (wakeLock != null) {
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
if (wifiLock != null) {
if (wifiLock.isHeld()) {
wifiLock.release();
}
}
}
}
And, finally, here is the manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxxxxx.ink" >
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:allowBackup="true"
android:icon="#mipmap/imgLinkmascotte"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".LinkMain"
android:label="#string/app_name"
android:theme="#android:style/Theme.Translucent.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LinkService" />
</application>
</manifest>
I have read this, and I have the doubt the problem is the same but it is actually happening to me on all the phone I have tried (galaxy Tab 7.1, galaxy tag 10, Galaxy SIII, Galaxy Note 3 Neo, Galaxy SIII mini) with android releases from 4.0 to 4.4.
I have already tried the solution posted here, but anything changed (again...it is a bit frustrating).
I have even tried to set the "Keep wifi option in standby" to "Always" in all the phones I've tried, but still nothing.
I have studied the WakeFulIntentService class, that is supposed to work as everybody is saying that it is, but I can't see any significant different in my code.
I really hope someone can help me, I'm really stuck on this since last week.
EDIT: following the waqaslam answer, I have checked on a device that has "Wifi optimisation" option in Wifi-Advaced settings, and it actually works as soon as I uncked the option. So, now, the problem become: can I disable Wifi optimisation in devices that haven't that option shown in the advanced menu? as I wrote below in my comment, this seems not to be related to android release, as I have two devices (both Samsung) with 4.4.2 and they are not showing the option.
New EDIT: from the edited waqaslam answer, I have tried to add multicastlock to my service, but again anything changed. This is getting annoying, there's hardly something easy and clear to do with android.
thank you very much
C.
I think the problem is not with the WakeLocks but the Wi-Fi settings.
In newer versions of android, there's an additional setting in Settings -> Wi-Fi -> Advanced called Wi-Fi optimization, which (if turned-on) disables all the low priority communications (like listening to UDP broadcasts) when the display is off.
Disabling the option should allow your device to listen UDP broadcasts even when the display is switched-off.
You may also use WifiManager.MulticastLock in order to acquire WiFi lock that should listen to these special broadcasts when screen is switched-off.
WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("lockWiFiMulticast");
lock.setReferenceCounted(false);
lock.acquire();
and when done with the lock, then call:
lock.release();
Also, don't forget to add the following permission to your manifest:
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
For more info, you may read this.
Writing that just to mark the post as answered. I finally realilzed that there is no solution, or at least there is no solution working well on "all" the phones with "all" the android distribution (or at least from JB).
I have solved my personal issue just revisiting the concept of my app, considering that:
- Sending UDP broadcast is always working even in idle mode
- TCP servers are not affected by WiFi optimisation.
thank you all for the help and suggestion
C.
May be the reason is this .
Starting from Android 6.0 (API level 23), Android introduces two
power-saving features that extend battery life for users by managing
how apps behave when a device is not connected to a power source. Doze
reduces battery consumption by deferring background CPU and network
activity for apps when the device is unused for long periods of time.
App Standby defers background network activity for apps with which the
user has not recently interacted
I have a very simple activity for discovering other android devices via bluetooth:
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// Get the local Bluetooth adapter
FrameLayout f = new FrameLayout(this);
setContentView(f);
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
// Get a set of currently paired devices
Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
// Request discover from BluetoothAdapter
Log.i("bluetooth", "about to start device discovery");
mBtAdapter.startDiscovery();
//start receiving stuff
mReceiver = new BluetoothReceiver();
}
The problem is that the BluetoothRecieiver class called at the end of the activity's onCreate() doesn't seem to find and devices, although I have one turned on in the vicinity when I am debugging this:
public class BluetoothReceiver extends BroadcastReceiver {
public ArrayAdapter<String> mNewDevicesArrayAdapter;
#Override
public void onReceive(Context context, Intent intent) {
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);
// If it's already paired, skip it, because it's been listed already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
Log.i("face", device.getName() + "\n" + device.getAddress());
mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
if (mNewDevicesArrayAdapter.getCount() == 0) {
Log.i("face", "found NOTHING!");
mNewDevicesArrayAdapter.add("no devices found");
}
}
}
}
Is there anything I am missing here?
I think it's because when you call registerReceiver() mReceiver is null, move mReceiver = new BluetoothReceiver(); above the first this.registerReceiver(mReceiver, filter);, also you could do something like
filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
and then call this.registerReceiver(mReceiver, filter); only one time