Android startup Service onStart and another issue - android

I've been trying to figure this out for a while now and can't figure out why this is happening. This seems like it would be simple, but I can't get this to work out.
Here's what I'd like to happen
When I start the application,
1. If the background Service (long running singleton service) isn't running, start it before starting the activity.
2. Start the "homepage" activity
Updated 8/20
Here's what is happening:
1. I start the application and the service isn't running
2. I kick off the intent (via context.startService)
- the context.startService is called
3. The activity runs to completion
4. The onStartCommand is run
How can I get the onStartCommand to run before the activity starts running??
Any advice on this would relieve a lot of frustration. I've searched the forums prior to asking this but couldn't find anything that matches my issues
Thanks a lot!
Update
Thanks for the quick responses.
I should have mentioned that I'm already running this from an extension of Application (starting the service in the onCreate method).
In my current implementation (below), here's what happens in order as I step through the app. I thought this would cause the service to run before the activity but the activity runs and then the service runs. This is the main point of my confusion.
1. the application onCreate is called
2. the startService method is run
3. the starting activity runs
4. the service onCreate is called
- the service onStart is never called (I'll try the onStartCommand instead as I'm not targeting older platforms - thanks for that suggestion Alexander)
public class MyApp extends Application {
#Override
public final void onCreate()
{
if(!MyService.isRunning()) // this is a static method with thread lock
{
Intent i = new Intent(context, MyService.class);
i.setAction(MyConstants.INTENT_START_SERVICE);
context.startService(i);
}
}
}

You can create a new class that extends the Application class. This class will run before the main activity is called, and only when the app is first launched. This is where you can launch a service before your homepage activity is opened.

Thanks to Alexander O for his comment that pointed me in the right direction to getting the onStart command to run. I still can't get the onStartCommand to run before the activity though. Any suggestions?
My issue was that I had both an onStartCommand and an onStart function in my service.
Apparently I didn't understand the function of onStartCommand and thought that it was just supposed to define the service type (STICKY, NOT_STICKY).
Once I removed onStart and moved the onStart code into onStartCommand the application began working.
For those wondering, here's basically what I had.
public class MyService extends Service
{
...
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// this was being executed but didn't really do anything
return Service.START_STICKY;
}
...
#Override
public void onStart(Intent intent, int startId)
{
// logic that was never executed
// problem fixed when I removed onStart and moved the code to onStartCommand
}
}

Related

OnTaskRemoved in Android O

