I have a BroadcastReceiver inside an Activity to change some views (when it's visible) from a service. I can't make it static(and declare it in manifest) because I access views from activity inside onReceive(), so I register/unregister it inside my Activity's onResume() & onPause().
public class MyActivity extends Activity {
private BroadcastReceiver mReceiver;
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("action1");
filter.addAction("action2");
mReceiver = new CustomReceiver();
registerReceiver(mReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
if (mReceiver != null)
unregisterReceiver(mReceiver);
}
//some code
class MyBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//NEVER GET HERE
}
}
}
I send explicit intents (a must in Android O) to this receiver from a service like so:
Intent intent = new Intent(appContext, MyActivity.MyBroadcast.class);
intent.setAction("action1");
sendBroadcast(intent);
What is wrong with my implementation?
---SOLUTION---
As Mike M. commented we can use implicit intents to fire BroadcastReceiver even in Andorid O if they're registered using Context.registerReceiver()
Apps can use Context.registerReceiver() at runtime to register a receiver for any broadcast, whether implicit or explicit.
So it will be:
Intent intent = new Intent("action1");
sendBroadcast(intent);
Related
I have a broadcast receiver that gets triggered on geofencing events and either "clocks in" or "clocks out" with the server. If my application's "Attendance" activity is already open I would like it to display the clocking status change but I don't want the Broadcast Receiver to start the activity if it's not open - in other words display the change "live" while the activity is open only.
The way I imagine doing this is with the Broadcast Receiver sending an Intent to the activity but name "startActivity()" doesn't sound encouraging unless there are any special flags I can pass to prevent starting an Activity that isn't already open - I can't seem to find any.
The other option would be to constantly poll the value while the activity is open but it doesn't seem optimal so I would only use it if there wasn't another way and I can't think of a reason why it couldn't be possible with Intents.
There are several different ways to accomplish the same task. One is registering a listener like the following example:
MainActivity
public class MainActivity extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Receiver.setOnReceiveListener(new Receiver.OnReceiveListener() {
public void onReceive(Context Context, Intent intent)
{
//Do something.
}
});
}
#Override
protected void onDestroy()
{
super.onDestroy();
Receiver.setOnReceiveListener(null);
}
}
Receiver
public class Receiver extends BroadcastReceiver
{
private static OnReceiveListener static_listener;
public static abstract interface OnReceiveListener
{
public void onReceive(Context context, Intent intent);
}
public static void setOnReceiveListener(OnReceiveListener listener)
{
static_listener = listener;
}
#Override
public final void onReceive(Context context, Intent intent)
{
if(static_listener != null) {
static_listener.onReceive(context, intent);
}
}
}
Just have your BroadcastReceiver send a broadcast Intent. Your Activity should register a listener from this broadcast Intent and if it gets triggered, it can update the UI.
Here's an example:
Declare a private member variable in your Activity:
private BroadcastReceiver receiver;
In Activity.onCreate(), register the BroadcastReceiver:
IntentFilter filter = new IntentFilter();
filter.addAction("my.package.name.CLOCK_STATUS_CHANGE");
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Here you can update the UI ...
}
};
registerReceiver(receiver, filter);
And in onDestroy() you can unregister it (probably not necessary, but cleaner):
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
In your BroadcastReceiver that detects the geofencing event, you should create and send a broadcast Intent:
Intent broadcastIntent = new Intent("my.package.name.CLOCK_STATUS_CHANGE");
sendBroadcast(broadcastIntent);
I have a variable in FetchAddressIntentService class name addressText which holding zip code using reverse geocode. what i want is to send the addressText data to my MainActivity.
You have to register your main activity to the broadcast and then send the broadcast from the service.
In your main activity:
private BroadcastReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState){
IntentFilter filter = new IntentFilter();
filter.addAction("BROADCAST_ZIP_CODE");
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//get data from the intent and display it
String zipCode = intent.getStringExtra("ZIP_CODE");
//do something with the zipCode
}
};
registerReceiver(receiver, filter);
}
#Override
protected void onDestroy() {
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
super.onDestroy();
}
In your service:
public class ZipCodeService extends Service {
#Override
public void onCreate() {
String zipCode = "your_zip_code";
Intent intent = new Intent();
intent.setAction("BROADCAST_ZIP_CODE");
intent.putExtra("ZIP_CODE",zipCode);
sendBroadcast(intent);
}
}
You can achieve this in two ways.
Using a Bound Service and registering your Activity as a listener object with your Service by having your Activity implement a listener interface. Docs here.
Sending a Local Broadcast from the Service to your Activity. (See JackD's answer)
Depending on how you've architected your application you may prefer one solution more than the other. The Android docs will help which is best.
I need to send broadcast intent for specific receiver.
I use this function for it:
void sendTestBroadcast(Class<? extends BroadcastReceiver> clazz) {
Intent intent = new Intent(context, clazz);
intent.setAction(MY_ACTION);
context.sendBroadcast(intent);
}
Then I handle results in my Activity:
#Override
protected void onStart() {
super.onStart();
mReceiver = new Receiver();
registerReceiver(mReceiver, new IntentFilter(MY_ACTION));
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(mReceiver);
mReceiver = null;
}
Receiver is private and non-static class. I pass Receiver.class to my receiver sender as an argument. I also tried to use ComponentName to set destanation target, but it's still not working. I even tried to do Receiver class static -- same result.
What am I doing wrong?
i have an Activity and a Sticky Service. The Activity needs to show some values in it´s UserInterface depending on the values of the Sticky Service. So whenever the Service changes his data, the Activity needs to update it´s UserInterface.
But how should the Service notify the Activity to change it´s values??
Please remind that the Activity sometimes isn´t alive, only the Service is Sticky.
Use LocalBroadcasts
in your service class:
public class LocalMessage extends IntentService{
private Intent broadcast;
public static final String BROADCAST = "LocalMessage.BROADCAST";
public LocalMessage(String name) {
super(name);
broadcast = new Intent(name);
}
#Override
protected void onHandleIntent(Intent intent) {
if (broadcast != null) LocalBroadcastManager.getInstance(context).sendBroadcast(broadcast);
}
}
and here is method inside service to broadcast
private void sendLocalMessage(){
(new LocalMessage(LocalMessage.BROADCAST)).onHandleIntent(null);
}
In your activity:
private void registerBroadcastReciever() {
IntentFilter filter = new IntentFilter(YourService.LocalMessage.BROADCAST);
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(receiver, filter);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//doSmth
}
};
in your activity onDestroy() method unregister receiver;
There are lots of posts out there on using BroadcastReceiver for receiving messages in an Activity that are broadcast from a Service. I've been through dozens and haven't found one that puts it all together. Bottom line is I can't get my Activity to receive broadcasts. Here's what I've done to date:
Service class broadcast:
Context context = this.getApplicationContext();
Intent intentB2 = new Intent(context, StationActivity.AudioReceiver.class);
intentB2.putExtra("Track", mSongTitle);
this.sendBroadcast(intentB2);
Log.i(TAG, "Broadcast2: " + mSongTitle);
Activity class declaration:
public String INCOMING_CALL_ACTION = "com.example.android.musicplayer.action.BROADCAST";
Activity class inline BroadcastReceiver:
public class AudioReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
// Handle receiver
Log.i(TAG, "Inner BroadcastReceiver onReceive()");
String mAction = intent.getAction();
if(mAction.equals(INCOMING_CALL_ACTION)) {
Log.i(TAG, "Inner BroadcastReceiver onReceive() INCOMING_CALL_ACTION");
}
}
};
Android manifest receiver declaration:
<receiver android:name=".StationActivity.AudioReceiver">
<intent-filter>
<action android:name="com.example.android.musicplayer.action.BROADCAST" />
</intent-filter>
</receiver>
What am I missing? Thanks in advance.
In your service:
Intent intentB2 = new Intent("some_action_string_id");
intentB2.putExtra("Track", mSongTitle);
sendBroadcast(intentB2);
Then in your activity:
public class MyActivity extends Activity {
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(getApplicationContext(), "Woot! Broadcast received!", Toast.LENGTH_SHORT);
}
};
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter("some_action_string_id"); // NOTE this is the same string as in the service
registerReceiver(myReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(myReceiver);
}
}
This is the common approach to receive broadcast events in activities. Note that we are registering the receiver when the activity is in the foreground and unregistering it when the activity is no longer visible.
replace your service code with below code and add String INCOMING_CALL_ACTION in your service or directly use it from activity class.
Context context = this.getApplicationContext();
Intent intentB2 = new Intent();
intentB2.setAction(INCOMING_CALL_ACTION);
intentB2.putExtra("Track", mSongTitle);
this.sendBroadcast(intentB2);
Log.i(TAG, "Broadcast2: " + mSongTitle);