Calling service method from its class - android

I have a service from which I instationate my ScreenReceiver class. How can I notify service when OnRecieve method of ScreenReceiver is triggered? I'd like the update() method to be called when 'onRecieve` is trigerred.
StateChecker.java (draft):
public class StateChecker extends Service {
//...
// setting TimeAlarm
TimeAlarm mTimeAlarm = new TimeAlarm();
mTimeAlarm.SetAlarm(this.getApplicationContext(),10);
public void update() {
//update sth
}
//...
}
ScreenReceiver.java (draft):
public class ScreenReceiver extends BroadcastReceiver {
//...
#Override
public void onReceive(Context context, Intent intent) {
//...
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
}
//...
}

You can probably do something like this:
Make a new Intent to your Service from the Receiver, passing off an Extra, then override onStartCommand() in the Service. Check the intent for the Extra, and if the Extra exists, call update().
Also, if you use this instead of this.getApplicationContext(), it is very likely that your Receiver's onReceive() Context parameter will be the service. Then you can just cast.
Eg
if (context instanceof StateChecker)
((StateChecker) context).update();

Define an interface and use a callback to let the activity know that a screen event has been received.
public Interface ScreenReceiverListener {
void onScreenReceive(int arg1, string arg2); ..<----add arguments you want to pass back
}
In your ScreenReceiver class
ArrayList<ScreenReceiveListener > listeners = new ArrayList<ScreenReceiveListener >();
...
public void setScreenReceiveListener(ScreenReceiveListener listener){
listeners.add(listener);
}
In your OnReceive
for (ScreenReceiveListener listener:listeners){
listener.onSCreenReceive(arg1, arg2);
}
In your Service:
public class StateChecker extends Service implements ScreenReceiveListener {
...
screenReceiver.setScreenReceiveListener(this);
...
}
public void onScreenReceive(int arg1, string arg2){
// do whatever you need to do
}
All from memory so please excuse typos and you should improve the ScreenReceiver class by adding removeScreenReceiveistener and checking that you do not add the same listener twice in setScreenReceiveListener.
Note. Because you use an interface, any class (not just a Service) can implement it so you can update anywhere in your app. The ScreenReceiver class doesn't know or care. It just calls the listeners, if any are registered.

Related

Why doesn't my BroadcastReceiver's onReceive get called when the BroadcastReceiver is an inner class?

When I have the AlarmReceiver class below in it's own file, the log statement gets logged and the onReceive method gets called. I need to make my BroadcastReceiver an inner class so I can call getFragmentManager() from my Activity. However, when I make it an inner class to my main Activity class, it does not get called. Why is that?
public class MainActivity extends Activity {
public class AlarmReceiver extends BroadcastReceiver { //this needs to be an inner class to access the activity
#Override
public void onReceive(Context arg0, Intent arg1) {
Log.d("BROADCAST","RECEIVED");
//start a new activity, an alarm has gone off
AlarmFragment alarmFragment=new AlarmFragment();
// getFragmentManager().beginTransaction().replace(R.id.container, alarmFragment).commit();
}
}
public void setAlarm(){
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
//Get the Alarm Service
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Long currentTime = new GregorianCalendar().getTimeInMillis();
//DEBUG TIME
alarmManager.set(AlarmManager.RTC_WAKEUP,currentTime+7500,PendingIntent.getBroadcast(this,1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
}
}
Kindly change your Activity Class to FragmentActivity and also Access with context Object,like below code.
arg0.getFragmentManager().beginTransaction().replace(R.id.container, alarmFragment).commit();
Its is a Try. Kindly let me know your feedback.
Why is that?
you are got major fundamental mistake about how to send and receive broadcast mechanism works:
you are providing to alarm manager a PendingIntent to start broadcast, but in practice - you providing it intent without any Action specified.
sending broadcast without an action is meaningless!!!
you should add to the intentAlarm object an custom action string that identify your broadcast, and register your AlarmReceiver receiver programatically with an IntentFilter that handles this custom action:
Intent intentAlarm = new Intent(CUSTOM_ACTION_STRING);
....
....
(you should hold reference to an instance of your AlarmReceiver class. that's the mAlarmReceiver ...)
add to the Activity onResume() callback registration to the broadcast:
#Override
public void onResume() {
super.onResume();
registerReceiver(mAlarmReceiver , new IntentFilter(CUSTOM_ACTION_STRING));
}
don't forget also to unregister the receiver:
#Override
public void onPause() {
unregisterReceiver(mAlaramReceiver);
super.onPause();
}

Activity to Activity communication without finish

I have two activities: one is the main (A), and the second one which is started from A (B). I start B with startActivityForResult(intent, id).
I know I can send the result back to A via the setResult() method, but as far as I know, the result isn't sent until finish() is called. I need to send data from B to A without closing B (even several times before closing). Is there a way to achieve that?
As far as I've read, there are not many options to achieve this. I could use SharedPreferences but then I'd need also some kind of event to inform A that it has to read a value!
Any ideas appreciated.
------ FINAL SOLUTION ------
Finally I got it thanks to #Nathaniel Waggoner's advice. Here's what I did:
Inside my activity I declared the extension of BroadcastReceiver:
class ActivityBroadcast extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final String txt2send = intent.getStringExtra("txt2send");
if ((txt2send != null) && (!txt2send.isEmpty())) {
// Do the needed stuff
...
}
}
}
So now I declared the ActivityBroadcast instance in my class and initialized it:
private static ActivityBroadcast broadcast_signal;
broadcast_signal = new ActivityBroadcast();
The way I control that it's just my Intent the one who triggers the onReceive method is with an IntentFilter set to the SENDTXT2SOCK customized action, this way:
// CustomActions.SENDJOIN2CHAN is just a constant from a customized public class
// where I define my own constants to not interfere with the "official" ones
registerReceiver(broadcast_signal, new IntentFilter(CustomActions.SENDTXT2SOCK));
This way I'm saying that on broadcast_signal will just be registered the CustomActions.SENDTXT2SOCK action, so any other is ignored. Now we just have to send a signal from the desired activity to that receiver:
final Intent intentResult = new Intent(CustomActions.SENDTXT2SOCK);
intentResult.putExtra("txt2send", "blabla");
sendBroadcast(intentResult);
And that's all, works like a charm!
Use broadcasts and intents.
Broadcast Receivers:
http://developer.android.com/reference/android/content/BroadcastReceiver.html
You can also give a shot to OnsharedPreferenceChangelistner
you can use eventBus simple library.
first register eventbus in receiver activity
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
then set a subscriber method
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
then in other activity post your entity like this
EventBus.getDefault().post(new MessageEvent());
You can use broadcasts and observers to call a method of one activity from another activity. You will use an intent to call a broadcast from activity B, and then you will use an observer to call a method in activity A from the broadcast.
For example, if you want to call ActivityA.someMethod from ActivityB, you can do the following (don't forget implements Observer on ActivityA):
public class ActivityA extends AppCompatActivity implements Observer{
//This is the method you want to call from ActivityB
public void someMethod(Intent intent){
//intent will be the Intent object created in ActivityB, you can pass data to this method by setting extras in the intent
}
//Define the observer and broadcast receiver classes
private static class MyObservable extends Observable{
private static final MyObservable instance = new MyObservable();
public void updateValue(Object data){
synchronized(this){
setChanged();
notifyObservers(data); //This method calls ActivityA.update
}
}
}
public static class MyBroadcastReceiver extends BroadcastReceiver{
//This class must be public and static and must be added to the manifest
//To add this class to the manifest in Android Studio put the cursor on the name of the class, press Alt+Enter and choose "Add to manifest"
#Override
public void onReceive(Context context, Intent intent){ //This method will be called when the broadcast is sent from ActivityB
MyObservable.instance.updateValue(intent);
}
}
//Connect the observer to the activity in the onCreate method
#Override
protected void onCreate(Bundle savedInstanceState){
MyObservable.instance.addObserver(this);
//Do everything else in onCreate as usual
}
//This method will be called when the notifyObservers method is called from the oberver
#Override
public void update(Observable observable, Object data){
this.someMethod((Intent) data); //Call the method that you need
}
}
public class ActivityB extends AppCompatActivity{
public void callSomeMethodOnActivityB(){
Intent intent = new Intent(this, ActivityA.MyBroadcastReceiver.class);
//Add some extras to the intent to pass data
sendBroadcast(intent); //Calls ActivityA.MyBroadcastReceiver.onReceive
}
}
Most of this answer is based on ilw's answer to "Communication between BroadcastReceiver and Activity", credits to them.

Intent Filter not calling onReceive for USB_ACCESSORY_ATTACHED

I have declared an intent filter for USB_ACCESSORY_ATTACHED in the constructor of a MyDialogFragment and registered/unregistered it in the fragment's onResume and onPause methods. MyReceiver extends BroadcastReceiver in an inner class to receive the USB_ACCESSORY_ATTACHED intent. See following code:
public class MyDialogFragment extends DialogFragment {
private Context context;
private IntentFilter usbIntentFilter;
private MyReceiver myReceiver;
MyDialogFragment(Context context) {
usbIntentFilter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
myReceiver = new myReceiver();
this.context = context;
}
#Override
public void onResume() {
super.onResume();
// Register broadcast receiver
context.registerReceiver(myReceiver, usbIntentFilter);
}
#Override
public void onPause() {
super.onPause();
// Unregister broadcast receiver
context.unregisterReceiver(myReceiver);
}
class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MyApp","Called USB receiver");
}
}
}
However, the onReceive method of MyReceiver never gets called when I attach a USB accessory. Furthermore, when I change the intent to
usbIntentFilter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
the onReceive method of MyReceiver does get called. So my question is: why does it work when I detach the accessory, but not when I attach the accessory?
So it appears that USB_ACESSORY_ATTACHED intent never actually gets through to the activity, see SO question :
Android 3.1 USB-Host - BroadcastReceiver does not receive USB_DEVICE_ATTACHED
You have to work with the onResume method that is called indirectly by USB_ACCESSORY_ATTACHED. I have to say, this isn't clear in the Android documentation, and I question its implementation.

How can I send result data from Broadcast Receiver to Activity

I have an Activity that calls a Broadcast Receiver. The Broadcast Receiver waits and listens to GPS. When the listener gets the new point I want to send that new point to Activity. How can I send data from Broadcast Receiver to Activity?
I need a listener in my Activity waiting for response from Broadcast Receiver. How can I do that?
You can call the receiver from your activity. If you don't want to add the logic of the receiver in you activity you can use an abstract receiver.
You abstract receiver:
public abstract class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Add you receiver logic here
...
...
onNewPosition();
}
protected abstract void onNewPosition();
}
In your activity:
public class MyActivity extends Activity {
private smsReceiver smsReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_one_position);
smsReceiver = new smsReceiver() {
// this code is call asyncrously from the receiver
#Override
protected void onNewPosition() {
//Add your activty logic here
}
};
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
intentFilter.setPriority(999);
this.registerReceiver(smsReceiver, intentFilter);
}
#Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(this.smsReceiver);
}
}
I hope it will help you...
I defined a listener for my receiver and use it in activity and it is running perfect now. Is it possible to happen any problem later?
public interface OnNewLocationListener {
public abstract void onNewLocationReceived(Location location);
}
in My receiver class wich is named as ReceiverPositioningAlarm:
// listener ----------------------------------------------------
static ArrayList<OnNewLocationListener> arrOnNewLocationListener =
new ArrayList<OnNewLocationListener>();
// Allows the user to set an Listener and react to the event
public static void setOnNewLocationListener(
OnNewLocationListener listener) {
arrOnNewLocationListener.add(listener);
}
public static void clearOnNewLocationListener(
OnNewLocationListener listener) {
arrOnNewLocationListener.remove(listener);
}
// This function is called after the new point received
private static void OnNewLocationReceived(Location location) {
// Check if the Listener was set, otherwise we'll get an Exception when
// we try to call it
if (arrOnNewLocationListener != null) {
// Only trigger the event, when we have any listener
for (int i = arrOnNewLocationListener.size() - 1; i >= 0; i--) {
arrOnNewLocationListener.get(i).onNewLocationReceived(
location);
}
}
}
and in one of my activity's methods:
OnNewLocationListener onNewLocationListener = new OnNewLocationListener() {
#Override
public void onNewLocationReceived(Location location) {
// do something
// then stop listening
ReceiverPositioningAlarm.clearOnNewLocationListener(this);
}
};
// start listening for new location
ReceiverPositioningAlarm.setOnNewLocationListener(
onNewLocationListener);
you have couple of ways you can do it and several considerations.
you can poll, meaning check every now an again using either Handler
or Timer to see if info has arrived.
you can register the broadcast receiver as an inner class of your activity and then you can call methods in your activty.
you can have the Broadcast send Intent to your class with the info, but if your activity is not in foreground you might bring it there , and that's not 100% what you want...
Regarding some consideration, BroadCastReciver is mainly used as a listener, not notider so inner class, is best practice, in my opinion, for use with Activities, for Services you can use it as a standalone class and register it in the Manifest.xml...
Now you got to remember that when broadcast is being broadcast your Activity might be inactive due to orientation change or event that pauses your app so you might miss the event. i don't listen to system events but to my own events so i use sticky broadcast to prevent that issue.
Just need to implement the broadcast receiver in the activity. register the receiver with activity's context.

Android Best Practice on Updating the UI from BroadcastReceiver to a certain activity

When i have a broadcastReceiver say android.intent.action.MEDIA_BUTTON and i want to update the current activity's UI without creating a new activity, is there any good practice on this one?
What i know (might not be correct)
1) I can put the BroadcastReceiver in the same class as the activity and call the updateUI function after certain activity
2) Create a ContentObserver?
3) Communicate to a service created by the activity, use aidl. (I dont know how to get the current service if its registered from an activity)
4) Create a custom filter on the broadcastReceiver located on the same class as the activity, and use context.sendBroadcast(msg of custom filter) and in the custom filter call updateUI (same as one but more generic?)
The final flow is it would come from a BroadcastReceiver and ends up updating the UI without renewing the activity (unless the activity is dead?)
Kindly provide links/source code on your how you tackle this kind of problem. Thanks a lot in advance :)
The easiest way to provide this functionality is to put the broadcast receiver in you Activity and bind / unbind it using registerReceiver and unregisterreceiver:
public class MyActivity extends Activity {
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
MyActivity.this.receivedBroadcast(intent);
}
};
#Override
public void onResume() {
super.onResume();
IntentFilter iff = new IntentFilter();
iff.addAction("android.intent.action.MEDIA_BUTTON");
// Put whatever message you want to receive as the action
this.registerReceiver(this.mBroadcastReceiver,iff);
}
#Override
public void onPause() {
super.onPause();
this.unregisterReceiver(this.mBroadcastReceiver);
}
private void receivedBroadcast(Intent i) {
// Put your receive handling code here
}
}
Depending on the intent you wish to receive, you may need to add the appropriate permissions to your AndroidManifest.xml file.
What I recently had to do to change a Button's text after receiving data from a LocalBroadcastManager is to store the value in a private field and then do the UI stuff in my onResume() method.
public class myClass extends Activity {
private String myString;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// register to receive data
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver, new IntentFilter("myAction"));
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// get the extra data included in the intent
myString = intent.getStringExtra("myString");
}
};
#Override
public void onResume() {
super.onResume();
System.out.println("onResume");
// do something to the UI
myButton.setText(myString != null ? myString : "Default");
}
}

Categories

Resources