I´m working on my IntentService, in which I generate values in a loop. In overriden methods onStartCommand() and onDestroy(), there is possible to display a message using Toast. I would like to use Toast also in onHandleIntent(), but it´s not working. I know there are better ways (files, attributes etc.) to display values, but I need these values immediately, when they are created. Not in the end (only for control, if it´s working properly). Please, can you help me identify the problem? Thanks in advance.
public class HelloIntentService extends IntentService {
public HelloIntentService() {
super("HelloIntentService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
#Override
protected void onHandleIntent(Intent intent) {
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}}
#Override
public void onDestroy()
{
Toast.makeText(this, "Service is being destroyed now.", Toast.LENGTH_SHORT).show();
}
}
onHandleIntent runs on a separate thread in the background per the source code and therefore does not have any ability to update the UI. I would suggest using logging statements, rather than Toasts to display your information:
Log.d("HelloIntentService","service starting");
Related
Android will kill some service when memory is not enough.
Like this:
I know I can use foreground service to prohibit android to kill my service
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
try {
Notification notification = new Notification(R.mipmap.ic_launcher,"this is service", System.currentTimeMillis());
Intent intent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,intent , 0);
notification.setLatestEventInfo(this, "myapp", "myservice", contentIntent);
notification.flags =Notification.FLAG_AUTO_CANCEL;
startForeground(123,notification);
}
catch(Exception e)
{
stopSelf();
}
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
But this will display a notification on screen
I would rather kill service than display notification, but I also don't want to display stopped message.
I found some app, it can display no message when android kills it.
e.g. Screen Dimmer
How can I prohibit android to display app stopped message?
Check this: https://stackoverflow.com/a/32229266/2965799
According to that I have used the following code to handle the exception. I wanted to display another message so I added my own message however if you use his answer there will be no messages.
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
new Thread() {
#Override
public void run() {
Looper.prepare();
Toast.makeText(getActivity(),"Your message", Toast.LENGTH_LONG).show();
Looper.loop();
}
}.start();
try
{
Thread.sleep(4000); // Let the Toast display before app will get shutdown
}
catch (InterruptedException e) { }
System.exit(2);
}
});
One way is to implement a UncaughtExceptionHandler with your own custom failure code. The API to install your handler is this:
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh);
The class is documented here. As a very basic example:
import java.lang.Thread.UncaughtExceptionHandler;
public final class CrashHandler implements UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
android.util.Log.wtf("My app name", "Oops, caught it dying on me!");
}
}
A full working example is available here.
I am working on below code to run a service in background,but the problem is i am not getting how to run the service indefinitely even though the app is closed,here on press of back my service is stopping.I have read many tutorials but still confused with this.
public class HelloService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
if (isRunning) {
Log.i(TAG, "Service running");
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
On Android there is NO way (at least for a third party app) to have a never ending process running. The system can always kill your service. So you can use a foreground service but the system can kill your service even in this case (even with low probability). In addition, you should consider that the cpu can go to sleep. So you should take a wakelock but in this way you can kill the user battery so it's not a good solution. My suggestion is to always work "on event" for example with a brodacast receiver that starts a intent service, it does some work and then exit. The always running processes are simply a wrong design choices on Android.
One Way is to use while loop but keep a check i.e
while(true) {
if (condition != true) {
Thread.sleep(time);
} else {
break;
}
}
These methods are implemented in a class extending Service. A new service is started every time a button is pressed.
If the button is pressed once, LogCat outputs what I expect, which includes a final output of "Service onDestroy." However, when the button is pressed twice, the second time before the first service ended, "Service onDestroy." displays only once when the first service is done, and the second service prints out the rest of "Service Running" logs but not "Service onDestroy."
Can anyone tell me why? Thank you!
public int onStartCommand(Intent intent,int flags, int startId) {
Log.i(TAG,"Service onStartCommand " + startId);
final int currentId = startId;
Runnable r = new Runnable() {
public void run() {
for (int i = 0; i < 3; i++) {
long endTime = System.currentTimeMillis() + 10*1000;
while (System.currentTimeMillis() < endTime) {
synchronized(this) {
try {
wait(endTime - System.currentTimeMillis());
}catch (Exception e) {
}
}
}
Log.i(TAG,"Service running");
}
stopSelf();
}
};
Thread t = new Thread(r);
t.start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i(TAG,"Service onBind");
return null;
}
#Override
public void onDestroy() {
Log.i(TAG,"Service onDestroy");
}
In the guide for Services they use don't use stopSelf() but stopSelf(startId) when extending Service. The first stopSelf() propably stops both executions of your Service.
See here: http://developer.android.com/guide/components/services.html
Edit: Also a service is only created and destroyed once even when there are several executions of it running it is still a single service. In your case (a Bound Service) it will only be destroyed when the last excecution finishes. For logging every excecution ending you could try to override the stopSelf(int startId) method.
Can anyone tell me the way to keep a Service always running or restarting itself when the user close it? I've watched that facebook services restart when i clear memory.
I don't want to make ForegroundServices.
You should create a sticky service. Read more about it here.
You can do this by returning START_STICKY in onStartCommand.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
Read also about application:persistent which is "Whether or not the application should remain running at all times". This is more troublesome - System will try not to kill your app which will effect others in the system, you should be careful using it.
I copied this from a service I used in an app I did before.
ITS IMPORTANT TO NOT UPDATE ANY UI. because you have no user interface in services. this applies to Toasts as well.
good luck
public class nasserservice extends Service {
private static long UPDATE_INTERVAL = 1*5*1000; //default
private static Timer timer = new Timer();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
_startService();
}
private void _startService()
{
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
doServiceWork();
}
}, 1000,UPDATE_INTERVAL);
Log.i(getClass().getSimpleName(), "FileScannerService Timer started....");
}
private void doServiceWork()
{
//do something wotever you want
//like reading file or getting data from network
try {
}
catch (Exception e) {
}
}
private void _shutdownService()
{
if (timer != null) timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped...");
}
#Override
public void onDestroy()
{
super.onDestroy();
_shutdownService();
// if (MAIN_ACTIVITY != null) Log.d(getClass().getSimpleName(), "FileScannerService stopped");
}
}
How do I start my service in a new thread. I looked on other questions but it dint work for me. What changes do I need to make in my service when normally running and when running in a separate thread?
Rename your public void onStart(final Intent intent, final int startId) method to _onStart and use this new onStart implementation:
#Override
public void onStart(final Intent intent, final int startId) {
Thread t = new Thread("MyService(" + startId + ")") {
#Override
public void run() {
_onStart(intent, startId);
stopSelf();
}
};
t.start();
}
private void _onStart(final Intent intent, final int startId) {
//Your Start-Code for the service
}
For API Levels 5 and Above
public void onStart(Intent, int) was deprecated at API level 5. This should be replaced with public int onStartCommand(Intent, int)
#Override
public int onStartCommand(final Intent intent, final int startId){
//All code from 'onStart()' in above placed here as normal.
}
private void _onStart(final Intent intent, final int startId) {
//Your Start-Code for the service
}
I do not think you can start your service in a new thread, but what you can do is start a new thread in your service.
This is because like the activity, the service has life cycle methods that run on the main thread.
So your service will run on the main thread but it will do the heavy lifting on a new thread that it creates when ever it needs to.
I hope it helps..
Citing from http://developer.android.com/reference/android/app/Service.html
"Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done."
In my project, i have someone like this and it's work:
Thread welcomeThread = new Thread() {
#Override
public void run() {
try {
super.run();
while (isMyServiceRunning() != true) {
sleep(100);
}
} catch (Exception e) {
System.out.println("EXc=" + e);
} finally {
Intent i = new Intent(getApplicationContext(), MainPage.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
}
};
welcomeThread.start();