How to execute methods from a running service from broadcast? - android

on a broadcast I want to call a non static method from Service XYZ. The Service is start by the receiver on boot.
Has someone a idea to run methods from this running service?
One solution in this forum is to make the method static and use a singleton pattern to execute. But is there another method? Maybe with a binder?
//EDIT for example i have the following clases:
public class MyService extends Service{
.....
public void method(){
//TODO
}
}
public class MyBroadcastReceiver extends BroadcastReceiver{
.....
public void onReceive(Context context, Intent intent) {
String intentAction=intent.getAction();
if(intentAction.equals(Intent.ACTION_BOOT_COMPLETED)){
//start service
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent);
}
else{
//TODO call method() in MyService
}
}
how can i call the method method()? I know that i can cast with context.getSystemService() system services. But how can i get my own service object?
greetings

You can add an action string to your intent using setAction in the intent that launches the Service. In your service's onStartcommand you can extract the intent's action, and based off that you can execute the method in your service.
You will always send commands to your service using startService this will not launch your service twice. It will either get started once, or the new intent is sent to the service.
So, in your on boot completed section you should set the intent action to whatever you want, and start the service - you can remove the else block completely.
In your Service implement the onStartCommand, extract the intent's action, and based off that action you can just execute your method.

Related

Android Activity communication with IntentService

I need to have a two way communication between my activity and a running IntentService.
The scenario is like this: the app can schedule alarms which on run, start an IntentService which fetches some data from web and process it. There are three possible situations when IntentService finishes:
The app is in focus, which means that when the IntentService will finish, the app needs to refresh its views with the new data.
The app is closed and when opened after IntentService has finished the work, so the app will have access to processed data
The app is opened while the IntentService is running, in which case I need to have a way from the activity to ask the IntentService if its doing something in the background.
For 1. I have already implemented a BroadcastReceiver in my activity which gets registered with the LocalBroadcastManager. When IntentService finishes the work, sends a broadcast and the activity reacts. This works fine
For 2. There is nothing needed to be done
For 3. I don't know what to do. So far I've tried this:
In Activity:
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_SEND_TO_SERVICE));
In IntentService
private LocalBroadcastManager localBroadcastManager;
private BroadcastReceiver broadcastReceiverService = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BROADCAST_SEND_TO_SERVICE)) {
//does not reach this place
//Send back a broadcast to activity telling that it is working
}
}
};
#Override
protected void onHandleIntent(Intent intent) {
localBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BROADCAST_SEND_TO_SERVICE);
localBroadcastManager.registerReceiver(broadcastReceiverService, intentFilter);
.... //do things
}
The problem with my implementation is that n the IntentService the BroadcastReceiver does not fire onReceive. Any suggestions or maybe a simpler way for the Activity to ask the IntentService what it is doing?
LE:
Trying to get atomicboolean.
In Service:
public static AtomicBoolean isRunning = new AtomicBoolean(false);
#Override
protected void onHandleIntent(Intent intent) {
isRunning.set(true);
// do work
// Thread.sleep(30000)
isRunning.set(false);
}
In Activity, restarting the app while service is running:
Log(MyIntentService.isRunning.get());
//this returns always false, even if the intent service is running
On AndroidManifest
<service
android:name=".services.MyIntentService"
android:exported="false" />

Android : How to know if service has finished execution when called from a non-activity class

I have Push Notification receiver class
Am calling LocationService , a service to check for me the location of user and calculate if user is within 1 km radius, and updates a variable in shared pref.
I display the notification
Question : How do I know service has finished execution ? Please note that I can not use bindservice() as service is called from a non activity class
public class PushReceiver extends ParsePushBroadcastReceiver {
public static Context mContext;
#Override
public void onPushReceive(Context context , Intent intent) {
mContext = MyApp.getContext();
//startService(new Intent(this, LocationService.class));
Intent i1 = new Intent (context, LocationService.class);
context.startService(i1);
// here I want to check if LocationService has finished execution
if (1 == 1){
super.onPushReceive(context, intent);
}
}// end of onPushRecieve
}
Just fire off your notification inside your custom LocationService.
Plus, you don't want to do anything async inside a BroadcastReceiver as it will exit before the async method performs any callback.
See BroadcastReceiver
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.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.
In the event that you have no control over the custom LocationService code then you should probably just start your own Service and poll for the shared pref value your waiting for. This is however not ideal.
I notice the Parse receiver you are extending does not extend WakefulBroadcastReceiver which may be an issue - check out the docs for this...
Thanks Dori It worked. LocationService is my own class . I trapped the Notfication message in PushReciever and displayed it in the Service.
public class PushReceiver extends ParsePushBroadcastReceiver {
public static Context pushContext;
public static Notification pushNoti;
#Override
public void onPushReceive(Context context , Intent intent) {
pushContext = context;
Intent i1 = new Intent (context, LocationService.class);
pushNoti= getNotification(context,intent);
context.startService(i1);
}// end of onPushRecieve
}
// and in LocationService Service just fired it
NotificationManager nm = (NotificationManager)
PushReceiver.pushContext.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
public void onConnected(Bundle bundle) {
Log.d("onConnected ", "Value: ");
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
nm.notify(0,PushReceiver.pushNoti);
}

