I have the following service declared in the manifest:
<application
...
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.android.test.TestService"
android:process=":Remote"
android:permission="android.permission.WAKE_LOCK"/>
<receiver android:name="com.example.android.test.TestService">
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
</intent-filter>
</receiver>
</application>
and this is the Service class
public class TestService extends Service implements SensorEventListener {
public class BatteryReceiver_andFileChecker extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//TODO
}
// constructor
public BatteryReceiver_andFileChecker(){
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
//TODO
return START_STICKY;
}
#SuppressLint("WakelockTimeout")
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Logging service started new", Toast.LENGTH_SHORT).show();
//Acquire wake lock
PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WLTAG:MyWakelockTag");
wakeLock.acquire();
//Display notification
this.notIntent = new Intent(this, MainActivity.class);
this.pendingIntent = PendingIntent.getActivity(this, 0, this.notIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, this.channelID).setSmallIcon(R.drawable.ic_launcher_background).setContentTitle("Test").setContentText("Sensor is recording").setPriority(NotificationCompat.PRIORITY_DEFAULT).setContentIntent(this.pendingIntent);
startForeground(this.NOTIFICATION, builder.build());
//BatteryCheck
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
mReceiver = new BatteryReceiver_andFileChecker();
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
super.onDestroy();
//cancel notification
stopForeground(true);
//Unregister battery receiver
unregisterReceiver(mReceiver);
//release wakeLock
wakeLock.release();
//Stop Service
stopSelf();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
// super.onBind(intent);
return null;
}
#Override
public void onSensorChanged(SensorEvent event) {
//TODO
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
And this services is created and terminated on two different "onclick" functions from the MainActivity
public class MainActivity extends AppCompatActivity {
...
public void onClickStart(View v) {
// Start Service
this.intent = new Intent(getApplicationContext(), TestService.class);
this.intent.putExtra("foo",foo);
startService(this.intent);
}
public void onClickStopAcquisition(View v) {
// Stop Service
stopService(this.intent);
}
}
This code runs as expecten in Android 6.0.1 and does not work on Android 10...
When I debug de app, no errors are fired when pressed the Start and Stop buttons in both OS, nevertheless, android 6.0.1 fires the service and android 10 does not...
Any reason why?
Just to keep in mind when understanding my implementation, my intention is to make a service which keeps running and doing stuff even if the user is not active in the application. Since I implementen the SensorEventListener to record data from sensors, my intention is to record data while the user might be interacting with the phone or even doing nothing (after he presses the power button of the phone, the service keeps running acquiring data and performing actions)
Then, the service should be terminated either when the user clicks the stop button or either when the MainActivity is terminated.
Thank you!
i guess you should read more about background services and broadcast in android API 26 or higher
From the official documentation available here
If an app registers to receive broadcasts, the app's receiver consumes resources every time the broadcast is sent. This can cause problems if too many apps register to receive broadcasts based on system events; a system event that triggers a broadcast can cause all of those apps to consume resources in rapid succession, impairing the user experience. To mitigate this problem, Android 7.0 (API level 24) placed limitations on broadcasts, as described in Background Optimization. Android 8.0 (API level 26) makes these limitations more stringent.
Apps that target Android 8.0 or higher can no longer register
broadcast receivers for implicit broadcasts in their manifest. An
implicit broadcast is a broadcast that does not target that app
specifically. For example, ACTION_PACKAGE_REPLACED is an implicit
broadcast, since it is sent to all registered listeners, letting them
know that some package on the device was replaced. However,
ACTION_MY_PACKAGE_REPLACED is not an implicit broadcast, since it is
sent only to the app whose package was replaced, no matter how many
other apps have registered listeners for that broadcast. Apps can
continue to register for explicit broadcasts in their manifests. Apps
can use Context.registerReceiver() at runtime to register a receiver
for any broadcast, whether implicit or explicit.
Broadcasts that require a signature permission are exempted from this restriction, since these broadcasts are only sent to apps that are signed with the same certificate, not to all the apps on the device
you should work with JobScheduler
Important Update
to answer your question in comment : use WorkManager for deferrable background tasks.
This library is backward compatible
It use JobScheduler,FirebaseJobDispatcher or AlarmManager
No Need to depend on play service library.
Recommended by Google for deferrable background work.
Can use features like chaining, constraints etc.
Related
I implemented an BroadcastReceiver for Android-Platform to detect whenether the Devices Battery is being Charged or not. Unfortunately, it doesn't seem to work on my Device which has Android 10 installed (Android 10 is my minimum requirement for the App).
I need this BroadcastReceiver to be triggered even if the App is not running. Therefore an Implicit broadcast would be an excellent choice instead of register an BroadcastReceiver while the App is running.
Permissions set within "AndoirdManifest.xml"
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
My PowerConnectedBroadcastReceiver looks like this:
[BroadcastReceiver(Enabled = true, Exported = true)]
[IntentFilter(new[] { Intent.ActionPowerConnected, Intent.ActionPowerDisconnected, Intent.ActionDockEvent, Intent.ActionBatteryChanged }, Priority = (int)IntentFilterPriority.HighPriority)]
public class PowerConnectedBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Console.WriteLine($"PowerConnectedBroadcastReceiver received an intent: {intent}");
}
}
What am I doing wrong?
Any Kind of advise would be appreciated.
From Broadcast Receivers docs
Apps that target Android 8.0 (API level 26) or higher may not statically register for an implicit broadcast. Apps may still statically register for an explicit broadcast. There is a small list of implicit broadcasts that are exempt from this restriction. These exceptions are described in the Implicit Broadcast Exceptions guide in the Android documentation. Apps that are interested in implicit broadcasts must do so dynamically using the RegisterReceiver method. This is described next.
Dynamic registration
[BroadcastReceiver(Enabled = true, Exported = true)]
public class PowerConnectedBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Console.WriteLine($"PowerConnectedBroadcastReceiver received an intent: {intent}");
}
}
PowerConnectedBroadcastReceiver receiver;
IntentFilter intentFilter;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
receiver = new();
intentFilter = new(Intent.ActionPowerConnected);
intentFilter.AddAction(Intent.ActionPowerDisconnected);
intentFilter.AddAction(Intent.ActionDockEvent);
intentFilter.AddAction(Intent.ActionBatteryChanged);
intentFilter.Priority = (int)IntentFilterPriority.HighPriority;
}
protected override void OnResume()
{
base.OnResume();
RegisterReceiver(receiver, intentFilter);
}
protected override void OnPause()
{
UnregisterReceiver(receiver);
base.OnPause();
}
Edit
As the broadcast receiver is managed inside the activity it has the life cycle of the activity, if you want it to keep running for some reasons even if the app is not running, then i believe you should register/unregister it inside a foreground service.
Related questions:
Android keep BroadcastReceiver in background
How to keep broadcast receiver running in background?
Extra
Failing on un-register the broadcast receiver when the activity is terminated, will result in a leak. UnregisterReceiver() is called in OnPause rather than OnDestry() because the latter is not guaranteed to be called.
Android Activity onDestroy() is not always called and if called only part of the code is executed
I have developed small app to detect changes in network like on, off or connection change Wifi to Ethernet, whenever app closed or running in all cases.
Provided code working for me upto Nuget 7, when testing app in Oreo 8 background services not working when app terminated.
How can I get it work in Oreo?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
Intent vpnServiceIntent = new Intent(getBaseContext(), MyService.class);
startForegroundService(vpnServiceIntent);}}
WifiReceiver.java file
public class WifiReceiver extends BroadcastReceiver {
static final String CONNECTIVITY_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (CONNECTIVITY_CHANGE_ACTION.equals(action)) {
if (!isConnected()) {
if (context != null) {
Toast.makeText(context," Not connected...",Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(context,"connected...",Toast.LENGTH_LONG).show();
}
}
}
}
MySevice.java file
public class MyService extends Service
{
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
WifiReceiver receiver =new WifiReceiver();
registerReceiver(receiver,filter);
return START_STICKY;
}
}
Manifest.xml file
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
<receiver android:name=".WifiReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<service android:name=".MyService" />
</application>
Note: If I call startForeground(101, notification); in onCreate of MyService class, my above code is working but showing permanent notification icon on top most status bar, that I don't want at all.
since Android 8.0 (API level 26) it is basically impossible to run background service while app is not visible because of Battery optimizations and security reasons.
It sucks, many useful apps can not run and work normally.
They recommend to use ForegroundService which requires to show notification.
It would be almost okay, but these ForegroundServices also gets killed after some time.
To avoid killing them you need to make BatteryOptimization prompt so user would let service running in background without killing.
But it is not over yet... Services is still being killed on most of Manufactures like Samsung, Huawei and so on because they has they own badly implemented BatteryOptimizations running parallel with native one... and if user want some app avoid to be killed while running in background it has to go long way to settings find provider specific settings and let app run....
here is an example how to change these provider specific settings on Slack
I think it is worst thing that happened to Android.....
I'm posing this as Q&A style because I found this idea working. And it's a fix to the hard problem to crack for beginners with Android.
Google has deprecated registering Broadcast Receiver into manifest like this below from API Level 26+ ( Except Some )
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
But, If one wants to receive particular device state changes like Internet Connectivity Changes (Which isn't allowed) while the app is in background and if it's important for any feature of his application, what should he do?
When I was going through the documentation, My eyes got stuck here :
Context-registered receivers receive broadcasts as long as their registering context is valid. For an example, if you register within
an Activity context, you receive broadcasts as long as the activity is
not destroyed. If you register with the Application context, you
receive broadcasts as long as the app is running.
That practically means if I can hold a Context, the broadcast-receiver registered with it will run in the background.
For doing that, a Service will be the best practice.
This is below code for a STICKY_SERVICE which is started again after killed and thus the context remains valid.
AlwaysOnService.class
package app.exploitr.auto;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class AlwaysOnService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
registerReceiver(new ClickReceiver(), new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
return Service.START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onLowMemory() { // rem this if you want it always----
stopSelf();
super.onLowMemory();
}
}
Now, the receiver which actually does things :
ClickReceiver.class
package app.exploitr.auto;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import java.util.Objects;
public class ClickReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
switch (Objects.requireNonNull(intent.getAction())) {
case AutoJob.NOTIFICATION_CANCEL_TAG:
System.out.println("Not related");
break;
case AutoJob.LOGIN_CANCEL_TAG:
System.out.println("Not related");
break;
case "android.net.conn.CONNECTIVITY_CHANGE":
System.out.println("Oops! It works...");
break;
}
}
}
Launch Code From Any Activity Class
private void setUpBackOffWork() {
if (DataMan.getInstance(getBaseContext()).getPeriodic()) {
AutoJob.schedulePeriodic();
//Not related
}
if (DataMan.getInstance(getBaseContext()).getPureAutoLogin()) {
startService(new Intent(this, AlwaysOnService.class));
}
}
So my target was to Login into my isp automatically when I turn up my android's WiFi, and the code works smooth. It doesn't fail ever (It's running for 7 hours and 37 minutes till now and working well | not across reboots).
To keep the receiver running across reboots, try manifest registerable BOOT_COMPLETED actions. It works just like the old one.
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
Update 1
Now, as Google took one step to limit background execution & as a result you've also to make the service a foreground service. So, the procedure goes below.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, new Intent(THIS_SERVICE_CLASS_NAME.this, ACTIVITY_TO_TARGET.class), 0);
/*Handle Android O Notifs as they need channel when targeting 28th SDK*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel(
"download_check_channel_id",
"Channel name",
NotificationManager.IMPORTANCE_LOW);
if (notificationManager != null) {
notificationManager.createNotificationChannel(notificationChannel);
}
builder = new Notification.Builder(this.getBaseContext(), notificationChannel.getId())
.setContentTitle("Hi! I'm service")
.setContentIntent(pendingIntent)
.setOngoing(true);
notification = builder.build();
startForeground("StackOverflow".length(), notification);
}
return START_STICKY;
}
This also applies to Xamarin Android. The Play Store demanded to upgrade my apps's SDK to 8.0 Oreo, and a bunch of stuff stopped working on it.
Microsoft's documentation on Broadcast Receivers is quite confusing:
Apps that target Android 8.0 (API level 26) or higher may not statically register for an implicit broadcast. Apps may still statically register for an explicit broadcast. There is a small list of implicit broadcasts that are exempt from this restriction.
Even Google's official docs are quite inscrutable.
On Xamarin Android it used to be enough to follow this pattern:
[BroadcastReceiver]
[IntentFilter(new string[] {MyReceiver.MyAction})]
public class MyReceiver : BroadcastReceiver
{
public const String MyAction = "com.mytest.services.MyReceiver.MyAction";
public override void OnReceive (Context context, Intent intent)
{
// ...
}
}
The IntentFilter annotation instructs the compiler to add the receiver and intent filters registrations to the Manifest file during the build process. But from target SDKs v8.0 (Oreo/API 26) and above Android ignores these configurations on Manifest (except some system implicit actions). So this means that the IntentFilter annotations only works for those exceptions, and to make your broadcast receivers receive broadcasts it is required to register them on execution time:
#if DEBUG
[Application(Debuggable=true)]
#else
[Application(Debuggable=false)]
#endif
public class MyApplication: Application
{
public override void OnCreate ()
{
base.OnCreate ();
Context.RegisterReceiver(new MyReceiver(), new IntentFilter(MyReceiver.MyAciton));
}
}
It is also possible to register a receiver only for the lifecycle of an Activity, as explained by #Toaster. You can keep sending broadcasts normally:
// ...
ApplicationContext.SendBroadcast(new Intent(MyReceiver.MyAction));
// ...
I'm working on an application that uses Android's DownloadManager to download files. In my AndroidManifest.xml I register a receiver to listen for downloads completing like this
<receiver android:name=".download.DownloadCompleteBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
In the broadcast receiver's onReceive method, I launch an IntentService to perform some post-processing on the downloaded file before it's ready for use. Here's what that code looks like:
public class DownloadCompleteBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
final long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L);
context.startService(
new Intent(context, DownloadService.class)
.putExtra("downloadId", downloadId));
} catch (Throwable t) {
Log.i("Yo", Log.getStackTraceString(t));
}
}
The DownloadService class looks something like this
public class DownloadService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
// Some processing logic
...
// Send processing complete
sendBroadcast(new Intent("com.example.package.DownloadService:PROCESSING_COMPLETE"));
}
}
This service is registered in my AndroidManifest.xml like this
<service android:name=".download.DownloadService" android:process=":Downloads"/>
Finally, I have an activity that listens for that PROCESSING_COMPLETE broadcast. That code looks like this
public class MyActivity extends AppCompatActivity {
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Update some UI
}
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter("com.example.package.DownloadService:PROCESSING_COMPLETE"));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
}
And finally, the issues:
1) I am seeing delays (as much as 20 seconds) between when the download manager completes a download and when my registered BroadcastReceiver receives the download complete notifications. Is this normal? This issue/question is not as big of a concern as the next two.
2) I am seeing delays (as much as 2 minutes) between when my BroadcastReceiver calls startService() and when DownloadService.onCreate() is called. What's going on here? Sometimes my devices will show an ANR dialog asking me to wait for the app or force close it. I know I declared the service to run in a separate process, and there's some lead time to create the process and launch the service, however I'm seeing similar delays in successive runs when the process is already created. Moving DownloadService to the default process doesn't appear to improve the load time, however I believe the best practice is to run such a service in it's own process to keep it from being terminated should the app crash.
3) I am seeing delays (as much as 2 minutes) between when the DownloadService sends the PROCESSING_COMPETE broadcast and when my activity actually receives it. This is without leaving the activity then coming back (an onPause() and onResume()cycle), though my code handles unregistering and re-registering. What's going on here? I'm testing on a Galaxy S7 running 6.0. I hardly have any apps installed/running on this device that I could image would be slowing down broadcasts. Another interesting observation is that if I send multiple broadcasts, they're all delivered at the same time after the long delay.
Thanks for the help in advance!
I have tried various ways to achieve this, but my service eventually gets killed.
I want to use AlarmManager to trigger a class every one hour. Even if the device is sleeping, it should sent a flashing LED alert, vibration or sound. In any case, it should run forever.
I have noticed that Whatsapp is always running, even though I kill all the running apps and clear the memory, put the device to sleep, and still Whatsapp receive messages and alerts me. How are they doing it? I want to do the same with my app.
NOTE: NOW THIS ANSWER IS ONLY VALID FOR ANDROID 7 AND BELOW. SINCE ANDROID 8 GOOGLE HAS CHANGED HOW BACKGROUND TASKS ARE HANDLED
Since I posted this question, I have implemented two different approaches to this solution into multiple apps.
APPROACH 1
This extract is from an app where I use push notifications, which need instant wake up calls for the device. Here what I do is
use WAKE_LOCK permission and
use a Wakelocker abstract class
use it in an Activity as needed:
Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
WakeLocker class:
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context context) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, "WakeLock");
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
}
Activity class example:
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Waking up mobile if it is sleeping
WakeLocker.acquire(getApplicationContext());
// do something
WakeLocker.release();
}
APPROACH 2
Best when you want to give Android control over wake up, and can live with periodically waking up your code. Simply use an AlarmManager to invoke a Service class at regular intervals. Here is some code from my LifeLog24 app:
MainActivity
Intent ll24 = new Intent(context, AlarmReceiverLifeLog.class);
PendingIntent recurringLl24 = PendingIntent.getBroadcast(context, 0, ll24, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC_WAKEUP, first_log.getTime(), AlarmManager.INTERVAL_HOUR, recurringLl24); // Log repetition
Alarm Class
public class AlarmReceiverLifeLog extends BroadcastReceiver {
private static final String TAG = "LL24";
static Context context;
#Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "Alarm for LifeLog...");
Intent ll24Service = new Intent(context, LifeLogService.class);
context.startService(ll24Service);
}
}
and LifeLogService.class is where I do my stuff. Alarm wakes up every hour in this case and triggers the BroadcastReceiver which in return runs the service. There is more to it, to make sure service is not run twice and so on, but you get the point how it is done. And AlarmManager is actually the best way to do it since you don't worry about battery usage, etc. and Android takes care of waking up your Service at regular intervals.
It is very simple.
steps:
1.create a Service class.
2.create a BroadcastReceiver class
3.call BroadReceiver in onDestroy method of service
4.In onReceive method of BroadReceiver class start service once again.
Here's the code
Manifest file:`
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".utilities.NotificationService"
android:enabled="true">
</service>
<receiver
android:name=".utilities.RestartService"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="RestartService" />
</intent-filter>
</receiver>
</application>
`
Service class
public class NotificationService extends Service {
public NotificationService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Intent restartService = new Intent("RestartService");
sendBroadcast(restartService);
}
}
BroadcastReceiver class
public class RestartService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context,NotificationService.class));
}
}
Follow these easy steps to keep servce alive forever in android device.
1. Call a service by using alarm manager.
2. return START_STICKY in onStart method.
3. In on destroy call the alarm manager and restart service by using startService method.
4.(Optional)Repeat the point number 3 in onTaskRemoved method.
Request partial WakeLock.
<uses-permission android:name="android.permission.WAKE_LOCK" />
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();
onStartCommand retrun START_STICKY :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
You can use a function startForeground(int, Notification) see here and here
A started service can use the startForeground(int, Notification) API
to put the service in a foreground state, where the system considers
it to be something the user is actively aware of and thus not a
candidate for killing when low on memory. (It is still theoretically
possible for the service to be killed under extreme memory pressure
from the current foreground application, but in practice this should
not be a concern.)