Background service is not working in Oreo - android

I want to run my app in background if I kill the app instance also. But after I kill my app the service also stops working. Here is my code please any one help me to solve my issue.
I followed this link for running in the background but it is not working if I remove the instance. Please can any one show me how to run a background service if the instance is removed also?
This is my MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
setContentView(R.layout.activity_main);
Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ALARM_REQUEST_CODE, alarmIntent, 0);
mSensorService = new SensorService(getCtx());
mServiceIntent = new Intent(getCtx(), mSensorService.getClass());
if (!isMyServiceRunning(mSensorService.getClass())) {
startService(mServiceIntent);
}
}
Ths is my service class
public class SensorService extends Service{
public int counter=0;
public SensorService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public SensorService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000); //
}
/**
* it sets the timer to print the counter every x seconds
*/
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
Log.i("in timer", "in timer ++++ "+ (counter++));
}
};
}
/**
* not needed
*/
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}

Its a long story. I have gone through it. Still implemented it. Now my service runs on every boot_complete event and keeps running all the time ( with a notification ).
Official Documentation:
Big NO. Google android developer documentation is poor, with no proper sample example too. It is theoretical and just theoretical. Keep reading if interested
https://developer.android.com/about/versions/oreo/background
Synopsis 1:
You can only receive BOOT_COMPLETE and only few broadcasts in traditional receiver. Rest all broadcast receivers you need to implement runtime in a service by registering them through a code from service which always runs.
Synopsis 2:
Again, you can not have always running processes in or above 8.0 (Oreo)...
To achieve always running process... Create a Intentservice with proper notification of type ongoing and make OnStartCommand START_STICKY and register receiver with code in OnCreate
How to implement it :
I have implemented it take reference from here :
Oreo: Broadcast receiver Not working
Now Your Question : I want to run my app in background if it kills the
app instance also.
With the help of above implementation link of my own you can achieve it
*Terms and conditions
You device must have proper android operating system released and burnt as it is.
Yes, I am using android :
No... You are Using Funtouch OS : VIVO ( By modifying Android)
There are many devices in market COLOR OS : OPPO ( By modifying Android)
....
....
Already google has made it complicated... version by version....
With no proper documentation and sample codes....
And Now Independent mobile device manufacturers making a lot of
changes to allow only selective applications run in background
like WhatsApp, Facebook, Google Twitter Instagram
Now you will ask a developer question If these app runs in background then I can make my app run in background too....
No... They are OS based modifications to check if a service is from allowed vendors then only it can be alive there in background. If they will not allow these vendors then no one take phones which does not run these famous social apps.
Hushhhhhhhh.......