In my android app, I have a Service that starts when the app goes in background. OnStartCommand begins long running task that analyzes and checks device and app status.
Now, I am preparing the app for Android O. First issue that i faced is Services, I rework them to JobServices.
Now I am facing another issue. When user removes my app from application stack JobService.OnTaskRemoved doesn't get called.
Before, when I used Service calling of Service.OnTaskRemoved worked fine for me.
Now I see only way. I need My old Service for handlingService.OnTaskRemoved and new JobServices for executing task.
Am I wrong? May be some one can give me good advice?
You are implementing the wrong concepts.., which creates problem.., To tackle it .. you are again implementing wrong things.. Please offload all...
In my android app, I have a Service that starts when the app goes in background..
The Problem ;
In android O there is no background execution allowed at all.. Even a single line of code is not guaranteed to execute..!!
And you want it to execute long running service..!!
The Solution;
The same service can be started whenever App is opened first time... On acquiring all runtime permissions. As :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, YourLongRunningService.class));
}
else
{
context.startService(new Intent(context, YourLongRunningService.class));
}
OnStartCommand begins long running task that analyzes and checks device and app status.
The Problem ;
OnStartCommand is not meant to be coded the long running procedures / statements of code..
Nor it is meant to be coded at all........
The Solution;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("RUNNER : ", "\nPERFORMING....");
return START_STICKY;
}
Above single line tells android to keep alive ALL THE TIME UNTIL DEVELOPER STOPS IT ON HIS OWN VIA CODE STOPSELF Even removed from background or from recents; It gets re-created automatically by android os
Then where should i write the code.... ??
Wait... its too early to code yet....!!! patience
begins long running task that analyzes and checks device and app status
Your question is un clear and in my brain there is a gradle error ... I can not resolve your symbols :
analyzes
checks device
app status
But i know that these your broadcasts definitely .. And you need to implement broadcast-receivers... to receive it...!!
I will implement Broadcast receivers... Its too easy...
The Problem ;
Wait... Android O do not allows you to implement many broadcast receivers from static receivers like we does... And even we are not allowed to call that receivers on specific intent-actions from manifest.xml
The Solution;
Implement runtime receivers in your above created service YourLongRunningService in onCreate like :
IntentFilter myFilter = new IntentFilter();
myFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
this.registerReceiver(mCallBroadcastReceiver, CallFilter);
CONNECTIVITY_CHANGE is an example and it would be your intent action / broadcast you want to listen for...!!
What is mCallBroadcastReceiver and all...
These are runtime registration of receivers... and needed to be unregistered from onDestroy like :
#Override
public void onDestroy()
{
this.unregisterReceiver(mCallBroadcastReceiver);
super.onDestroy();
}
No.... No... No.... I do not want to un-register it... I want it always working..
Our service is START_STICKY Even if it is destroyed; gets started automatically and registers mCallBroadcastReceiver in onCreate again..
Where is the receiver then....???
In this case mCallBroadcastReceiver is receiver defined in class area where we declares the variables and constants :
public class YourLongRunningService extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";
private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
// All your receiver code goes here...
}
};
// your constructor
// your onStartcommand
// your ondestroy
}
What notification Manager is doing here....???
In and above O you can not run foreground service without proper Ongoing task notification... It will go in your onCreate which will call Startforeground with the notification to start this service as a foreground service
What below android O...?
It works below Android O too... Just call with normal startservice its code it given on very start...!!
Where is my long running code goes then....???
From receiver receive broadcast you want and start a intentservice or a job or a alarm class or whatever you want...
I will make a simple class which takes context in constructor and defines a public method named LongRunningCode may be of one crore lines of code....
And on receiving broadcast in receiver , I will make a object of that class by passing context of receiver and will simply call LongRunningCode method with that object
Hope it helps

Custom JobIntentService onHandleWork not called

