I have a service that I am trying to run constantly as long as the user has it on. The problem is the service uses a ton of memory; I'm guessing because it notifies the users and displays images constantly. So I put the bulk of my code in another activity. The service just calls the activity.
The issue is that I'm trying to use the return Start_Sticky to restart the service when it needs to. It takes about 2 hours before it uses up enough memory to need to restart. When it does restart it doesn't do the onStartCommand am I missing something?
public class AUTOAlarmService extends Service {
#Override
public void onCreate() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent DI = new Intent(getBaseContext(), AUTOSERVICES.class);
DI.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(DI);
return START_STICKY;
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
I think you should reconsider some work done because your service is taking too much resources and that shouldnt be happening any way. There are many applications with a lot of services but non have problem of restarting the device for that matter.
However if you want to restart a service you have to stop and then start the service again.
stopService(new Intent(this, YourService.class));
startService(new Intent(this, YourService.class));
Hope it helps.
Related
i'm trying to make a very simple service that plays an audio file by putting a button that its onClick() -> starts the service which in turn plays the sound.
but when i destroy the activity the song stops ( i can't tell Service state)[that i put a toast in onDestroy method in Service class , and it didn't come out.]
Any One Can HELP ?!!
AndroidManifest
<service android:name=".ExampleService"
android:enabled="true"
android:exported="true"
></service>
ExampleService.java
public class ExampleService extends Service {
MediaPlayer mpService;
private final static String TAG="ExampleService";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mpService.start();
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
mpService=MediaPlayer.create(this,R.raw.lwyashko);
Toast.makeText(this,"*** STARTED *** ",Toast.LENGTH_SHORT).show();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public void onDestroy() {
Log.d(TAG,"onDestroy was Called ");
Toast.makeText(this,"Service Destroyed",Toast.LENGTH_SHORT).show();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
MainActivity.java
playService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
i=new Intent(getApplication(),ExampleService.class);
startService(i);
}
});
As of API 26, only foreground services will usually be allowed to run without an Activity still active. You make a service a foreground one by calling startForeground() within the service. You will need to create and provide a notification in the call. Here's the relevant documentation page.
Normally, after the service is started by startService, the service will not be destroyed after the activity is closed. However, if the user manually cleans up the task, the entire APP process will be closed and the Service will stop.
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 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.
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...!!