Application variables in service - android

I create the app with a foreground service. The service runing in another process and thread.
The Application class have an Array and have public method getArray. Service can access to Application and call method getArray.
App started, array fill and service started.
If app change the array, service return the array created at start app.
How i can update the array in the service?
on service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(mThread != null)
mThread.interrupt();
mApplication = (Application) getApplication();
mTaskManager = mApplication.getTaskManager();
TaskArray lTasks = mTaskManager.getAll();
// always return same size
Log.d(mLogTag, "onStartCommand " + lTasks.size());
createThread();
mThread.start();
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
RESULT:
I was found the reason of getting a copy of applicaton object in my app. This is happening because getApplicationContext() return the context of the single, global Application object of the current process.
For each process created a copy of application object.

Get the context of Application class by using getApplicatonContext() in your service class by writing this line ((YourApplicatonClassName)getApplicationContext()).getArray() and set the new data value .
It is better, if possible, to share your code so that I can understand what you exactly want.
Thanks

Related

Service - (After killing application)

I want to start an Android Service after killing the application and close service after done specific method.
If it's possible then a snippet or a sample would be very welcome.
In Android Studio:
Choose File > New > Service > Service.
Give it a name then click finish.
It will now create a new class with the name you entered and register it in the manifest for you.
All you have to do now is override onStartCommand and return the integer constant START_STICKY to let the system know you would like the service to be running even after the application is removed from recents...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service started!", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
Now you can stop the service anywhere in your code calling stopSelf();

Best approach to execute service in Android