You need to create ForegroundService in order continue processing when your app is killed, as follows:
public class SensorService extends Service{
private PowerManager.WakeLock wakeLock;
#Override
public void onCreate() {
super.onCreate();
//wake lock is need to keep timer alive when device goes to sleep mode
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK_TAG");
createNotificationChannel(this);
Notification notification = new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL").setSmallIcon
(<icon>).setContentTitle("Title")
.setContentText("Content").build();
startForeground(1001, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
public void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Channel name";
String description = "Description";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel("NOTIFICATION_CHANNEL", name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getApplicationContext().getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
To start the service:
Intent i = new Intent(context, SensorService.class);
ContextCompat.startForegroundService(context, i)
Note:
You cannot run service endlessly with this approach. During doze mode if OS recognizes it as CPU intensive then your Service will be terminated.
You need to call stopSelf() when your Timer task has been executed successfully.

Oreo Introduced
new Concept PIP (Picture in Picture Mode )
and it have categories services control by making channels and priority to them.you have to change the code just for oreo to create notifications and services
read about google developers documentation carefully here
https://developer.android.com/guide/topics/ui/notifiers/notifications
both java and kotlin code is available here to create notification in oreo
https://developer.android.com/training/notify-user/build-notification
it was my effort to find the solution after searching and sharing with you.
here is some sample code :
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Much longer text that cannot fit one line...")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line..."))
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
for creating channels write this code:
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
you can see full detials for push notifications and sending messages by clicking on the above links.

Related

Android Listener stop running when app in background

I am developing an app where the app will detect Bluetooth signals (Sensoro Smart Beacon device) and open the activity. But I want the app to still be able to detect the signal even when the application on the background or even when killed. I used a foreground service, it detects the signal when I open the application and move between activities but when sending the app to the background and opening other applications, the listener stops although the service still working. I am printing the logs. System.out.println("Sensoro 2" ); keeps printing even when I kill the application or open another application. But the printing logs in BeaconManagerListener are not working. I tried to use background service but it didn't work also.
Can you please advise if there is a way to make the listener works in a service when the app in background or killed?
Here is the service code:
public class MyService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
int service_timer=0;
Timer timer = new Timer();
SensoroManager sensoroManager;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
sensoroManager = SensoroManager.getInstance(MyService.this);
String input = intent.getStringExtra("inputExtra");
System.out.println("Sensoro 2" );
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.build();
startForeground(1,notification);
//do heavy work on a background thread
//stopSelf();
if (sensoroManager.isBluetoothEnabled()) {
sensoroManager.setCloudServiceEnable(true);
/**
* Enable SDK service
**/
try {
sensoroManager.startService();
} catch (Exception e) {
e.printStackTrace(); // Fetch abnormal info
}
}
else
{
Toast.makeText(MyService.this,"Bluetooth off",Toast.LENGTH_LONG).show();
}
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//your method
System.out.println("Sensoro 2" );
BeaconManagerListener beaconManagerListener = new BeaconManagerListener() {
#Override
public void onUpdateBeacon(ArrayList<Beacon> beacons) {
// Refresh sensor info
for (Beacon beacon : beacons
) {
System.out.println("Sensoro 3" );
// System.out.println("Sensoro" +beacon.getAccuracy());
}
}
#Override
public void onNewBeacon(Beacon beacon) {
if (beacon.getSerialNumber().equals("0117C59B243C")){
System.out.println("Sensoro 3" );
System.out.println("Sensoro acc" +beacon.getAccuracy());
}
}
#Override
public void onGoneBeacon(Beacon beacon) {
if (beacon.getSerialNumber().equals("0117C59B243C")){
System.out.println("Sensoro acc gone");
System.out.println("Sensoro acc Timer" +service_timer);
}
}
};
sensoroManager.setBeaconManagerListener(beaconManagerListener);
}
}, 0, 2000);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// timer.cancel();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
Here is where I call it:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService();
}
public void startService() {
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("inputExtra", "Foreground Service Example in Android");
System.out.println("Sensoro 1 ");
ContextCompat.startForegroundService(this, serviceIntent);
}
public void stopService() {
Intent serviceIntent = new Intent(this, MyService2.class);
stopService(serviceIntent);
}
public void movingg(View view) {
Intent intent=new Intent(this,Usermain.class);
startActivity(intent); }
}
This is not 100% a match with what are you searching but this is near to what are you want.
You can use WorkManager that is working even application in the background. There are two types of WorkManager. 1) OneTimeWorkRequest 2) PeriodicWorkRequest.
So you can you PeriodicWorkRequest which will call every 15 min(minimum interval) and you can add your code in WorkManager to detect Bluetooth signals. So you can able to detect Bluetooth single at every 15 mins of intervals.
I hope this will help you solve your problem.
I don't know if this will help you, but here's my answer:
public void startService() {
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("inputExtra", "Foreground Service Example in Android");
System.out.println("Sensoro 1 ");
startService(serviceIntent);
}
I looked at the Android rules and regulations page
According to Google documents, from Android 8 onwards, all applications that do not have a Google-approved signature will be removed from the background after a few minutes.
But the solutions:
The first solution is to run the application in debug mode
The second solution is to assign a signature to the application and send it to Google for approval
recommend:
The third solution is to remove the google play service application from the emulator or android phone
you can use BroadcastReceiver.
if your app is killed or in the background ,the broadcast receiver is catch the event of bluetoth
I see there are two issues with your approach here.
First you should your check for specific beacon serial number could be causing issue.
Secondly you are using a Timer that goes off every 2 seconds and every time it does it adds a new BeaconManagerListener which should not be the case you should extract the listener outside maybe make it a class member and then use the same listener every time instead of continuously creating new listener which then replaces the old one.
Also why add listener after 2 seconds I think is should be added before calling sensoroManager.startService()
Lastly if the task is not needed to be repeated every few seconds and can be done with an interval >= 15 mins then consider using Periodic Work Manager instead.

