I want to stop my WakefulService when I close a special Activity AND when I close the whole app. Therefore I wrote this into onDestroy() and in the function which is called in onBackPressed()
stopService(new Intent(getApplicationContext(), GcmIntentService.class));
But the service is still running. Can anyone help me?
Service:
<service android:name="com.flipflopdev.epvp_aj1987_chat.GcmIntentService" />
If you want your app to stop responding to GCM messages, you will need to disable the BroadcastReceiver that is set up to receive the GCM broadcast. You can disable it via setComponentEnabledSetting() on PackageManager. Just remember that you will need to re-enable it again later to receive GCM messages again.
You should wait for the task to finish, look here:
Proper way to stop IntentService
to make task abort, set some global variable (ie. in sharedpreferences) which will indicate that task should be cancelled/aborted. Then IntentService will close on its own. Another possibility is to implement Abort as a task:
// Pseudocode for example cancellable WakefulIntentService
public class MyService extends WakefulIntentService {
AtomicBoolean isCanceled = new AtomicBoolean(false);
public static void cancelTasks(Context context) {
Intent intent = new Intent(context, SynchronizationService.class);
intent.putExtra("action", "cancel");
context.startService(intent);
}
public MyService () {
super("MyService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.hasExtra("action")) {
// Set the canceling flag
if ( intent.getStringExtra("action").equals("cancel") ) {
isCanceled.set(true);
}
}
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void doWakefulWork(Intent intent) {
// Clean up the possible queue
if (intent.hasExtra("action")) {
boolean cancel = intent.getStringExtra("action").equals("cancel");
if (cancel) {
return;
}
}
// here do some job
while ( true ) {
/// do some job in iterations
// check if service was cancelled/aborted
if ( isCanceled.get() )
break;
}
}
}
and if you want to abort your service, you call:
MyService.cancelTasks(getActivity());
You could put all this cancelling code into base class to make it look more clean.
Related
I have an application in which I have created a service MyService.class
Now MyService.class is tied to my activity using bindService() but I want my service to run in the background even if activity destroys itself.
So I started the service and then bind it like below:
private void doBindService() {
if (!isServiceBound){
Log.d(LOG_TAG, "Binding Service...");
if (mBtAdapter != null && mBtAdapter.isEnabled()){
Intent intent = new Intent(MyActivity.this, MyService.class);
startService(intent);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
}
In MyActivity's onDestroy method I am unbinding the service
Now my service is running smoothly until the connection with the remote device breaks. I want to pause/sleep/stop this service if connection breaks, then after every 60 seconds it tries to start the service/connection.
I have tried this but doesn't work.
private void stopService() {
doUnbindService();
stopService(new Intent(MyActivity.this, MyService.class));
startService(new Intent(MyActivity.this, MyService.class));
}
Please any help will be much appreciated. Thanks in advance!!!
Try this
create a method that perform the Operation you want
create a Thread or Runnable class
Call the Helper method you created in the run() of the Thread or Runnable
Inside the Service onStartCommand start the Thread if connection is available
thread.wait/sleep if no connection
I'm not sure I have understanding your request.
With this solution you can play, pause and stop service.
And the service do some work every 60seconds
public class MyService extends Service {
public static boolean testConnexion;
private Timer timer;
#Override
public void onCreate() {
super.onCreate();
timer = null;
testConnexion = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (timer != null) {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (testConnexion) {
//StartConnexion
}
}
}, 1000, 60000);
}
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
}
}
In Any activity
To start or stop service.
(Your can call startService many times as you want, there will be just one who will run.)
if (v.getId() == R.id.startService) {
Intent intent = new Intent(this, MyService.class);
startService(intent);
} else if (v.getId() == R.id.stopService) {
Intent intent = new Intent(this, MyService.class);
stopService(intent);
}
To pause action (but not kill the service)
MyService.testConnexion = false;
And for restarting
MyService.testConnexion = true;
Your service is not related to your activity.
If your killing your activity, your service continues to run.
I hope this can help you
Whenever my application is minimized I start a service that is sending pull requests to my HTTP server to check for notifications, when the application is brought back up the service gets terminated (along with the scheduled runnable). All works well until I decided to kill the application (slide it off the screen from the running apps list). Then for some reason the properties of the service get reset (even the static ones) and onStartCommand gets called again with it's first parameter Intent as null which is weird for me.
Here are some parts of the code
public class DnActivity extends Activity {
protected String cookieString = "";
protected String userAgent = "";
protected WebView webview;
#Override
protected void onStop() {
super.onStop();
try {
Intent mServiceIntent = new Intent(this, PullService.class);
mServiceIntent.putExtra("cookieString", cookieString);
mServiceIntent.putExtra("userAgent", userAgent);
startService(mServiceIntent);
} catch (Exception e) {
Log.d("DNev", e.getMessage());
}
}
#Override
protected void onStart() {
super.onStart();
Intent mServiceIntent = new Intent(this, PullService.class);
stopService(mServiceIntent);
}
#Override
public void onCreate(Bundle savedInstanceState) {
...
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
try {
cookieString = getCookieFromAppCookieManager(url);
} catch (Throwable e) {
Log.e("DNev", e.getMessage());
}
}
});
}
}
And the service
public class PullService extends Service {
protected static String cookieString;
protected static String userAgent = "Mobile APP for Android";
protected Service PullService = this;
protected ScheduledFuture interval;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
if (intent.hasExtra("cookieString")) {
cookieString = intent.getStringExtra("cookieString");
}
if (intent.hasExtra("userAgent")) {
userAgent = intent.getStringExtra("userAgent");
}
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
interval.cancel(true);
}
#Override
public void onCreate() {
super.onCreate();
Log.d("DNev", String.valueOf(cookieString));
Log.d("DNev", String.valueOf(userAgent));
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
interval = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
public void run() {
Log.d("DNev", "1");
Log.d("DNev", String.valueOf(cookieString));
Log.d("DNev", String.valueOf(userAgent));
...
As I said, everything works fine until I destroy the activity, then the interval keeps running but cookieString and userAgent become their default values.
I need to be able to persist these values when the activity gets destroyed, how can I do that?
I'm not experienced in neither android nor java development, and I want to apologize if my code made anyone cry blood.
Here is the manifest entry for the service, it resides in <application
<service android:name=".PullService" android:exported="false"/>
All works well until I decided to kill the application (slide it off the screen from the running apps list).
When you kill the app (which I assume Force Stop from i.e. Settings -> Apps) then WHOLE app gets terminated, including its services. Everything stored in variables will go away with the process. If you want it to survive, you need to store it in persistent storage (i.e. in database or shared preferences).
Also I'd save this data once I received it, in onStartCommand() because if onDestroy() will not be called (which is not unlikely for abruptly killed process) then your data would be lost.
I start a service that is sending pull requests to my HTTP server to check for notifications
Don't. Use GCM to actually push notification to the app. Do not pull.
in the DnActivity.onDestroy() method, save the info somewhere, you could have the "shutting down" of the activity control the mServiceIntent and do alterations to it (like shutting it down as well)
For instance:
DnActivity.onDestroy(){
super.onDestroy();
stopService(mServiceIntent);
Intent mServiceIntent = new Intent(this, PullService.class);
mServiceIntent.putExtra("some_value", the_value);
mServiceIntent.putExtra("some_other_value", the_other_value);
startService(mServiceIntent);
}
I want to listen the power key event in the service.
How can in do that ?
Currently I am working with an app, where I need to listen the power button for some events, from a service which is running in a background, even when the app is killed or stopped.
Somehow I can manage to get it.
But when I kill/stop the app, the service is getting stopped.
How can i overcome this ?
Currently the code i am using this :
Service Class:
public class SampleService extends Service
{
SettingContentObserver mSettingsContentObserver;
AudioManager mAudioManager;
private ComponentName mRemoteControlResponder;
private Intent intent;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.v("StartServiceAtBoot", "StartAtBootService -- onStartCommand()");
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onStart(Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
Toast.makeText(getApplicationContext(), "On", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Off", Toast.LENGTH_SHORT).show();
}
}
public void onCreate()
{
mSettingsContentObserver = new SettingContentObserver(this,new Handler());
getApplicationContext().getContentResolver().registerContentObserver
(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver );
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mRemoteControlResponder = new ComponentName(getPackageName(),
StartAtBootServiceReceiver.class.getName());
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new StartAtBootServiceReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void onDestroy()
{
getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
}
}
BroadcastReceiver Class:
public class StartAtBootServiceReceiver extends BroadcastReceiver
{
static boolean wasScreenOn;
private boolean screenOff;
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
wasScreenOn = false;
Toast.makeText(context, "Power Off", Toast.LENGTH_SHORT).show();
}
else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON))
{
wasScreenOn = true;
}
Intent i = new Intent(context, SampleService.class);
i.putExtra("screen_state", screenOff);
i.setAction("com.example.antitheft.SampleService");
context.startService(i);
//
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent i1 = new Intent();
i1.setAction("com.example.sampleonkeylistener.MainActivity");
context.startService(i1);
}
}
}
given above is the sample code and i have created AndroidManifest.xml files also with user's permission but i cannot get the app continue service if it is killed or stopped.
Thanks in Advance.
#Override
public void onDestroy() {
super.onDestroy();
startService(new Intent(this, SampleService.class));
}
This is one way to ensure that service will never stop even user want to destroy it.
This is one Just ONE of ways to achieve what you are trying to achieve.
Secondly, you can try and run service in "foreground" by using startForeground().
Also, make sure that in you return "START_STICKY" (which you are doing in the sample code that you shared and I trust that you are also doing in App's code too :) ) in Services's onStartCommand().
This will ensure that If this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service.
And you may find some additional pointers/hints to make sure your service is not stopped at below link.
How can we prevent a Service from being killed by OS?
Just pick and choose the approach that best suits YOUR Need/implementation.
I created a service and want to run this service always until my phone restarts or force closed. The service should run in background.
Sample code of created service and start services:
Start the service:
Intent service = new Intent(getApplicationContext(), MyService.class);
getApplicationContext().startService(service);
The service:
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO do something useful
HFLAG = true;
//smsHandler.sendEmptyMessageDelayed(DISPLAY_DATA, 1000);
return Service.START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO for communication return IBinder implementation
return null;
}
}
Manifest declaration:
<service
android:name=".MyService"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
</service>
Is it possible to run this service always as when the application pauses and anything else.
After some time my application goes pause and the services also go pause or stop.
So how can I run this service in background and always.
"Is it possible to run this service always as when the application pause and anything else?"
Yes.
In the service onStartCommand method return START_STICKY.
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
Start the service in the background using startService(MyService) so that it always stays active regardless of the number of bound clients.
Intent intent = new Intent(this, PowerMeterService.class);
startService(intent);
Create the binder.
public class MyBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
Define a service connection.
private ServiceConnection m_serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
m_service = ((MyService.MyBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
m_service = null;
}
};
Bind to the service using bindService.
Intent intent = new Intent(this, MyService.class);
bindService(intent, m_serviceConnection, BIND_AUTO_CREATE);
For your service you may want a notification to launch the appropriate activity once it has been closed.
private void addNotification() {
// create the notification
Notification.Builder m_notificationBuilder = new Notification.Builder(this)
.setContentTitle(getText(R.string.service_name))
.setContentText(getResources().getText(R.string.service_status_monitor))
.setSmallIcon(R.drawable.notification_small_icon);
// create the pending intent and add to the notification
Intent intent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
m_notificationBuilder.setContentIntent(pendingIntent);
// send the notification
m_notificationManager.notify(NOTIFICATION_ID, m_notificationBuilder.build());
}
You need to modify the manifest to launch the activity in single top mode.
android:launchMode="singleTop"
Note that if the system needs the resources and your service is not very active it may be killed. If this is unacceptable bring the service to the foreground using startForeground.
startForeground(NOTIFICATION_ID, m_notificationBuilder.build());
In order to start a service in its own process, you must specify the following in the xml declaration.
<service
android:name="WordService"
android:process=":my_process"
android:icon="#drawable/icon"
android:label="#string/service_name"
>
</service>
Here you can find a good tutorial that was really useful to me
http://www.vogella.com/articles/AndroidServices/article.html
Hope this helps
If you already have a service and want it to work all the time, you need to add 2 things:
in the service itself:
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
In the manifest:
android:launchMode="singleTop"
No need to add bind unless you need it in the service.
A simple solution is to restart the service when the system stops it.
I found this very simple implementation of this method:
How to make android service unstoppable
You can implement startForeground for the service and even if it dies you can restart it by using START_STICKY on startCommand(). Not sure though this is the right implementation.
I found a simple and clear way of keeping the Service running always.
This guy has explained it so clearly and have used a good algorithm. His approach is to send a Broadcast when the service is about to get killed and then use it to restart the service.
You should check it out: http://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android
You don't require broadcast receiver. If one would take some pain copy one of the api(serviceconnection) from above example by Stephen Donecker and paste it in google you would get this, https://www.concretepage.com/android/android-local-bound-service-example-with-binder-and-serviceconnection
Add this in manifest.
<service
android:name=".YourServiceName"
android:enabled="true"
android:exported="false" />
Add a service class.
public class YourServiceName extends Service {
#Override
public void onCreate() {
super.onCreate();
// Timer task makes your service will repeat after every 20 Sec.
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
// Add your code here.
}
});
}
};
//Starts after 20 sec and will repeat on every 20 sec of time interval.
timer.schedule(doAsynchronousTask, 20000,20000); // 20 sec timer
(enter your own time)
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO do something useful
return START_STICKY;
}
}
I had overcome this issue, and my sample code is as follows.
Add the below line in your Main Activity, here BackGroundClass is the service class.You can create this class in New -> JavaClass (In this class, add the process (tasks) in which you needs to occur at background). For Convenience, first denote them with notification ringtone as background process.
startService(new Intent(this, BackGroundClass .class));
In the BackGroundClass, just include my codings and you may see the result.
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.widget.Toast;
public class BackgroundService extends Service {
private MediaPlayer player;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
player = MediaPlayer.create(this,Settings.System.DEFAULT_RINGTONE_URI);
player.setLooping(true);
player.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
player.stop();
}
}
And in AndroidManifest.xml, try to add this.
<service android:name=".BackgroundService"/>
Run the program, just open the application, you may find the notification alert at the background. Even, you may exit the application but still you might have hear the ringtone alert unless and until if you switched off the application or Uninstall the application. This denotes that the notification alert is at the background process. Like this you may add some process for background.
Kind Attention: Please, Don't verify with TOAST as it will run only once even though it was at background process.
Hope it will helps...!!
Is there anyway to check if onResume was called from the device waking up from sleep state in Android?
The reason why I need to check that is I don't want it to call a particular method if resumed from sleep state:
#Override
public void onResume() {
super.onResume();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())
&& !SomeCrazyMethodOrPropertyCheckingIfDeviceWakedUpFromSleep) {
processIntent(getIntent());
}
}
You might say "Take that processintent method out of onResume"... It's not an option, NFC P2P mode requires you to process the received NDEF message inside onResume.
I would recommend overriding onNewIntent() to handle the NFC intents:
#Override
public void onNewIntent(final Intent intent) {
setIntent(intent);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
processIntent(intent);
}
}
In processIntent() you can check whether the intent was handled already:
private void processIntent(final Intent intent) {
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
// Log.v(TAG, "Ignoring intent; already treated this intent.");
return;
}
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
// new intent; process it
...
}
Likely this will solve your problem.
I think you can try to do something with ACTION_SCREEN_ON :
register a receiver for it (you need to it in code, it won't work in manifest).
in the onReceive do something like:
MY_FLAG_JUST_WAKE_UP = true;
and in the onResume() :
if(!MY_FLAG_JUST_WAKE_UP){
doStuff();
}
MY_FLAG_JUST_WAKE_UP = false;
But, it need to be tested, I don't know if you will always receive the intent before the onResume() get called.