I have a service that have an variable life time. It may execute from 5 minutes to 2 hours (for example). So I'm looking for the best approach to do that, and my service must achieve the following features:
Send (to my server) lat-long every 5 seconds and some extra information (string's, boolean's and int's)
I have tried a "normal" service and tried to do something like this to achieve this:
public class MyFiveSecondsService extends Service {
private Handler handler;
Runnable r = new Runnable() {
#Override
public void run() {
//here send my new data
}
};
public void onCreate(){
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(handler == null){
handler = new Handler();
}
handler.post(r);
return super.onStartCommand(intent, flags, startId);
}
}
Actually that code works, but I got some performance problems with that approach, so I tried to do something like this:
public class SendUniquePositionIntentService extends IntentService {
public SendUniquePositionIntentService() {
super("co.bomboapp.Service.IntentService.SendUniquePositionIntentService");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleIntent(Intent intent) {
//do the logic here
}
}
public class MyFiveSecondsService extends Service {
private Handler handler;
Runnable r = new Runnable() {
#Override
public void run() {
//call my SendUniquePositionIntentService here
}
};
public void onCreate(){
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(handler == null){
handler = new Handler();
}
handler.post(r);
return super.onStartCommand(intent, flags, startId);
}
}
And that approach haven't worked, when I had closed the app any service kept running. So before start any other attempt to achieve this, I want some direction, what's the best approach to do this "infinite loop service" and keep the performance?
I'm using Android 4.1 as min API, and targeting 5.0 API.
My test device is a Nexus 5 running Android 6.
Right now I'm using parse.com as database.
"I have tried a "normal" service...but I got some performance problems"
By default, a service runs on the application's main thread, so when you create a handler with
public int onStartCommand(Intent intent, int flags, int startId) {
if(handler == null){
handler = new Handler();
}
...
}
the handler is associated with the main thread's Looper and all messages and runnables are delivered and later executed on the thread. That's the reason of the "performance problems". From the documentation:
Remember that if you do use a service, it still runs in your application's main thread by default...
Regarding the second approach and the part
"...when I had closed the app any service kept running"
you haven't mentioned how exactly you "close" the app, but what I can see is
public int onStartCommand(Intent intent, int flags, int startId) {
...
return super.onStartCommand(intent, flags, startId);
}
which means that if the system kills the service it, by default, will be recreated. So if "closing" your app means killing it, the following chain of actions takes place:
The system recreates MyFiveSecondsService,
onStartCommand() is called and the handler posts the runnable
within the run() method SendUniquePositionIntentService is started
From the documentation of onStartCommand():
the default implementation calls onStart(Intent, int) and returns either START_STICKY or START_STICKY_COMPATIBILITY.
Note that starting a service from another one (like starting SendUniquePositionIntentService from MyFiveSecondsService in your case) is redundant unless you intended to.
The final part of your question is confusing to me. On one hand it doesn't work for you because "...any service kept running" but, on the other hand, you'd like "do this "infinite loop service""...?
If you only need to send such information as "strings, booleans and ints" to a server (without any feedback to the component that started the service), I suppose it's simply enough for you to use IntentService. This is a "out-of-box" framework that does its work on a background thread (letting you avoid freezing the main thread) and stops itself once it's done. As an example you can use the documentation on IntentService - it's well written.
Also note that the behaviour of a service after killing it by the system depends on the flag returned by onStartCommand(). E.g. use START_NOT_STICKY to not recreate the service after killing the app or START_REDELIVER_INTENT to recreate it with the last Intent redelivered.

getApplicationContext() returns null in a Service

I have a Service in it's own process, I've declared it in manifest like that:
<service
android:name="com.discountscatcher.util.PointService"
android:configChanges="orientation"
android:process=":pointservice" >
</service>
But onStartCommand I was trying to get an ApplicationContext, but it always returns null, what I can forget?
public int onStartCommand(Intent intent, int flags, int startId) {
android.os.Debug.waitForDebugger();
Context mContext = getApplicationContext();
return Service.START_STICKY;
}
and I starting it like that:
startService(new Intent(getApplicationContext(), PointService.class));
in Myactivity OnCreate
any ideas?
You are running your Service in a different process so it has no communication with the Actual Application process..
Try to remove this line from your service
android:process=":pointservice"
After your application is finished Application context is becomes null. At most situations there is no need to run the service in a different process. Also it is not recommended.
For more information check here
Service in another process
service reference Example2

Way to share data with service in android

I have an application where user will choose whether he wants Vibrate or Silent mode. And from the Main Activity I am passing the data as part of Intent to the service (the service is always running).
In the onStartCommand method of service, I get the data for first time and everything works fine. But when I exit the application, after some time may be the service's onStartCommand method is again invoked with no data in the Intent (may be Launcher or android OS is doing it).
Since I am setting a local String variable with data from Intent, I get Null Exception when the onStartCommand method is invoked by OS.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(mode == null) {
mode = (String) intent.getExtras().get("mode");
}
return super.onStartCommand(intent, flags, startId);
}
Now my problem is how to get the data from activity for the first time and then refer to it in various member methods of service class.
I have tried making the mode variable as static but same issue. Looks as if OS will unload service class at its discretion and then load it back and invoke onStartCommand with plain Intent.
You must use a SharedPreference to save the state of the variable Vibrate or Silent mode. Here a possible solution:
SharedPreferences preferences = getApplicationContext()
.getSharedPreferences("preferences_name", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("mode", "silent"); // Silent Mode
// editor.putString("mode", "vibrate"); //Vibrate Mode
editor.commit();

How to store an object's state when a service is restarted

My application launches a service which spawns a thread. The thread does some polling every 5 seconds. Android can restart my service as it sees fit. I am trying to store the polling thread so when the service is restarted it can use the existing polling thread.
Here's the onStartCommand() method:
public int onStartCommand(Intent intent, int flags, int startId)
{
if(intent == null)
{
Log.d("screener", "onStartCommand was called with null intent. System must've killed and restarted service...?");
}
else
{
processToMonitor = intent.getStringExtra("com.screener.processToMonitor");
Log.d("screener", "onStartCommand was called");
}
if(pollThread == null)
{
poller = new Poller(this, wakeLock, processToMonitor);
pollThread = new Thread(poller);
pollThread.start();
Log.d("screenon", "polling thread was not already running. Going to start it");
}
else
{
Log.d("screener", "polling thread has already been running. Not going to restart it");
}
return START_STICKY;
}
It appears that when the passed Intent object is null, this signifies the service has been restartedm so I can successfully detect this scenario. The object I would like to store is poller (or pollerThread which encapsulates the poller). I have tried making it static which didn't work. I also overrode Application and stored an instance in there, but it is still not persisted.
So, how do I store my object when the service is restarted? Or, do I accept that Android cleans everything up and simply restart the thread?
Why do you want to store the thread? Let it "die" and once your service is restarted a new poller thread will start.

Categories

Resources