I am having an app that has to get the location of where I am in many activities. I found this very helpful complete piece of code here. Its how to Get Current Location Using Background Service. I implemented it in my code. The first time it worked ok. The next, when it reached this if
if (mPref.getString("service", "").matches("")) {
medit.putString("service", "service").commit();
Intent intent = new Intent(getApplicationContext(), GoogleService.class);
startService(intent);
} else {
Toast.makeText(getApplicationContext(), "Service is already running", Toast.LENGTH_SHORT).show();
}
I get the message that service is already running. Why this happens? I have closed and reopened the app, why the service still running? Help pls, its very important, thank you
If you use SharedPreferences to persist the info about your Service then the info survives the app restart and so your if condition is always false (when you do mPref.commit() you save the key pair to the file).
Related
My Android application starts a local foreground service (in the same process as my activity). The service have to stay alive, even if the system destroys the activity due low memory.
Next time a user starts the app, I need to check whether the service is running or not.
I tried to store state in public static boolean Started = false; flag in service class (I know that it is bad practice).
My activity starts in the process where service is running. I thought, that static constructor is called ones. So, I would be able to check this flag in activity. However, static data is reinitialized to defaults.
Could any one give me a cue about this behavior?
here is just an example how I restart the service when apps come forground
public void storeLastLocation() {
if (!isStoreLocationActive){
Log.d("IQ MA", "storeLastLocation() called");
String access_token = Configs.access_token;
Intent intent = new Intent(MainActivity.this, StoreLocationService.class);
intent.putExtra("access_token", access_token);
stopService(intent);
startService(intent);
isStoreLocationActive = true;
}
}
then store boolean on service is running
I just recently added the capability of my app to check for updates on our local server (this app is not published in the Google Play store. It's going to be used internally and there is no internet connection where it will be used. Don't ask. That's how it is :) ). I keep track of updates by checking a certain table in SQL Server and if my app's version is lower than what is indicated in this table, I download the new APK from an internal website (LAN only) then install the APK. I also have another application in the device that listens for PACKAGE_ADDED broadcasts. I can capture the broadcast successfully.
The problem is, after installation, the broadcast receiver starts the app by calling the following.
public class PackageInstalledBroadcastReceiver extends BroadcastReceiver {
private final String MY_PACKAGE_NAME = "com.company.packagename";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
String packageName = intent.getData().getSchemeSpecificPart();
if (packageName.equalsIgnoreCase(MY_PACKAGE_NAME)) {
Intent i = new Intent();
i.setClassName(MY_PACKAGE_NAME, MY_PACKAGE_NAME + ".LoginActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
}
But it takes a long time for the app to start. The user might think that nothing is happening, so he/she can start the app manually by clicking the app's icon. If the user clicks the app's icon, the app starts immediately. After a while, the activity that the broadcast receiver started is also opened. So now, I end up with two instances of my app in the same activity (LoginActivity). I can say that this is the case, because if I press the Back key on the device from the LoginActivity, I still end up in another LoginActivity and if I press the Back key again, I end up on the device's desktop.
You have two problem in your question:
The fist, why your BroadcastReceiver take a long time to start your activity.
It have not enough information for stoving this.
The second your want to make your activity have a single instance.
Android provide a way to do that:
Step one: Visit your application androidmanifest file
Step two: Find your activity declaration.
Step there: Add the following property android:launchMode = "singleInstance"
The reference here:
P/s: If you could provide my some more information of your fist problem. Please create a new question. Hope you resolve it.
I have added Google Now search within my application. The way it works is, the user types something in the EditText object and oonce they press the button, this intent runs -
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
String term = searchInput.getText().toString();
intent.putExtra(SearchManager.QUERY, term);
startActivity(intent);
However I am having issues killing the service after the intent has been launched.
calling finish();after the intent will not work unless I am directing the intent to a different class itself.
Here's a video preview fo what I mean, you can clearly see I am pressing home to close the app but when I reopen it . It opens to the Google Now app. But when pressing back, it stops. How exactly can I get the intent to stop after I press the home key?
And my app is a dialogue type app so I have excluded it from the recent menu because of allot of reasons. Everywhere else the app kills itself as soon as the user exits it but here the service keeps running.
Video - Video Preview
I have also tried many questions answers, have researched but nothing has helped so far. I may be doing something wrong. Could someone kindly help me out here, thank you very much! :)
A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continues to run after onStartCommand() returns. So, the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().
use stopSelf() upon compleetion of task assigned to service.
And if you want to finishs ervice when application finishes, then in onDestroy(), call stopService() after checking whether its running or not, such method can be used:
public static boolean isMyServiceRunning(Class<?> serviceClass, Activity pActivity) {
ActivityManager manager = (ActivityManager) pActivity.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
to stop service from activity use below code:
stopService(new Intent(yourMainActivity.this,yourIntentService.class));
or you can write condition in service to stop itself like below:
if(check your condition here)
stopSelf();
You don't have to stop an IntentService - it will terminate itself when it has no more work to do.
It runs on separate worker thread.
Multiple intents are queued on the same worker thread.
So even if your Activity was destroyed from where this service was started it will continue performing its tasks until all the queued ones are complete and after completion it is automatically terminated.
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand().
stopService() : Request that a given application service be stopped. If the service is not running, nothing happens. Otherwise it is stopped. Note that calls to startService() are not counted -- this stops the service no matter how many times it was started.
Note: that if a stopped service still has ServiceConnection objects bound to it with the BIND_AUTO_CREATE set, it will not be destroyed until all of these bindings are removed.
I am asking a vexed question that has been (partially, to my mind) addressed here and here. Let's say like in many examples we want to create a music application, using (say) a single activity and a service. We want the service to persist when the Activity is stopped or destroyed. This kind of lifecycle suggests a started service:
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
Ok, but we also want to be able to communicate with the service, so we need a service binding. No problem, we have both a bound and started service as this answer suggests:
At activity startup (or some other point) we call startService()
After that we call bindService() to obtain the IBinder interface, and proceed from there.
So far so good, but a problem arises from the fact that when the activity starts, we do not know if the service is around or not. It may have been started or it may not have been. The answer could be something like:
At startup, try to bind to the service (use bindService() without the BIND_AUTO_CREATE flag)
If that fails, then start the service using startService(), and then bind to it.
This idea is premised on a particular reading of the docs for bindService():
Connect to an application service, creating it if needed.
If zero flag means "service is not really needed" than we are OK. So we try something like this using the following code:
private void connectToService() {
Log.d("MainActivity", "Connecting to service");
// We try to bind to an existing service
Intent bindIntent = new Intent(this, AccelerometerLoggerService.class);
boolean bindResult = bindService(bindIntent, mConnection, 0);
if (bindResult) {
// Service existed, so we just bound to it
Log.d("MainActivity", "Found a pre-existing service and bound to it");
} else {
Log.d("MainActivity", "No pre-existing service starting one");
// Service did not exist so we must start it
Intent startIntent = new Intent(this, AccelerometerLoggerService.class);
ComponentName startResult = startService(startIntent);
if (startResult==null) {
Log.e("MainActivity", "Unable to start our service");
} else {
Log.d("MainActivity", "Started a service will bind");
// Now that the service is started, we can bind to it
bindService(bindIntent, mConnection, 0);
if (!bindResult) {
Log.e("MainActivity", "started a service and then failed to bind to it");
} else {
Log.d("MainActivity", "Successfully bound");
}
}
}
}
And what we get is a successful binding every time:
04-23 05:42:59.125: D/MainActivity(842): Connecting to service
04-23 05:42:59.125: D/MainActivity(842): Found a pre-existing service and bound to it
04-23 05:42:59.134: D/MainActivity(842): onCreate
The global question is "Am I misunderstanding bound versus started services and how to use them?" More specific questions are:
Is it the correct understanding of the docs to think that zero flag passed to bindService() means "Do not start the service"? If not, is there no way to call bindService() without starting the service?
Why does bindService() return true even if the service is not running? In this case it doesn't seem like the service has been started, based on Log calls.
If there the previous point is the correct/expected behavior of bindService(), is there a workaround (i.e. somehow ensure that startService is called only if the service is not running?)
P.S. I've moved on from the problem in my own code: I issue startService() calls regardless, since repeated startService() are simply ignored. However, I would still like to understand the issues better.
If you bindService with 0 flag then the service will not start. You can bindService with BIND_AUTO_CREATE flag and if the service is not started, it will be started. However, when you unbindService the service will be destroy.
bindService with 0 flag always returns true.
You can always call startService. If the service is already running then a new service will not be created. The running service onStartCommand will be called.
There should not be any problem if you startService in onCreate and then bindService in onResume and unbindService in onPause.
I have an network app which uses a service to connect to other peers. When you close the application using "Recent apps" it will just close the process and not the service which is actually not bad for I want to be in this way. But it makes a little trouble next time user opens the app. It crashes so user has to again close the up using "Recent Apps" and then try to use the app again. The problem is definitely the running service because if I stop the service before I run it next time. It works just fine !
Actually it is strange for me because I don't start another service at the startup. I start it when user taps on a button. Anyway If it is possible the best way is to being able to use the running service, else, I just want to stop the service on start of my application.
i am new to android and I'm stuck at this point :(
Thanks for help
A service skeleton:
public class MyService extends Service {
public static final String TAG = "MyServiceTag";
...
}
This is part of the starting activity:
processStartService(MyService.TAG);
private void processStartService(final String tag) {
Intent intent = new Intent(getApplicationContext(), MyService.class);
intent.addCategory(tag);
startService(intent);
}
This is part of the stopping activity:
processStopService(MyService.TAG);
private void processStopService(final String tag) {
Intent intent = new Intent(getApplicationContext(), MyService.class);
intent.addCategory(tag);
stopService(intent);
}
Use one static object which indicate whether service is running or not.
otherwise second option I found How to check if a service is running on Android?,
if(startService(someIntent) != null) {
Toast.makeText(getBaseContext(), 'Service is already running',Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getBaseContext(), 'There is no service running, starting service..', Toast.LENGTH_SHORT).show();
}