Android: Stop Foreground Service causing Application crash

Prerequisites:
As a part of the requirement for my application, I need to make sure that the application won't be closed (killed) by the Android system while in background. For this purpose I implemented Foreground service, even though I don't do any actual process in background, just maintaining the state of the application. Everything works just fine, except one thing which is not fully clear to me how to fix.
The issue:
Sometimes (only once, for now), I receive this exception:
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground():
This exception is thrown when I'm trying to stop the foreground service while it wasn't actually started.
So, my question is - is there is a way to stop foreground service properly, making sure that it is not running before actually stopping it?
What I found at the moment is that I can have static instance for my service and compare to null before stopping service, or get the list of all services currently running. But all these look like some "hack" workarounds.
Here some code:
MyForegroundService:
public class ForegroundService extends Service {
public static final int NOTIFICATION_ID = 1;
public static final String CHANNEL_ID = "SessionForegroundServiceChannel";
public static final String ACTION_FOREGROUND_START = "ACTION_FOREGROUND_START";
public static final String ACTION_FOREGROUND_STOP = "ACTION_FOREGROUND_STOP";
public static void startForegroundService(Context context) {
Intent intent = new Intent(context, ForegroundService.class);
intent.setAction(ForegroundService.ACTION_FOREGROUND_START);
ContextCompat.startForegroundService(context, intent);
}
public static void stopForegroundService(Context context) {
Intent intent = new Intent(context, ForegroundService.class);
intent.setAction(ForegroundService.ACTION_FOREGROUND_STOP);
ContextCompat.startForegroundService(context, intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_FOREGROUND_START.equals(intent.getAction())) {
createNotificationChannel();
Intent stopForegroundIntent = new Intent(this, ForegroundServiceBroadcastReceiver.class);
PendingIntent pendingLogoutIntent = PendingIntent.getBroadcast(this,
0, stopForegroundIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? null
: getString(R.string.app_short_name))
.setContentText(getString(R.string.foreground_description))
.setColor(getResources().getColor(R.color.color))
.setSmallIcon(R.drawable.ic_notification)
.addAction(R.drawable.ic_logout, getString(R.string.logout), pendingLogoutIntent)
.build();
startForeground(NOTIFICATION_ID, notification);
} else if (ACTION_FOREGROUND_STOP.equals(intent.getAction())) {
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
getString(R.string.app_name),
NotificationManager.IMPORTANCE_LOW
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
<service
android:name=".ui.ForegroundService"
android:exported="false"
android:stopWithTask="true"/>
I also have BroadcastReceiver and EventBus to listen to some events and stop foreground depending on those events.
Can you please help me, guys?
Let me add more details to what #Pawel commented:
You get this exception if you don't call Service.startForeground within 3 seconds of calling Context.startForegroundService that's all there's to it.
Here is how the complete solution will look like:
When it comes to the case when you need to stop a foreground service you need to do the following (pseudo code):
if (action == START_FOREGROUND) {
...
startForeground(NOTIFICATION_ID, notification);
} else if (action == STOP_FOREGROUND) {
startForeground(NOTIFICATION_ID, closeNotification); //in case it wasn't started before
stopForeground(true);
stopSelf();
}
Even though it is not obvious, and any documentation don't directly say that when you need to stop foreground you need to start foreground before stopping it (if it wasn't started).
Thanks #Pawel for the hint.

ForegroundService on android Oreo gets killed

I'm trying to build up a service which requests the device location every minute.
I need this to work in the background even when the application is closed. So far I managed to make it work on devices which have a pre-Oreo android OS but now I'm testing the service on android Oreo device and is not working when I close or put the application in background.
In my research I found that for Oreo devices, a Foreground Service with an ongoing notification should be used to achieve this so to start with I've implemented a simple Foreground Service like the below which shows an ongoing notification while the app is started and is removed when the app is stopped.
public class MyForegroundService extends Service {
private static String TAG = MyForegroundService.class.getSimpleName();
private static final String CHANNEL_ID = "channel_01";
private static final int NOTIFICATION_ID = 12345678;
private NotificationManager mNotificationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public MyForegroundService() {
super();
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Android O requires a Notification Channel.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.app_name);
// Create the channel for the notification
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);
// Set the Notification Channel for the Notification Manager.
mNotificationManager.createNotificationChannel(mChannel);
}
startForeground(NOTIFICATION_ID, getNotification());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
stopForeground(true);
}
private Notification getNotification() {
// Get the application name from the Settings
String appName = PrefApp.getSettings(getApplicationContext()).getAppConfigs().getAppName();
String applicationKey = PrefApp.getSettings(getApplicationContext()).getAppConfigs().getAppKey();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setContentTitle(appName)
.setContentText("Services are running")
.setOngoing(true)
.setPriority(Notification.PRIORITY_HIGH)
.setSmallIcon(R.mipmap.ic_notification)
.setWhen(System.currentTimeMillis());
// Set the Channel ID for Android O.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(CHANNEL_ID); // Channel ID
}
return builder.build();
}
}
I am starting and stopping the above service using the below functions.
public void startMyForegroundService() {
Log.d(TAG, "Start Foreground Service");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(getApplicationContext(), MyForegroundService.class));
} else {
startService(new Intent(getApplicationContext(), MyForegroundService.class));
}
}
public void stopMyForegroundService() {
Log.d(TAG, "Stop Foreground Service");
stopService(new Intent(getApplicationContext(), MyForegroundService.class));
}
I'm testing the above service and for some reason the service gets killed after about 30 mins from when I start it. Can anyone tell me if I'm doing something wrong or possibly guide me for a solution which can work for me?
Note: I've followed this tutorial and tested their application as well and that it still not working. The service is being killed after some time.
Basically my goal is to implement a service which can run in the background (even when the application is closed) and get location updates every minutes.
You can use firebase job dispatcher for background service.
Code:
Add this dependencies:
implementation 'com.firebase:firebase-jobdispatcher:0.8.5'
public class MyJobService extends JobService
{
private static final String TAG = MyJobService.class.getSimpleName();
#Override
public boolean onStartJob(JobParameters job)
{
Log.e(TAG, "onStartJob: my job service class is called.");
// enter the task you want to perform.
return false;
}
#Override
public boolean onStopJob(JobParameters job)
{
return false;
}
}
Create a job in the activity, you do it the way you used to do for background services.
/**
* 2018 September 27 - Thursday - 06:36 PM
* create job method
*
* this method will create job
**/
private static Job createJob(FirebaseJobDispatcher dispatcher)
{
return dispatcher.newJobBuilder()
//persist the task across boots
.setLifetime(Lifetime.FOREVER)
//.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
//call this service when the criteria are met.
.setService(MyJobService.class)
//unique id of the task
.setTag("TAGOFTHEJOB")
//don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// We are mentioning that the job is periodic.
.setRecurring(true)
// Run every 30 min from now. You can modify it to your use.
.setTrigger(Trigger.executionWindow(1800, 1800))
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
//.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
//Run this job only when the network is available.
.setConstraints(Constraint.ON_ANY_NETWORK)
.build();
}
/**
* 2018 September 27 - Thursday - 06:42 PM
* cancel job method
*
* this method will cancel the job USE THIS WHEN YOU DON'T WANT TO USE THE SERVICE ANYMORE.
**/
private void cancelJob(Context context)
{
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
//Cancel all the jobs for this package
dispatcher.cancelAll();
// Cancel the job for this tag
dispatcher.cancel("TAGOFTHEJOB");
}

