In service there is a receiver:
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
Service is a foreground service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
startForeground(NOT_ID, getNotification(type));
return START_STICKY;
}
Service has notification running all time. When the service is "paused" notification is ok.
Problem:
When the USB charger is unplugged (The same thing happens connected to a PC or to a normal charger.) and the test is performed on Android 9 the receiver does not capture events, connection events, for example change Wi-Fi, connect by data or lose connection.
If I plug USB in, the events detectios works ok. To see the events I am using a test interface, not logcat.
I understand that this happens because I suppose in Android 9 the system pauses the services to save battery when the device is not plugged in.
Is there any way in Android 9 that the receiver is called when the USB is unpluged?
I tested in Android 8.1 and service is not paused.
Note: I can not declare the receiver in the manifest because from Android 6 it can not be done for battery reasons.
More info: To do the tests all the activities are completely closed and only the service and the notification is showing. If some activity is visible to user receiver works ok.
Related
I want to call a method before shotdown or restart an android phone.
As they said on the official site
Broadcast Action: Device is shutting down. This is broadcast when the device is being shut down (completely turned off, not sleeping). Once the broadcast is complete, the final shutdown will proceed and all unsaved data lost. Apps will not normally need to handle this, since the foreground activity will be paused as well.
As of Build.VERSION_CODES#P this broadcast is only sent to receivers registered through Context.registerReceiver.
I am trying to wakeup my android app via nearby bluetooth devices. If I force close the app (in Android 8.0 and above), and when I bring my Android device near to a BLE device, can I get a callback or intent callback so that I can push a ForeGround service and make the app stay awake.
I tried scanning for the BLE devices nearby but when the app is force killed, the BLE scan stops and I cannot wake up the app via BLE nearby devices.
Force stop kills application totally. It won't get FCMs, alarms in AlarmManager are removed too, etc. So app processes are totally killed, and any info is removed.
Yes. On Android 8+ you can use an Intent-based scan tied to a BroadcastReceiver to wake up an app based on a BLE advertisement detection. The BroadcastReceiver will only be allowed to run for a few seconds, but you can use this time to start an immediate JobService that can run for up to 10 minutes. This is exactly what the Android Beacon Library does out-of-the-box to allow background detections. You may also be able to use a foreground service to run longer than 10 minutes in the background. Read more about the options here.
ScanSettings settings = (new ScanSettings.Builder().setScanMode(
ScanSettings.SCAN_MODE_LOW_POWER)).build();
// Make a scan filter matching the beacons I care about
List<ScanFilter> filters = getScanFilters();
BluetoothManager bluetoothManager =
(BluetoothManager) mContext.getApplicationContext()
.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
Intent intent = new Intent(mContext, MyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, pendingIntent);
The above code will set an Intent to fire that will trigger a call to a class called MyBroadcastReceiver when a matching bluetooth device is detected. You can then fetch the scan data like this:
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int bleCallbackType = intent.getIntExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, -1);
if (bleCallbackType != -1) {
Log.d(TAG, "Passive background scan callback type: "+bleCallbackType);
ArrayList<ScanResult> scanResults = intent.getParcelableArrayListExtra(
BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT);
// Do something with your ScanResult list here.
// These contain the data of your matching BLE advertising packets
}
}
}
You can use Geofence to wake the app. Geofence will survive 'Force stop' of the application.
I have an app which interacts with a USB OTG device:
When a USB device connects, a helper activity is started to display the Android confirmation dialog. This is done via an IntentFilter in the manifest.
The helper activity starts a service is started by sending it an app-specific intent.
The service’s onCreate() method populates an IntentFilter, adding the actions to which the service should react when running, including UsbManager.ACTION_USB_DEVICE_DETACHED. Adding extra debug output tells me the method runs when I expect it to, i.e. the IntentFilter is populated when I register the receiver.
The service’s onStartCommand() method calls an internal method which registers the BroadcastReceiver for the intent filter (if the service was started with the start intent, and has the necessary permissions—else the service terminates).
When the receiver receives UsbManager.ACTION_USB_DEVICE_DETACHED and the device reported is the one that is currently connected, it stops the service.
There is also a main activity, which is not involved in handling the USB device.
The service also gets called for other reasons, notably when a charger is connected. In this case the service looks for a Bluetooth device (if a USB device is already connected, indicated by a member of the service instance being non-null, this is skipped and the service exits).
Now, if I plug in the USB device, I get the confirmation and the service starts, and when I unplug the device, the service stops again. So far, so good.
However, in some cases the service keeps running even after the device is unplugged. I have noticed this always happens when the main activity was open when I connected the device. Logs show me that the service never receives the UsbManager.ACTION_USB_DEVICE_DETACHED broadcast.
While doing further tests (open main activity and navigate away from it before connecting the device), I found evidence that there may be two instances of the service running for some reason.
What is happening here, and how can I reliably detect that the USB device was disconnected?
This behavior appears to be caused by two factors:
As described above, the service gets started not only when a USB device connects, but also on other events, such as the device being connected to an AC adapter or the main activity being opened. In these cases it will look for a Bluetooth device (“autoconnect”) and exit if none is found, or if a USB device is already connected.
As a result, when autoconnect is enabled, opening the main activity will always start the first service instance. If a USB device connects after that, we may apparently have two service instances running. I suspect the disconnect broadcast may get picked up by the wrong instance.
If I disable autoconnect, the service does receive the disconnection event but ignores it, as the devices are not considered equal. Yet log output shows that the device path for both devices is the same. Further analysis revealed that I had simply used != to compare the two UsbDevice instances, which fails to catch two different class instances referring to the same device.
So we need to do two things:
Use UsbDevice#equals() rather than the equality operator for comparison.
Prevent multiple instances of the service from running. Ensure the service exits when no device is found, and Intents are delivered to the existing instance rather than starting a new one.
I have created an android application using android studio API 21 to scan & connect to a BLE device and subscribe to receive advertised data. This works great, but now I would like to do this automatically without having the user to manually run the android application. Is there a way for my android device to know when it is in range of the BLE device and to automatically connect and receive data if available? I'm just a little confused as to what code is needed in the Broadcast receiver class and does the Broadcast receiver class need to be in a service?
AFAIK, there is no such system broadcast for notifying BLE device found.
I think you will have to do it by yourself with a service
To scan BLE devices in background, you will have to run the scanning in a service.
Few requirements you may want.
Start the service on app start
This is the starting point of your service first run.
Just call startService in your activity onCreate.
Keep service running
See, how to keep service running
Stop BLE scanning on bluetooth disabled
It is meaningless to keep scanning while bluetooth disabled by user.
So, you may want this check. See, detecting bluetooth change
Start the service on device boot
See, start service at boot
Implement BLE scan in service
Move all the code from your scanning activity (or fragment) to the service. Something like,
BLEScanningService extends Service {
#Override
public int onStartCommand (Intent intent, int flags, int startId) {
if (/*Bluetooth is available*/) {
/*
Do BLE scan
*/
} else {
// Stop BLE scanning and stop this service
}
}
}
Then, your will have BLE scanning service always running in background :)
Maybe you may also want to broadcast some event from the service so that app UI and notification can update correspondingly.
How receive device shutdown? I mean any broadcast receiver for get device shutdown state.
User press shutdown button on device. Choose shutdown -> Recevier get it.
Any ideas about it?
public static final String ACTION_SHUTDOWN
Since: API Level 4
Broadcast Action: Device is shutting down. This is broadcast when the device is being shut down (completely turned off, not sleeping). Once the broadcast is complete, the final shutdown will proceed and all unsaved data lost. Apps will not normally need to handle this, since the foreground activity will be paused as well.
This is a protected intent that can only be sent by the system.
Constant Value: "android.intent.action.ACTION_SHUTDOWN"