I have a service start in Activity A with
private void startService() {
Intent pushIntent = new Intent(this, MyService.class);
pushIntent.putExtra(MyService.TYPE_SCREEN, 1);
startService(pushIntent);
}
in my Service I get data from onStartCommand
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
typeScreen = intent.getExtras().getInt(TYPE_SCREEN);
return Service.START_STICKY;
}
I want when change from activity A to activity B, I will update type of screen from 1 to 2 in Service.
How I can do it?
Android only create one instance of a service.
Request that a given application service be started. The Intent can
either contain the complete class name of a specific service
implementation to start, or an abstract definition through the action
and other fields of the kind of service to start. If this service is
not already running, it will be instantiated and started (creating a
process for it if needed); if it is running then it remains running.
So in your case, the service is already running, then you just have to send the intent with the screen 2 extra. It will only call the onStartCommand Override method.
Intent pushIntent = new Intent(this, MyService.class);
pushIntent.putExtra(MyService.TYPE_SCREEN, 2);
startService(pushIntent);
Related
I'm trying to make an Android App that records the user's activity(like where he touches or drags).
Because of the recent change in Android security and permissions, we can't make an app that draws over an another app and records its movements.
So our team decided to solve the problem this way
since the adb shell's permission is root, we can use logcat and the grep tool to parse the logs and find what we want.
create a service that constantly spins up logcat and saves into a file.
create another service that reads the file logcat created, parse, and show the info.
There is currently a problem in our team.
How can we make a service that constantly reads a file and spit out the results?
After that we can do the other jobs more easily.
You can create a service as mentioned in below step to keep the service running all the time
1) In the service onStartCommand method return START_STICKY.
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
2)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);
3)Create the binder.
public class MyBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
4)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;
}
};
5)Bind to the service using bindService.
Intent intent = new Intent(this, MyService.class);
bindService(intent, m_serviceConnection, BIND_AUTO_CREATE);
6)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());
}
7)You need to modify the manifest to launch the activity in single top mode.
android:launchMode="singleTop"
8)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());
I'm trying to do a StartedService in android to send periodically the user location to a server.
Until this moment I managed to create the service and starting it from the 'parent ' application and I don't know how to keep it alive after the application was killed. From what I found on internet the 'StartCommandResult.Sticky' should restart the service if this one is killed but from some reason this is not restarted.
I overried the OnStartCommand:
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
locationTask = new Task(() =>
{
//stuff to do
});
locationTask.Start();
return StartCommandResult.Sticky;
}
And the service is started like this:
Intent intent = new Intent(this.Activity, Class.FromType(typeof(LocationService)));
this.Activity.StartService(intent);
Any suggestions what should I do in order to keep my service alive after the application was killed?
As observation I'm using xamarin to do it, but I won't mind an answer in android(java).
As stated in the official documentation:
A service is "started" when an application component (such as an
activity) starts it by calling startService(). Once started, a service
can run in the background indefinitely, even if the component that
started it is destroyed. Usually, a started service performs a
single operation and does not return a result to the caller. For
example, it might download or upload a file over the network. When the
operation is done, the service should stop itself.
So, starting the service like this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
Will have your service running even while your app is destroyed.
Regarding Service.START_STICKY in the official documentation:
If the system kills the service after onStartCommand() returns,
recreate the service and call onStartCommand(), but do not redeliver
the last intent. Instead, the system calls onStartCommand() with a
null intent, unless there were pending intents to start the service,
in which case, those intents are delivered. This is suitable for media
players (or similar services) that are not executing commands, but
running indefinitely and waiting for a job.
This is how I do it but its in JAVA code.
in your service you should implement a LocalBinder, onStartCommand and onCreate methods.
public class LocalBinder extends Binder {
ServiceName getService() {
return ServiceName .this;
}
}
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
return START_STICKY;
}
The onStartCommand should return START_STICKY;. And also, include this code on your Service:
#Override
public void onTaskRemoved(Intent rootIntent) {
// TODO Auto-generated method stub
Intent restartService = new Intent(getApplicationContext(),this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartServicePI = PendingIntent.getService(getApplicationContext(), 1, restartService, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() +1000, restartServicePI);
}
This will restart your Service on 1 second from the time you close it. Also, dont forget to add your service in your AndroidManifest.xml
<service android:name=".ServiceName"
android:exported="false"
android:stopWithTask="false" >
</service>
Override onStartCommand like this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
For me, everything in the code was right but the problem was with the use of debugging while checking if the service was on. When I use a release version (or just dev version without connecting to the debug), the process is not killed and the service is running normally.
No idea why though. I am using Xamarin Studio 6.0.
i have troubles with my STICKY Service. I call it in my MainActivity.class and bind it:
MainActivity:
Intent intent = new Intent(this, MyService.class);
ComponentName MyCompName= startService(intent);
bindService(intent, MyConnection, Context.BIND_AUTO_CREATE);
and...
MyService
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
I want that this Service runs STICKY and never be closed or restarted. But when i close my Application, the onCreate()-Method of MyService is called and all variables are reseted, and i don´t know why.
BTW: I don´t call stopService!
The difference between STICKY and NON_STICKY services is that STICKY services are restarted after being killed. I don't think it's possible to guarantee that your service will never be restarted - if memory is low it might be restarted.
If you need to preserve the state, you can save variables in a database. To see if the service is being created for the first time or restarted, you can check if the intent in onStartCommand is null.
If you only need to preserve the initial state when the service was created, you can use START_REDELIVER_INTENT which will resend the Intent used to create the service in onStartCommand.
I have an Android application.
In one activity I start a service like this:
Intent startIntent = new Intent(_context, HandlingService.class);
_context.startService(startIntent);
HandlingService is defined as follows:
public class HandlingService extends IntentService
Then inside HandlingService I have this:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, startId, startId);
Log.v(ApplicationName,"HandlingService.onStartCommand");
if ((flags & START_FLAG_RETRY) == 0){
Log.v(ApplicationName,"Service is restarting");
}
return START_STICKY;
}
and this:
#Override
protected void onHandleIntent(Intent sourceIntent) {
Log.v(ApplicationName, "HandlingService.onHandleIntent");
sendSomething();
}
and lastly:
protected void sendSomething() {
while (numberOfTry > 0) {
numberOfTry++;
Log.v(ApplicationName,"HandlingService.sending Something. Try# " + numberOfTry);
}
}
numberOfTry starts in 1.
Then from the activity that starts the service, when I click on a cancel button I call this:
Intent stopIntent = new Intent(CallingActivity.this, HandlingService.class);
CallingActivity.this.stopService(stopIntent);
I see HandlingService.OnDestroy being called, but I keep seeing the log with "HandlingService.sending Something. Try# " and the increasing numbers.
Question: Why it keeps alive if I already stopped it with the call to stopService?
Thanks in advance! Guillermo.
The documentation for IntentService explicitly states that you should not override onStartCommand() in your derived class. You are probably messing up the internal mechanics of the IntentService.
Either derive your class directly from Service or use the framework that IntentService already gives you (for starting/stopping itself).
from IntentService javadoc
public void setIntentRedelivery (boolean enabled)
Sets intent redelivery preferences. Usually called from the constructor with your preferred semantics.
If enabled is true, onStartCommand(Intent, int, int) will return START_REDELIVER_INTENT, so if this process dies before onHandleIntent(Intent) returns, the process will be restarted and the intent redelivered. If multiple Intents have been sent, only the most recent one is guaranteed to be redelivered.
If enabled is false (the default), onStartCommand(Intent, int, int) will return START_NOT_STICKY, and if the process dies, the Intent dies along with it.
I want to pass a string from activiy to service.
Bundle mBundle = new Bundle();
mBundle.putString("MyString", string);
mIntent.putExtras(mBundle);
startService(mIntent);
this is in Activity class
Intent myIntent = getIntent();
String value = myIntent.getExtras().getString(key);
and this is in Service class
It doesn't accept getIntent() method :S I don't know what I'll do
The code in the service must be placed in onStart(Intent intent, int startid) method and the code becomes String value = intent.getExtras().getString(key);
When you start the service using startService(mIntent) the service's onStartCommand is called which is good place to handle the intent.
Move the part of your code that depends on the intent to onStartCommand: http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int)
OnStartCommand was called OnStart before api version 5, follow link to documentation for further information about backwards compatibility in your app.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String value = intent.getExtras().getString(key);
}
Also remember to move heavy code into a background thread that you start in onStartCommand, as otherwise you will run into an Application Not Responding error.