Other way for getActivity() use in service Android java - java

In my PollFragment.java that able to call new PollTask((MainActivity)getActivity()).execute((Void)null);
And in my PollTask.java
public PollTask(MainActivity activity){
super(activity);
TerminalCfg terminalCfg = Global.getTerminalCfg();
terminalId = terminalCfg.getTerminalId();
retailerAcc = terminalCfg.getRetailerAcc();
internalId = APIUtil.getInternalId(activity);
username = APIUtil.getUsername(activity);
}
And now I want to call the new PollTask((MainActivity)getActivity()).execute((Void)null);
in MyBackgroundService with extends Service like below :
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
new PollTask((MainActivity)getActivity()).execute((Void)null);
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
Is there any other way to replace the getActivity() to call the method?

A Service is a separate component from an Activity and thus you cannot get a reference to it using getActivity(). Services are designed for doing work not visible to the user, including (but not limited to) background work on a separate thread from the UI thread. Services are more robust and offer more control over what work is being performed that is not visible to the user. They do not require an Activity to run.
An AsyncTask is a simple way of doing work from inside an Activity on a separate Thread from the UI thread.
Basically, you dont want or need an AsyncTask in a Service.
Instead, in your Service you should either spawn a Thread, or use IntentService which will handle creating a worker Thread for you. Then when you are finished, send an intent back to the Activity either by starting it or using a LocalBroadcast
Alternatively, you can tie a Service to an Activity and provide methods that the Service and Activity can call directly on each other through an IBinder interface. These are called bound services and will only be alive as long as the Activity is alive.
Try an IntentService
I think your best bet is to try learning how to use an IntentService
http://developer.android.com/reference/android/app/IntentService.html

Related

Avoid automatic restart of Service using StartCommandResult.Sticky/NonSticky

What I have going on is that I made a simple service in Xamarin.Android which for now simply just sends a single Local Push Notification.
In my main application (MainActivity) I have made a statement that checks whether or not this service runs. If it does not, I will simply start the service, otherwise I'll do nothing.
if (UtilityController.IsServiceRunning(typeof(WidgetService), this) == false)
{
StartService(new Intent(this, typeof(WidgetService)));
}
This works fine aswell. No problems here.
Now, the issue is when it comes to my Service being ran multiple times.
[Service]
public class WidgetService : Service
{
public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
{
SendPushNotification();
return StartCommandResult.Sticky;
}
//Other functions such as OnBind, OnDestroy etc..
}
Here I have a service that is straight forward. It's only purpose is to send a Push Notification in the function SendPushNotification(); which it does.
However, when I'm using different StartCommandResult enums, my OnStartCommand function gets triggered in different ways (which I assume is because it restarts the service):
Using StartCommandResult.Sticky makes the Service restart itself every time I close/kill the main app.
Using StartCommandResult.NotSticky makes the Service restart itself every time I start the main app.
This is a problem. I want the Service to only be run ONCE while it's still running. I don't want it ever to be restarted unless I specifically tells it to.
How do I achieve this?
Based on the info you have provided, what is happening should be something like this:
While using StartCommandResult.Sticky: As you have described, service is being restarted when you kill the service process. But this time OnStartCommand is being called with a null intent.
While using StartCommandResult.NotSticky: In this case, service is being stopped when you kill the process but notifications are not removed. When you start the app again, since service is not started, it will start a fresh from your activity.
What you could do depends on the behaviour you do expect from your app. If you want the service to stop when you close/kill the app, you can do something like this:
[Service]
public class WidgetService : Service
{
bool isStarted;
public override StartCommandResult OnStartCommand(Android.Content.Intent
intent, StartCommandFlags flags, int startId)
{
if (!isStarted)
{
SendPushNotification();
isStarted = true;
}
return StartCommandResult.NotSticky;
}
//Only will be called if stopWithTask attribute is set to false
public override void OnTaskRemoved(Intent rootIntent)
{
// Remove the notification from the status bar.
base.OnTaskRemoved(rootIntent);
}
public override void OnDestroy()
{
// We need to shut things down.
// Remove the notification from the status bar.
isStarted = false;
base.OnDestroy();
}
}
And stop the service when you are done with it or app is being closed. But if you want to keep the service running, since you are displaying a notification, I would suggest to make your service a foreground service

Don't destroy a bound Service on Activity destroy

Currently, I need a bound (Music)Service, because I need to interact with it. But I also want it to not be stopped, even when all components have unbound themselves.
As the Android Developer Guide says
"[...] Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed."
The Guide also says
"[...] your service can work both ways—it can be started (to run indefinitely) and also allow binding."
In my application, the service is started when the application starts.
I want to have this service destroyed only by a user-click on a close-button I am displaying in a custom notification. But currently, when I am destroying my MainActivity the service also stops.
This is where I am now, this is called when I want to create my Service:
public void createServiceConnection(){
musicConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder binder = (MusicService.MusicBinder)service;
musicSrv = binder.getService();
attachMusicService();
}
};
}
...which calls this:
public void attachMusicService(){
playerFragment.setMusicService(musicSrv);
musicSrv.attach(context); //need this for my listeners, nevermind
bindService(context);
}
...which calls this:
public void bindService(Context act){
if(playIntent==null){
playIntent = new Intent(act, MusicService.class);
act.startService(playIntent);
act.bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
}else{
act.startService(playIntent);
act.bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
}
//finished. I can do stuff with my Service here.
}
Have I misunderstood something?
I feel like the service should keep running, even the activity is destroyed, because I first made a started service and then bound to it.
Bind to your service from custom Application class. I don't think you can keep service alive after activity that's bound to it is destroyed (when onDestroy is called). You can keep service alive if activity pauses (onPause) by calling startForeground from service
Seems like the code was correct.
According to this Question I found out that my problem was the notification I displayed, wich is pretty interesting.
Seems like that a Service that is created for running indefinitely needs to have a Notification wich is displayed by startForeground(NOTIFY_ID, notification);.
I showed my notification with notificationmanager.notify(NOTIFY_ID, notification); before, now I have
`notificationmanager.notify(NOTIFY_ID, notification);
startForeground(NOTIFY_ID, notification);`
and the service won't stop anymore after all my bound Activities are destroyed.