I recently was updating an app that I work on to handle notifications from push using a JobIntentService instead of a regular IntentService because it seems like the correct way to handle this on pre-Lollipop devices as well as post. I am enqueueing work as such:
enqueueWork(context, MyJobServiceExtension.class, JOB_ID, work);
This is the manifest declaration:
<service android:name="com.example.MyJobServiceExtension"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"
tools:node="replace">
I never see any callbacks in onHandleWork or any error logs in my logcat. Has anyone successfully integrated this that could help?
Update 1
I tested this on an API level 21 device and it worked.. but it doesn't seem to be getting called on my Android Oreo Pixel XL device.. Any clues as to why?
Update 2
Also I seem to be seeing the IntentService's onCreate be called, but none of the other lifecycle methods (including onHandleWork). Has anyone encountered this either?
I had the same issue after upgrading from IntentService to JobIntentService. Make sure you remove this method from your old implementation:
#Override
public IBinder onBind(Intent intent) {
return null;
}
For me this solved the problem, and now it works both on pre- and post-Oreo.
I had the same problem (worked fine on a pre-O device, no indication of anything happening whatsoever on an O-device). Today, I tried again with exactly the same code as yesterday, now it works - only difference is that I rebooted the device in between.
My current theory is that my initial setup did not work; my current one does and just redeploying new code does not clear out the broken state from the JobScheduler; a reboot or an uninstall/reinstall of the package does.
The setup that's working now (migrated from a former IntentService):
<service
android:name=".MyJobIntentService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"/>
and start with
Intent intent = new Intent();
intent.putExtra(EXTRA_NAME, extraValue);
JobIntentService.enqueueWork(context, MyJobIntentService.class, FIXED_JOB_ID, intent);
Note that the intent is not an explicit intent (i.e., the ComponentName is not set).
If you have overridden the onCreate method in your JobIntentService, it will prevent the onHandleWork to be called.
I converted my Service to JobIntentService and only after I removed the onCreate method it worked.
This is what worked for me,
Remove the IBind Override as suggested by #agirardello
and added the following
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
Have no idea why this worked.
I ran into this issue trying to enqueue the JobIntentService using JobScheduler. While JobScheduler has its own enqueueWork() method, it doesn't work with JobIntentService. The service will start but onHandleWork() is never called.
It started working again when I used the static enqueueWork() method that is on the JobIntentService - eg:
MyJobIntentService.enqueueWork(context, ...)
None of this was obvious from reading Android's javadoc.
I encountered a somewhat similar problem with onHandleWork not being called the second time after migrating from Service to JobIntentService. Logs were showing that enqueueWork was called but onHandleWork was executing only the first and appeared to be stuck.
After some more digging and logging, I discovered that the difference was that in a "stuck" scenario there was JobIntentService#onDestroy even though all operations in onHandleWork were performed and seemingly finished.
Turned out that the culprit was bindService call of that service to activity lifecycle which was preventing disposing of the first job and for some reason calling enqueueWork after this condition was causing the service to "stuck" and never run any of the following onHandleWork again.
So, here is an incorrect log of events in which JobIntentService will appear to be stuck after the first call never triggering onHandleWork again:
enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
enqueueWork -> second call
enqueueWork -> third call
And here is the correct log of events with JobIntentService functioning correctly after removing bindService call:
enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy (service is destroyed after the job is finished)
enqueueWork -> second call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy
enqueueWork -> third call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy
Hope this will be helpful to someone.
For me I was still starting the service after enqueueWork and was giving me error because of that.
Just try exiting and running the Android Studio again. Then test again.
In my case, the version of Android Studio is v 3.3.1.
See the sample code that works properly.
public class CustomizedIntentService extends JobIntentService
{
public static final String MY_ACTION = "action.SOME_ACTION";
private static final int MY_JOB_INTENT_SERVICE_ID = 500;
public CustomizedIntentService() {
}
// Helper Methods to start this JobIntentService.
public static void enqueueJobAction(Context context, String action) {
Intent intent = new Intent(context, CustomizedIntentService.class);
intent.setAction(MY_ACTION);
enqueueWork(context, CustomizedIntentService.class, MY_JOB_INTENT_SERVICE_ID, intent);
}
#Override
protected void onHandleWork(#NonNull Intent intent) {
String action = intent.getAction();
// action will be "action.SOME_ACTION"
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public boolean onStopCurrentWork() {
return super.onStopCurrentWork();
}
}
// start the JobIntentService as you need.
CustomizedIntentService.enqueueJobAction(context, CustomizedIntentService.MY_ACTION);
As funny as this may sound, l had a similar issue because l did not change the name of the class to its own name in the enqueueWork() because l copied the code from one of my classes.
After l made the update it started working properly.
I finally found the solution for that problem LoL
If you Override the "onBind" method and u call the work using the "enqueueWork" method you need to return the bind to the engine of the work doing this:
#Override #Nullable
public IBinder onBind(#NonNull Intent intent) {
[... Do What You Want ... ]
return super.onBind(intent);
}
So returning the IBinder of the "super.onBind" method, so you must use that to bind to the JobIntentService.
If you want to bind and return another binder you can do that:
#Override #Nullable
public IBinder onBind(#NonNull Intent intent) {
IBinder binder = initSynchronizer();
new Thread(
() -> onHandleWork(intent)
).start();
return binder;
}
So by starting you "onHandleWork" in another Thread.
This way you can use:
"bindService(....., JobIntentService.BIND_AUTO_CREATE);"
to bind to the service and return your Binder.
Anyway when you unbind from the service the service will get killed, and if it still run you cannot bind again to it because the service got killed but the thread in which the "onHandleWork" is still running...
So I suggest you to use this version only if you have to do a task which need to communicate with the activity until it is alive and need to still working if the activity get killed (without the possibility to bind again the jobService, but only to start a new one...)
To don't kill the service after the unbind you need to start it in "foreground" the "stopForeground" in the "onDestroy". This way you service still be alive just for the thread which is handling the "onHandleWork" methods.
I hope google's will solve this sh*t fast LoL, I converted all the older "Service" and "IntentService" to the new one jobs but... they work really worst than before!
Bye have a nice coding ;)
I think that I have such problem since I try to toast some text inside onHandleWork() but actually the problem was that it was wrong. I should use a Handler. It may be the problem if one uses for example AsyncTask subclasses to execute on another thread inside onHandleWork() which is a very bad idea.
For everyone who couldn't solve the problem with the other answers:
Try using different JOB_IDs every time enqueueWork is called. If a previous job hasn't finished, the Service may just be stuck (similar to the problem the user "git pull origin" has described) and a new job with a different ID may solve this issue.