Worker-Thread ends prematurely

I am targeting Oreo. As you know, oreo introduced limits on background task execution time. Workarounds are - according to google - to put the background task in the foreground. This is what I was trying to do, yet once the foreground service is running, it gets destroyed after some time.
First the phone switches off it's screen, then once I activate it again, the background task continues. Sometimes onDestroy on the foreground service is called without the task being completed.
My goal is to have all tasks being set by enqueueWork to be executed without ondestroy being called and without phone sleep mode to interrupt it.
ForeGroundService
public class ForeGroundService extends JobIntentService {
static final int JOB_ID = 1000;
static final int ONGOING_NOTIFICATION_ID = 33;
static void enqueueWork(Context context, Intent work) {
enqueueWork(context, ForeGroundService.class, JOB_ID, work);
}
Notification.Builder notification;
NotificationManager mNotificationManager;
#RequiresApi(api = Build.VERSION_CODES.O)
void einleitung(String Titel, String Text)
{
Intent notificationIntent = new Intent(this, ForeGroundService.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(Titel,
Text,
NotificationManager.IMPORTANCE_HIGH);
channel.setSound(null,null);
mNotificationManager.createNotificationChannel(channel);
}
notification =
new Notification.Builder(this,Titel)
.setContentTitle(Titel)
.setContentText(Text)
.setSmallIcon(R.drawable.kleinesicon)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentIntent(pendingIntent)
.setTicker("setTicker");
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification.build());
startForeground(ONGOING_NOTIFICATION_ID, notification.build());
}
#RequiresApi(api = Build.VERSION_CODES.O)
void vordergrund(String Titel, String Text)
{
notification.setContentTitle(Titel);
notification.setContentText(Text);
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification.build());
}
PowerManager.WakeLock wakeLock;
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
protected void onHandleWork(Intent intent) {
if (beginn) {
einleitung("Test", "Test");
beginn = false;
}
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
//Do Work
}
#Override
public void onDestroy() {
super.onDestroy();
Intent local = new Intent();
local.setAction("de.test.action");
this.sendBroadcast(local);
stopForeground(true);
//toast("Fertig");
if (wakeLock != null)
wakeLock.release();
}
final Handler mHandler = new Handler();
}
MainActivity
public class MainActivity extends AppCompatActivity {
private int JI = 1000;
private BroadcastReceiver updateUIReciver;
#RequiresApi(api = Build.VERSION_CODES.O)
void somefunction(someparameters)
{
Intent mServiceIntent = new Intent();
mServiceIntent.putExtra...
ForeGroundService.enqueueWork(getBaseContext(),ForeGroundService.class,JI,mServiceIntent);
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(updateUIReciver);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter();
filter.addAction("de.test.action");
updateUIReciver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
ForeGroundService.shouldContinue = false;
}
};
registerReceiver(updateUIReciver,filter);
btnB.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.O)
public void onClick(View v) {
if (startcondition)
{
Intent startIntent = new Intent(MainActivity.this, MyService.class);
startIntent.setAction(Constants.ACTION.START_ACTION);
startService(startIntent);
Intent serviceIntent = new Intent(MainActivity.this,ForeGroundService.class);
startForegroundService(serviceIntent);
somefunction(someparameters);
}
else
{
Intent stopIntent = new Intent(MainActivity.this, MyService.class);
stopIntent.setAction(Constants.ACTION.STOP_ACTION);
startService(stopIntent);
}
}
});
}
}
EDIT: I made it work with sandhya sasane's solution and
public int onStartCommand(Intent intent, int flags, int startId)
{
if (beginn) {
executorService = Executors.newFixedThreadPool(1);
beginn = false;
}
final Intent i2 = intent;
executorService.execute(new Runnable(){
#Override
public void run(){
abarbeiten(i2);
}
});
return START_STICKY;
}
Important is the 1 in newFixedThreadPool(1); to only have one thread run at once
I am targeting Oreo. As you know, oreo introduced limits on background task execution time.
Yes, it does. I can understand you, as google has made the things very odd and complex first..., then again complicated... then again... then again... And now developers like me and you, and your question and problem, denotes the outcome / result / proof of that.
Workarounds are - according to google ...
Please save time and yourself too... Google documentation is worst.. i have given -10 out of 10 for their documentation.
to put the background task in the foreground.
You have a wrong perception of what foreground concept is..!! Read complete answer word by word carefully, Your problem will get solved..!!
This is what I was trying to do, yet once the foreground service is running, it gets destroyed after some time...
Now very simply... Your Concept and implementation, both are wrong..., So Try with a new sample project and guidelines provided here along with sample working and tested code across 4.0 to latest android P
.
First the phone switches off it's screen, then once I activate it again, the background task continues. Sometimes onDestroy on the foreground service is called without the task being completed.
It does not relate to foreground service, in any way.... forget this.
My goal is to have all tasks being set by enqueueWork to be executed without ondestroy being called and without phone sleep mode to interrupt it.
Forget this too... Lets first see what a foreground service is and how it is created...
What is foreground service
A service which remains active (It does not mean... continuously
running like never ending do-while loop)
Remain active until next boot / reboot
Even if user removes app from recents, it remains
But It does not remain active post next boot
It needs to be restarted by user by opening app again or via a broadcast receiver of ON_BOOT_COMPLETE or by a AlarmManager or By a JobScedular
When to use
As per my view users do not like a permanent notification showing message ^This is running in foreground and may discharge your battery soon^ , Again user would not be able to swipe it away and can only force stop or uninstall app to stop it. So it is as per my implementations point of view , ^Developers must use this for implementing runtime receivers as post - oreo devices do not welcomes static receivers implemented by extending Broadcastreceiver and placing its intent entry in manifest.xml file... Even if developer tries to do this that receiver will never get called on post - oreo devices ..., Yes it will get called below oreo devices. So implement just a ON_BOOT_COMPLETE receiver and rest all in a service.
How to implement a foreground service
Right click on project structure and make a service named RunnerService and then generate all mandatory methods. it does not require you to type all code manually.. Generate it as said. Sample foreground service :
public class RunnerService extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";
public RunnerService() { }
#Override
public void onCreate()
{
super.onCreate();
Log.d("RUNNER : ", "PROGRAMMED.... \n");
Bitmap IconLg = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("App Name")
.setContentText("Foreground service...")
.setTicker("Foreground service...")
.setSmallIcon(R.drawable.ic_menu_slideshow)
.setLargeIcon(IconLg)
.setPriority(Notification.PRIORITY_HIGH)
.setVibrate(new long[] {100})
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setAutoCancel(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{100});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
mNotifyManager.createNotificationChannel(notificationChannel);
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
startForeground(1, mBuilder.build());
}
else
{
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
mNotifyManager.notify(1, mBuilder.build());
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("RUNNER : ", "\n IT IS ACTIVE UNTIL NEXT BOOT....");
return START_STICKY;
}
#Override
public void onDestroy()
{
Log.d("RUNNER : ", "\n IT WILL BE AGAIN ACTIVE BY ANDROID OS AUTOMATICALLY, DO NOT WORRY AND DONT CODE TO START IT AGAIN !!....");
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("NOT_YET_IMPLEMENTED_BY_DEVELOPER");
}
}
How to start it
It depends on which android you are targeting below oreo or post oreo ... I will prefer to on all like below :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
this.startForegroundService(new Intent(this, RunnerService.class));
}
else
{
this.startService(new Intent(this, RunnerService.class));
}
Either from MainActivity or any ON_BOOT_RECEIVER, or from wherever you want, just start it as said here...
How to test is in foreground
By removing it from recents... It will call onDestroy but it will be never destroyed you will not be able to swipe away notification. This means a success.
How to test it quick
With a sample new project with a MainActivity just calling service in said manner.
What next..?
Yes you can ask your next tasks here only..., I will keep updating and guiding... I hope you have kept enqueueWork concept and all your concepts aside and do not thinking on it...
Lets go step by step and let me know the updates....
UPDATE 2
You should try it on emulator only... If success then try it on actual devices... Here is a problem again...
There are many mobile phone manufacturers in the world now, which takes
stock android from google as it is open source and modifies it to disable all services on BOOT. It only keeps Google , WhatsApp, FaceBook , Twitter and major market leaders... As if they do not allow them no one will purchase their devices ...
Examples :
Vivo = FunTouchOs
Oppo = ColorOs
There is a huge list....
Do not check on this for BOOT_COMPLETE..., IT will not work as they are modified the android..
But i want to test it on actual device
Then test it on such device which os is purely from google and having android os.
Then what should i do for other os modified from android
There are tricks ..., But lets go step by step.... I will let you know , once you success in this..!!
UPDATE : 3
As it is not clear what is the requirement i am making some assumptions and writing answer :
What you can do to implement foreground execution is :
Implement foreground service as i depicted
Use local broadcastmanager to broadcast events of your own.
in onCreate of a foreground service register runtime receiver to receive that broadcasts
On receiving broadcasts call to the methods of user defined class with context of foreground service. And perform all tasks from there.
Unregister receiver from onDestroy of foreground service.
What you can do to implement background execution is :
If you are having repeating tasks and wants to execute it in background even if the app is removed from recents ... Then :
Use Firebase Job Dispatcher which uses GooglePLAYServices
If you use forever then that job will be triggered automatically even if system is rebooted and even if app is not in foreground or background or in recents...
As of now i do not see any need of JobIntentService and therefore its static enqueueWork method; More resolution and details are needed for solving your problem.