Android - Communication between Activity and Service in another Thread

I am writing a Tracking App in Android.
I have got a Service implements LocationListener, which does all the stuff with location and writing to database, and Activity.
I would like to run Service in new thread to optimize my app. I want also to send both sides messsages from Service to Activity, which will show info about location.
I bind service, like it is mentioned in Bind to Service section and implement using a Messenger. Next I tried to do:
Thread t = new Thread(){
public void run(){
bindService(new Intent(this, GPSLogger.class), mConnection, Context.BIND_AUTO_CREATE);
}
};
t.start();
App is working, but all the GPSLogger stuff is doing in main thread.
Is it any way to repair this?
Regular services run in main thread.
You can use IntentService instead. It is a job queue with a single bg thread.
If you insist on using the base Service class then you'll have to spawn your own threads.

ScheduledExecutorService android doesn't work on boot

I want to launch a ScheduledExecutorService on boot for checking my database all days.
I should launch this service at boot because if user doesn't launch the app this service couldn't work.
So when I launch my ScheduledExecutorService when app started it's okay but on boot ScheduledExecutorService seems not to work.
The BroadcastReceive on boot is working.
This is my code
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
Toast.makeText(context, "Ca passe", Toast.LENGTH_LONG).show();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
Log.e("sc", "Ca passe");
Toast.makeText(context,"scheduler fonctionne", Toast.LENGTH_LONG).show();;
}
},10, 10, TimeUnit.SECONDS);
}
}
Do you have any idea ?
You need to read the documentation. Especially the documentation on the BroadcastReceiver lifecycle:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the NotificationManager API. For the latter, you can use Context.startService() to send a command to the service.
If you need to use an Executor, host it in an actual Android Service. Otherwise, consider using AlarmManager to wake up your Service.

Using an Android Service to handle a network connection

I'm working on an Android app that needs to maintain a network connection to a chat server. I understand that I can create a service to initiate the connection to the server, but how would the service notify an Android Activity of new incoming messages? The Activity would need to update the view to show the new messages. I'm pretty new to Android, so any help is appreciated. Thanks!
Can you pass a handler to your service?
First, define your handler as an interface. This is an example, so yours may be more complex.
public interface ServerResponseHandler {
public void success(Message[] msgs); // msgs may be null if no new messages
public void error();
}
Define an instance of your handler in your activity. Since it's an interface you'll provide the implementation here in the activity, so you can reference the enclosing activity's fields and methods from within the handler.
public class YourActivity extends Activity {
// ... class implementation here ...
updateUI() {
// TODO: UI update work here
}
ServerResponseHandler callback = new ServerResponseHandler() {
#Override
public void success(Message[] msgs) {
// TODO: update UI with messages from msgs[]
YourActivity.this.updateUI();
}
#Override
public void error() {
// TODO: show error dialog here? (or handle error differently)
}
}
void onCheckForMessages() {
networkService.checkForMessages(callback);
}
and NetworkService would contain something like:
void checkForMessages(ServerResponseHandler callback) {
// TODO: contact server, check for new messages here
// call back to UI
if (successful) {
callback.success(msgs);
} else {
callback.error();
}
}
Also, as Aleadam says, you should also be away that a service runs on the same thread by default. This is often not preferred behavior for something like networking. The Android Fundamentals Page on Services explicitly warns against networking without separate threads:
Caution: A service runs in the main thread of its hosting process—the service does not
create its own thread and does not run in a separate process (unless you specify
otherwise). This means that, if your service is going to do any CPU intensive work or
blocking operations (such as MP3 playback or networking), you should create a new thread
within the service to do that work. By using a separate thread, you will reduce the
risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
For more information on using threads in your service, check out the SO articles Application threads vs Service threads and How to start service in new thread in android
Did you check the Service API page: http://developer.android.com/reference/android/app/Service.html ?
It has a couple of examples on how to interact with a Service.
The service runs on the same thread and the same Context as the Activity. Check also here: http://developer.android.com/reference/android/content/Context.html#bindService%28android.content.Intent,%20android.content.ServiceConnection,%20int%29
Finally, take a look also at Lars Vogel's article: http://www.vogella.de/articles/AndroidServices/article.html
One common and useful approach is to register a broadcast receiver in your Activity, and have the Service send out notification events when it has useful data. I find this to be easier to manage than implementing a handler via a callback, mainly because it makes it easier and safer when there is a configuration change. If you pass a direct Activity-reference to the Service then you have to be very careful to clear it when the Activity is destroyed (during rotation, or backgrounding), otherwise you get a leak.
With a Broadcast Receiver you still have to unregister when the Activity is being destroyed, however the Service never has a direct reference to the Activity so if you forget the Activity will not be leaked. It is also easier to have the Activity register to listen to a topic when it is created, since it never has to obtain a direct reference to the Service...
Lars Vogel's article discusses this approach, it is definitely worth reading! http://www.vogella.com/tutorials/AndroidServices/article.html#using-receiver

Categories

Resources