Android Change a variable in service from other app

the title says all, I need to change the variable of my service from a activity in my other app , what to finalize the service or not, this is possible?
I found the Message object , but I do not quite understand
The simplest solution would be to implement a BroadcastReceiver. Your Service listens for the Broadcast and the other App sends the Broadcast.
Example Reciever:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Get bundle from intent and use it to set your Variable in your Service
}
}
Example Broadcaster (courtesy of Vogella):
Intent intent = new Intent();
intent.setAction("de.vogella.android.mybroadcast");
sendBroadcast(intent);

AlarmManager - Am I doing it right?

I had setup AlarmManager in my MainActivity class.
A class called AlarmReceiver gets fired up for every set interval of time.
I have to perform an operation when that class is fired up. That code is in in another class Parsing.java
Now in AlarmReceiver.java, I'm doing this :
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Parsing obj = new Parsing(context);
obj.execute();
}
}
I cannot write the code directly in AlarmReceiver.java, because AlarmReceiver.java is already extending BroadcastReceiverand my code which is Parsing.java is extending another class.
So, I'm creating an object for Parsing class and calling that method.
Is my approach correct?
I'll furnish further information in case needed.
Please let me know if my approach is correct?
Thanks in advance!
EDIT:
Parsing.java
public class Parsing extends AsyncTask<Void, Void, Void> {
//some code
}
Starting an AsyncTask from a BroadcastReceiver is wrong for two reasons:
1. The thread on which onReceive() runs is terminated after the method returns, effectively ending any long-running task which may have been started from there. To quote the official docs:
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 ..... 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.
2. The Context instance that onReceive() provides is not the same as
the Context of an Activity or Service, i.e. Activity.this or
Service.this. You need that proper Context for performing many of
the common useful operations that we usually do from an Activity or
Service. So, for example, the correct way to start a Service in
onReceive() is:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context.getApplicationContext(), ParsingService.class);
context.getApplicationContext().startService(i);
}
and not
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, ParsingService.class);
context.startService(i);
}
I don't know how you wrote your Parsing.java, it looks fine but remember this
This method is always called within the main thread of its process, unless you explicitly asked for it to be scheduled on a different thread using registerReceiver. When it runs on the main thread you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed). You cannot launch a popup dialog in your implementation of onReceive()
To me, i think it's a better way to handle this is calling another service inside onReceive method, like this
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, ParsingService.class);
context.startService(i);
}

Android Communication between Broadcast Receiver and MainActivity (Send data to activity)

I've a simple Main Activity which has to stop till an SMS is received... How can I launch a method from the MainActivity within the BroadcastReceiver's onReceive() Method?
Is there away with Signal and Wait? Can I pass something with a pending Intent, or how can I implement this communication?
Communication from BroadcastReceiver to Activity is touchy; what if the activity is already gone?
If I were you I'd set up a new BroadcastReceiver inside the Activity, which would receive a CLOSE message:
private BroadcastReceiver closeReceiver;
// ...
closeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//EDIT: receiving parameters
String value = getIntent().getStringExtra("name");
//... do something with value
finish();
}
};
registerReceiver(closeReceiver, new IntentFilter(CLOSE_ACTION));
Then from the SMS BroadcastReceiver you can send out this action:
Intent i = new Intent(CLOSE_ACTION);
i.putExtra("name", "value"); //EDIT: this passes a parameter to the receiver
context.sendBroadcast(i);
I hope this helps?
I had the exact same problem, I tried using intent but i was unsuccessful
The easiest way to use it would be using static methods and static variables
MainActivity.java
public static void stopsms()
{
/*
some code to stop the activity
*/
}
SMSReceiver.java
at the end call this function
MainActivity.stopsms();
It works amazing if your code does not affect when you use static methods and variables. Let me know if you need any help.
The problem with registering a second receiver within the activity, however, is that it will not be persistent like registering in the manifest... thus, although, this solution may work, will only work if the activity is running in background.
it's easy, use interface like that:
1) in your broadcast receiver create an interface.
public interface ChangeListener{
public void functionWhoSendData(String type);
public void etc();
}
and instantiate that interface in your broadcast receiver, use it:
public void onReceive(....
String data=functionWhereYouReceiveYouData();
ChangeListener.functionWhoSendData(data);
}
And in your activity, make it implements your interface

Categories

Resources