What can I expect when onCreate() calls startService()

I am trying to understand the Service Life Cycle while working through some Android Open Source Code.
I was looking at a Service implementation which I distilled down to something like the following...
public class MyService extends Service {
public MyService() { super(); }
#Override
public void onCreate() {
super.onCreate();
init();
//==this seems odd to me
//comment in AOSP says startService() is called to make
//sure Service stays around long enough for the async call
//to complete.
startService(new Intent(this, myservice.class()));
doSomeMoreInitAsync();
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
if(actionableIntent(intent,flags,startId)) {
//do something
//NOTE: the Intent passed to startService() in onCreate()
//above will go around this block of code, doing nothing
//except returning START_STICKY
}
return START_STICKY;
}
public void onDestroy() {
//destroy stuff
}
#Override
public IBinder onBind(final Intent intent) {
return mBinder; //an instance of android.os.Binder derivative
// created when this service was instantiated
}
//other stuff
}
Why would someone want to have onCreate() call startService() on itself like above, doing nothing? The comment in code sheds some light, but it's like assumptions are being made about the Life Cycle that I don't understand. I.e., is it reasonable to expect onCreate() to effectively start its own service?
I know that if a service has already been started then onCreate() will only be called once (unless destroyed and restarted, then a new instance of the service is created and onCreate() is called once on it). My first concern with this example would be that there is an expectation placed upon the underlying Service API implementation that the Service is already in the initialized state before onCreate() is called (else there be an infinite recursion, but there is not).
But isn't onCreate() supposed to be part of the initialization (albeit an optional part for the subclass)?
Is this coding logic a reasonable way of making sure the Service is forced to be an Unbounded Service? Or am I looking at a bad example in the AOSP which may have undefined behavior in the future?
You are correct in that a Service will call onCreate and onStartCommand if it is started via Context.startService. So in this sense, when you return START_STICKY, the Service will continually run until an explicit call to stopService() is called. It will also be destroyed and restarted during this lifecycle.
Another way to create a Service, is by binding to it. As per the docs:
Clients can also use Context.bindService() to obtain a persistent connection to a service. This likewise creates the service if it is not already running (calling onCreate() while doing so), but does not call onStartCommand().
So, it's possible for a Service to be created by simply binding to it. However, the lifecycle of a Service indicates that it will remain if it is started or a client is still bound to it. Meaning, that if it was created by a bind command, it will immediately be destroyed as soon as the client unbinds.
So, if a Service starts itself in the onCreate(), it will ensure that it puts itself in the started state regardless of whether it was created by binding or by an explicit call to startService. Since there's no actionable intent, the onStartCommand will just pass straight through. An clients that call startSevice will, presumably, have actionable Intents in which case the Service will perform its duties.

Stop the Service on Destroy of Application

