I will do something when service stopped in my app
for example:
i have a countdown code in my service,and then i will when that countdown stopped random button set visible.
i don't know how i can do something by service,i can't set button in service's body so how i can set it?and where i should do it?
in this following code i wrote my countdown in //your code line but i don't know how i can set button visible when count down stopped
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
strong text // your code
return Service.START_FLAG_REDELIVERY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
What you are trying to do is communicate between a running service and an Activity. There are multiple ways to do this. The most easiest would be to pass an event from the service and catch that event in the activity. You can implement it from scratch or use an Event Bus. I would recommend using this library EventBus. Using this library you can pass an object containing some info (about what happened in the service) to the activity and based on that you can perform the action you need. I'm not posting any code. Please try doing it yourself, it will be a good learning experience.
Related
I am currently resuming a project I had been working on, and starting from scratch to recreate it.
However, upon creating a Service class, I noticed something - in my old project, a method inside the Service called onStartCommand contains all of the code that needs to be fired, whereas in my new project when I create a Service class, this method is nowhere to be found.
- Do I need to manually ADD this "onStartCommand" method to contain my service code?
- If not, where exactly would my code go? It seems in my "old" project's code, I completely comment-block public TimerService, and pass null into IBinder, and create onStartCommand etc instead.. and I can't quite figure out why.
- While i'm here, can someone please double-check my CountdownTimer code below? and if it's correct, should I be putting it inside of a Thread?
When I create a new Service Class, it looks like this:
public class TimerService extends Service {
public TimerService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
However in my old Project, my Service class looks like this:
public class TimerService extends Service {
/*
public TimerService() {
}
*/
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
intent.getStringExtra("TIMER_VALUE");
String string_timerValue;
string_timerValue = intent.getStringExtra("TIMER_VALUE");
long long_timerValue;
long_timerValue = Long.parseLong(String.valueOf(string_timerValue));
// I DO NOT WANT ANY TICK VALUE, SO GIVE IT FULL TIMER VALUE
long long_tickValue;
long_tickValue = Long.parseLong(String.valueOf(string_timerValue));
new CountDownTimer(long_timerValue, long_tickValue) {
public void onTick(long millisUntilFinished) {
// DO NOTHING
}
public void onFinish() {
Toast.makeText(TimerService.this, "TIMES UP", Toast.LENGTH_LONG).show();
stopService(intent);
}
}.start();
return START_STICKY;
// END OF onStartCommand
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
// END OF ENTIRE SERVICE CLASS
}
THANK YOU!!
Do I need to manually ADD this "onStartCommand" method to contain my service code?
Yes.
can someone please double-check my CountdownTimer code below?
Only create a service when one is absolutely necessary. It is unclear why this service is necessary.
Beyond that:
Use stopSelf(), not stopService(), to stop a service from inside that service.
Examining Intent extras and using START_STICKY is not a good combination. START_STICKY says "if you terminate my process to free up system RAM, please restart my service when possible, but pass null for the Intent". That will cause your service to crash with a NullPointerException.
I'm a student writing some app to understand and study Android Development.
I'm trying to write an app the should work like this:
MapActivity:
Show a map with user position and open Access point in a range.
User and AP position should be received by the "MainClass".
MainClass:
This should do the main work. It should get user position, get open access point from db and insert into the db new open AP found with WifiManager scans.
Now, the MainClass should work in background, on user agree, even if the app is closed.
My questions are:
Should I do MainClass stuff on a new thread or on the UI thread?
Should MainClass be an AsyncTask, Service or other? please tell me why too.
the scan operation return a scan that get executed in a registered receiver. Does it run on UI thread or in a new one?
Thanks in advance.
UPDATE;
So, if i'm not messing what are you saying, the service should look like this:
public class MainService extends Service {
Thread mainThread;
#Override
public void onCreate() {
mainThread = new Thread(new Runnable() {
#Override
public void run() {
....
mainOperation();
....
}
});
mainThread.setPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
mainThread.run();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
does START_STICKY on kill call onStartCommand or onCreate?
Should I do MainClass stuff on a new thread or on the UI thread?
Answer:
You should do on the background thread (new thread) because android does not allow network tasks on UI thread also if you do time taking operation on UI thread UI will freeze
Should MainClass be an AsyncTask, Service or other? please tell me why too.
Answer:
As you clearly said your requirement (MainClass should work in background) you need to use Service because service runs in background even when your app is killed
You should use MainClass.java stuff into a background thread. i.e., Service
Service will trigger data through Broadcast receiver.
Broadcast receiver will send data to MapActivity.java. Registered receiver's onReceive() method always run in the UI thread.
If you want to run MainClass.java stuff in foreground you can use MVP pattern. You should do your stuff into presentation layer.
Background Service will be the best and only solution for your requirements I guess. Because you want your operation to keep running even when your app is closed.
I have a DialogFragment that can be launched from anywhere, let’s call it UploadDialogFragment. This fragment allows the user to accomplish two related tasks:
Upload an image (can take up to 1min)
Upload a JSON object with some text and a reference to the saved image
This two tasks need to be accomplished in sequence - you can’t do 2. without having completed 1.. So what really happens is:
I start uploading the image (1.)
Meanwhile, the user writes the text and adds other info
When all is ready, dismiss the dialog and start the second task (2.).
I used to do this with background tasks, but now I’d like to switch to a Service: the whole operation should be completed even if, after dismissing, I force quit the app.
Current design
In my experience I have always used IntentService, so I am a complete newbie. The current flawed design I am moving forward is something like:
public class UploadService extends Service {
private final Binder binder = new Binder();
public class Binder extends android.os.Binder {
UploadService getService() {
return UploadService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public void completeFirstTask() {
...
}
public void completeSecondTask() {
// wait for first task to complete if necessary...
...
stopSelf();
}
}
And here’s my UploadDialogFragment:
public class UploadDialogFragment extends AppCompatDialogFragment implements
ServiceConnection {
private UploadService uploadService;
private boolean boundService;
#Override
public void onServiceDisconnected(ComponentName name) {
uploadService = null;
boundService = false;
}
private void bindService() {
Intent i = new Intent(getActivity().getApplicationContext(), UploadService.class);
getActivity().getApplicationContext().bindService(i, this, Context.BIND_AUTO_CREATE);
boundService = true;
}
private void unbindService() {
if (boundService) {
getActivity().unbindService(this);
boundService = false;
}
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
uploadService = ((UploadService.Binder) service).getService();
uploadService.completeFirstTask();
}
// THEN, LATER:
// OnClick of a button, I call uploadService.completeSecondTask();
// and this.dismiss();
}
This is deeply flawed right now.
I need to reliably unbind() when the dialog fragment is closed/dismissed/recreating itself, otherwise I am going to leak it because of the ServiceConnection (right?). I don’t know when to do it?. onDismiss, onDestroyView, onSaveInstanceState ... I have tried many options but I often end up with a IllegalArgumentException saying that the service connection is not registered.
The service might never reach the completeSecondTask() part, and so no one is going to stop it, leaking it for no reason. I should probably call stopService() somewhere, but where? These are different scenarios:
I force-quit the app / recreate the fragment after a completeSecondTask() call: the Service should keep going until it ends.
I recreate the fragment without having called completeSecondTask() : the Service should keep going until it ends. (There’s proper logic inside my fragment to handle this)
I force-quit the app without having called completeSecondTask() : the Service should stop.
Questions
Now, you might see this as two questions: how to handle unbind(), and how to handle stopService().
However, because I am finding so hard to set up this little task, I am thinking that this is deeply flawed and I should use a totally different approach. I hope you can shed some light on this for me.
I think i have coded myself into a bit of a corner here. but I will try to explain my issue as best as I can. basically I am building an application on android that is supposed to be a copy of the alarm app on the phone. I have an object that represents the alarm. it includes time, and days as booleans etc. i persist these objects by serializing them and saving them to a file. then, on boot, I have a broadcastreciever which starts a boot service. basically the bootservice has a loop that iterates over my list of alarms. iam trying to call a method on each alarm object called "setSysAlarm()", which is supposed to recreate each android system alarm at the saved time. at present, the "setSystemAlarm" method is only creating a toast for testing purposes. BUT this is causing the application to crash. there is obviously a flaw in my design and I think that trying to use the app context is causing the crash. My thinking is that I should possibly create all alarms via the service through the GUI when is running, aswell as recreating the alarms on boot? therefore alarms creation can be done regardless of wheather the app is running, also the alarms will be created in one place ? below is my boot service code which is executed on boot.
public class BootService extends Service {
private Thread setallarams;
private file_acces_int fileaccess;
private ArrayList<alarm_entity> alarmlst;
private Runnable setalarmsrunnable = new Runnable() {
#Override
public void run()
{
for(alarm_entity alarm : alarmlst)
{
alarm.setSystemAlarm();
}
}
};
#Override
public void onCreate()
{
fileaccess = new file_access_model(getApplicationContext());
alarmlst = fileaccess.readFromFile();
setallarams = new Thread(setalarmsrunnable);
cont = this;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
setallarams.start();
try {
setallarams.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
stopSelf();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
and here is the setSystemAlarm() method from my alarm_entity class. basically this is meant to create a toast on boot but at present the app is crashing
public void setSystemAlarm()
{
Toast.makeText(cont, "hi there", Toast.LENGTH_SHORT);
}
if someone could help me out here id appreciate it. the methods i was using to get the context were
1. pass it in from the bootService. doesnt seem doable to me?
2. cretaing an instance on of Applicationin the constuctor of each alarm_entity and using that as the context. this also seems pretty stupid to me. lol
anyway thanks in advance and sorry for the long winded question!
Anyway, we´ve discussed too much for how You get the Logcat output :) . The basic question is, why You get this error. Maybe this is not the full answer, but I need to show some code. You are initializing Your context inside onCreate() of the service:
#Override
public void onCreate()
{
fileaccess = new file_access_model(getApplicationContext());
alarmlst = fileaccess.readFromFile();
setallarams = new Thread(setalarmsrunnable);
cont = this;
}
But like described in the API:
Do not call this method directly.
I don´t know if this is the reason for Your crash, we have no Logcat, it could be any other reason. But it´s recommended to initialize in onStartCommand(), so put Your initializations inside onStartComand():
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
fileaccess = new file_access_model(getApplicationContext());
alarmlst = fileaccess.readFromFile();
setallarams = new Thread(setalarmsrunnable);
setallarams.start();
.
.
.
The other thing is, I can´t see initializing alarm_entity class, maybe I am blind (?), but I can´t see nowhere that You pass a context to this class. For example, if You are initializing this class, it must be something like this inside Your onStartCommand();
mAlarm_entity = new alarm_entity(this);
Because Service holds context, then simply call this. Delete the onCreate() and then You don´t need to initialize a context, because the service has it allready.
Add this permission to your manifest
> android.permission.RECEIVE_BOOT_COMPLETED
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Android Service makes Activity not responding
I use service to synchronize data between database and view. But the service does not work properly, whenever I use service to work long task, the view stop response (I can't do any event in UI) and I have to wait the service has done. Here is my service:
public class SyncService extends Service{
private static final String TAG = "SyncService";
#Override
public void onCreate()
{
super.onCreate();
}
#Override
public void onDestroy()
{
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent)
{
Log.d(TAG, "call onBind");
return new DataManagerBinder();
}
private class DataManagerBinder extends Binder implements IUserDataManager
{
#Override
public void doProcess(Activity mView)
{
//do some long task (not touch UI thread)
// this will cause the view not response
syncDB();
// update view after process completed
mView.updateViewOnComplete();
}
}
I try to bind this service in client activity
//the interface to handle binder
IUserDataManager viewManager = null;
ServiceConnection serviceConnection = new ServiceConnection()
{
#Override
public void onServiceDisconnected(ComponentName name)
{
Log.i(TAG, "connection closed unexpectedly");
viewManager = null;
}
#Override
public void onServiceConnected(ComponentName name, IBinder binder)
{
Log.d(TAG, "serviceConnection onServiceConnected");
viewManager = (IUserDataManager) binder;
viewManager.doProcess(MyActivity.this);
}
};
Intent intent = new Intent(MyActivity.this, SyncService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Please give me the solution for that. Thanks in advance!
While others have given some responses, I don't know if the main point has been emphasized:
While a Service sounds like something that would automatically run in the background, it does not. It's merely a piece of code that can react to intents without maintaining a UI. However, the UI thread still does the processing for the Service.
By contrast, it looks like what you want, is a Service that sits in the background and does some work in a background thread. You will use the Service class to spawn a new thread, this is typically done on response to some intent, which you can define (usually in your onStart() or something similar). You will probably start a new thread which actually does the work updating the database, etc..., and use your main Service to coordinate to that thread.
As it looks like you also want to communicate with the service, you will have to implement an appropriate Messenger and Handler pair to keep track of messages you pass between the UI and the Service (coordinating a background thread), and also (possibly) some way (also perhaps a messenger) of coordinating between the Service and the background thread.
As others have noted, you can also use AsyncTask to do things on the UI thread and use a background thread "seamlessly."
Read up on the docs regarding services, specifically the "What is a Service?" paragraph. The service runs on the main UI thread. Take a look at AsyncTask, should solve your issue. The work here is done in a background thread, and the results are sent back to the UI thread.
Android closes service after sometime to save resources.
However you can prevent this from happening using something like
int onStartCommand(Intent, int, int){
return START_STICKY;
}
ref this