Android service is stopping without calling ondestroy

I'm calling a service every three minutes using the following function:
public void RunBackgroundService() {
final Handler service_handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
service_handler.post(new Runnable() {
public void run() {
context.startService(new Intent(context,BackgroundService.class));
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 180 * 1000);
}
And this is my service in which I'm launching a notification:
public class BackgroundService extends Service {
Helper helper;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
//Toast.makeText(this, "Service created!", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
//Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onStart(Intent intent, int startid)
{
helper=new Helper(this);
// Log.d("Service started at:", helper.getdatetime());
Intent n_intent = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, n_intent, 0);
// build notification
// the addAction re-use the same intent to keep the example short
long[] vibrate = { 0, 100, 200, 300 };
Notification n = new Notification.Builder(this)
.setContentTitle("Application")
.setContentText("This is a test")
.setSmallIcon(R.drawable.notification_icon)
.setContentIntent(pIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setVibrate(vibrate)
.setAutoCancel(true)
.build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
}
}
It's very important to me to remain the service running at all time, when the app crashes the service stops. How can I prevent the service from stopping ?
When an app crashes, the entire process goes down with it. This includes all Services and other threads in that process. You can't stop that from happening.
The best you can do is to configure your app to run in a different process from the main app process, but then you have to know how that affects the rest of your app.
Be sure to read the docs for how to define a service to run in another process. You use the android:process attribute for that.
You cna not stop system killing your service. But what you can do is to restart the service when it is crashed. Take a look at detailed sof post How to restart service after the app is killed from recent. This solution works not only when app is killed through recent taks by user but also when system kills app.
Use android:process tag to start process in different process.
Then use it as bind to service from your application, this way you can communicate with service via ipc and service runs indefinitely even if your app crashes.

Categories

Resources