I am confused right now , about service concept of running and stopping:
what i want to do:
Start Location service at the very start of application.
Keep getting location updates and store them to shared preference
Stop the service in onDestroy of Application scope!
So far i have searched and studied we can only do following things with service(correct me if i'm wrong):
Stop the service automatically by binding it to related activities/fragments/views , when all of them destroyed service unbind itself automatically so we can call stopself method in unbind
return START_NOT_STICKY in onStartCommand to tell OS , don't recreate it , and create intent local service , after completion of some work it will destroy itself.
Stopping the service manually , by declaring it's intent in some kind of static scope and stopping the service in on onActivityDestroyed of Application class [I am not sure what will happen? , maybe service will destroy each time any activity will be destroyed ? or it will be destroyed only when overall application get's destroyed?]
Either way , i am bit confused and beat , been trying to adjust my Location service with given details for 2 days
If you start your Service using START_NOT_STICKY, then your app will kill your service once your entire application is closed from background i.e. you cleaned your app from home screen.
Here START_NOT_STICKY states that you need not recreate service in case it is been killed.
If this is not the case then you have to manually kill it by your self.
Like
Intent lintent = new Intent(context, LocationService.class);
context.stopService(lintent);
You can use this code at point where your application kills.
That's it. You are good to go with this.
First of all, launch the "LocationService" on your app start:
public class MyApp extends Application {
private static final String TAG = "MyApp";
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "App started up");
startService(new Intent(this, MyLocationService.class));
}
}
Second :
As you said, the Service should better run with the "START_NOT_STICKY" flag
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Thrid:
Once the system kills your app, the Service will automatically be killed, so no problems at all.
There is no onDestroy() method on the Application object, the only similar event is onTerminated() and it is not being launched on production devices.
onTerminate
Added in API level 1 void onTerminate () This method is for use in
emulated process environments. It will never be called on a production
Android device, where processes are removed by simply killing them; no
user code (including this callback) is executed when doing so.
More information:
https://developer.android.com/reference/android/app/Application.html#onTerminate()
Btw, If you want the MyLocationService to send updates of the location to your app (when it is open), you should consider to use Otto or EventBus (I recommend you this last one because of the simplicity to use it). You can even configure the #Suscriber to receive updates of old retrieved locations if you want.
I will try to explain in a easiest way :)
There are two type of service
IntentService and Service
IntentService when started will kill itself once it treated the content of it onHandleIntent method
as for Service well this one will not end until you give it the command to do so even if your start it using the context of an activity. It will also stop when the application is stopped in an extreme case (by system (Settings/application/YourApp/stop app OR an app crash)
Easiest way is First of all start IntentService with AlarmManager at some repeating time (10 mintutes), then in onHandleIntent() get Location and store into preference.
No Need bind to your activity, the IntentService automatically stops itself after saved in preferences.
Yes you can stop the service in onDestroy() of the activity:
#Override
public void onDestroy(){
Log.v("SERVICE","Service killed");
service.stop();
super.onDestroy();
}

"Application is not responding. Would you like to close it?" getting an error while running service in Android

I have an Android application that has a button that starts the service.
Here is the service:
public class SimpleService extends Service
{
#Override
public int onStartCommand(Intent intent,int flags, int startId)
{
Toast.makeText(this,"Service Started",Toast.LENGTH_SHORT).show();
Integer i=0;
while (i<10)
{
Log.d("Hi",i.toString());
SystemClock.sleep(5000);
i++;
}
Log.d("Hi","return START_STICKY");
return START_STICKY;
}
public void onDestroy()
{
super.onDestroy();
Toast.makeText(this,"Service Stopped",Toast.LENGTH_SHORT).show();
}
}
When I clicked on the button, the service starts successfully, but after some while, in the emulator, I got an error like
Application is not responding. Would you like to close it?
Am I doing anything wrong in service implementation?
What I want to do is perform a task on every 5 seconds even if my application got killed.
I tried with IntentService but it got killed when my app got killed so my task remains incomplete.
while (i<10)
{
Log.d("Hi",i.toString());
SystemClock.sleep(5000);
i++;
}
I would like to point out this part of your code. Here what you are doing is once your service starts, you are doing 10 iterations of loop and in each iteration you are pausing execution for five seconds (which is a lot of time in terms of execution). As services run in the main process, in my opinion, they block the main thread, which means during the sleep, if your app is accessed, you will get the ANR (App not responding) error. Thus, these types of tasks should be run in a separate thread.
If you want to perform some repetitive tasks on the background, I'd suggest you make use of a AlarmManager component of the Android SDK.Alarm manager is a system service, thus you can access it by using the following line of code.
AlarmManager mAlarmMgr=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
//Then you can set alarm using mAlarmMgr.set().
You will then receive the alarm in a AlarmReceiver.
AlarmReciever class extends BroadcastReceiver and overrides onRecieve() method. inside onReceive() you can start an activity or service depending on your need like you can start an activity to vibrate phone or to ring the phone.
I hope this helps. Cheers!
Since By Default, all your app components (like Activity, Service etc) runs in Main/UI Thread, and if it get blocked, Android shows ANR dialog.
Also, Each of lifecycle method of service is called from UI thread. If you need background task to be running all the time, you can crate new thread for this.
You may try below code inside your Service class:
new Thread(new Runnable(){
public void run() {
while(i<10)
{
Thread.sleep(5000)
//REST OF CODE HERE//
}
}
}).start();

Categories

Resources