I am working on music player app and I have included the basic functionality like Play, Pause, next and Previous tracks using service class.
Now I want to update myrecyclerview UI according to the action that user clicks(eg: on the play, there should be an image of the selected element in recyclerview).
I thought to use Broadcast Receiver that service class will broadcast on different actions and then recyclerview can update according to the broadcast action. But how do I add such functionality?
You'd need an in-activity broadcast receiver. Such receivers are registered when your activity is shown and unregistered once it's hidden.
public class MainActivity extends Activity {
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Here update your RecyclerView
}
};
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(YourService.YOUR_CUSTOM_ACTION);
registerReceiver(mReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
}
And in your service, simply send broadcasts:
Intent intent = new Intent(YOUR_CUSTOM_ACTION);
// put extras in the intent as you wish
sendBroadcast(intent);
I am creating an SMS app. I can send messages fine, however I cannot get it to receive. I have successfully implemented the functionality to allow the app to be selected as the default SMS application on the device.
The problem I have is that I cannot pass the SMS from the BroadcastReceiver to the Activity that displays messages. I am aware of the ability to use intent.putExtra() for the message and then startActivity(), but what happens if that activity has already been started when the message is received? I do not want to restart the activity every time a new message is received.
There are few ways to skin that cat, one way is to have a receiver inside the Activity something like this
void onResume(){
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mSmsReceiver, filter);
}
void onPause(){
super.onPause();
unregisterReceiver(mSmsReceiver);
}
private BroadcastReceiver mSmsReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Do you stufff
}
};
I am trying to use BroadcastReceiver inside my service but it is not working properly.
I am starting my service in an onCreate in my activity. Then in the services onCreate I am calling the following to register the Broadcast reciever:
IntentFilter filter = new IntentFilter();
registerReceiver(DataUpdateReceiver, filter);
Here's the broadcast receiver i am trying to register:
private BroadcastReceiver DataUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Test", Toast.LENGTH_LONG).show();
}
};
Then else where in the Activity I am trying to call this so therefor the Toast message will be displayed.
Intent i = new Intent();
sendBroadcast(i);
But the Toast is not being displayed, I have also tried logging but nothing shows up. If anyone could help me out on this it would be appreciated, ty.
In my opinion, you have to specify action (or actions), which fire onReceive() method. Something like this might help you:
IntentFilter filter = new IntentFilter("some_action");
registerReceiver(DataUpdateReceiver, filter);
...
Intent i = new Intent("some_action");
sendBroadcast(i);
Declare on top of the class
public final static String MY_RECEIVER_START = "com.yourcompanyname.appname.MY_RECEIVER_START";
private Radio radio;
In the service constructor
//Initiate our receiver
radio = new Radio();
//Activate our recevier
context.registerReceiver(radio, new IntentFilter(MY_RECEIVER_START));
Also in the service, create the receiver class and the method which shows toast
/**
* Receiver Class
* This setup checks for the incoming intent action to be able to
* attach more messages to one receiver.
*/
private class Radio extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MY_RECEIVER_START)){
//show toast
}
}
}
After from anywhere in the application send message to our radio
context.sendBroadcast(new Intent("com.yourcompanyname.appname.MY_RECEIVER_START"));
This question already has answers here:
Having a Service receive SMS messages
(4 answers)
Closed 7 months ago.
I have a SmsReceiver class that I want to register in the main activity, what exactly should I do ?
I am new to Android.
Either you can do 2 things:
Create and define BroadcastReceiver in the Manifest
Create and register the BroadcastReceiver in code.
For option 2 (which you are asking):
Create a BroadcastReceiver in code (MyBroadcastReceiver).
Declare MyBroadcastReceiver in the scope of your Activity:
MyBroadcastReceiver mMyBroadcastReceiver;
Register the BroadcastReceiver in your Activity by:
IntentFilter filter = new IntentFilter(android.provider.Telephony.SMS_RECEIVED);
this.registerReceiver(mMyBroadcastReceiver, filter);
For API level 19 and above
IntentFilter smsFilter = new IntentFilter();
smsFilter.addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(this.receiver, filter);
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//some action
}
};
IntentFilter filter = new IntentFilter("YOUR_ACTION");
registerReceiver(receiver, filter);
Hope this helps
As you've asked to register BroadcastReceiver inside your MainActivity that fits to registerReceiver-codewise-inside-MainActivity
Here's what code looks like ==>
public class MainActivity extends Activity
{
BroadcastReceiver smsReceiver;
private IntentFilter myFilter = new IntentFilter(android.provider.Telephony.SMS_RECEIVED);
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
registerReceiver(smsReceiver, myFilter); // register BroadCastReceiver at time of initialization of Activity with proper Intent-Filter
}
#Override
protected void onPause()
{
unregisterReceiver(smsReceiver); // UnRegister BroadCastReceiver as you no longer have your activity at Foreground -- Saving CPU & Battery Drainage
super.onPause();
}
#Override
protected void onResume()
{
registerReceiver(smsReceiver, myFilter); // Register BroadCastReceiver Once again as your activity comes from pause to forground state again.
super.onResume();
}
smsReceiver = new BroadcastReceiver() //Implementation of your BroadCastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// Do whatever you like as sms is received and caught by these BroadCastReceiver
Toast.makeText(context, "SMS Received", Toast.LENGTH_LONG).show();
}
};
}
I'd like to know what is the best practice/way of programmatically register a broadcast receiver. I want to register specific receivers according to user choice.
As the registration is done through the manifest file, I'm wondering if there's a proper way to achieve this in code.
In your onCreate method you can register a receiver like this:
private BroadcastReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState){
// your oncreate code should be
IntentFilter filter = new IntentFilter();
filter.addAction("SOME_ACTION");
filter.addAction("SOME_OTHER_ACTION");
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//do something based on the intent's action
}
};
registerReceiver(receiver, filter);
}
Remember to run this in the onDestroy method:
#Override
protected void onDestroy() {
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
super.onDestroy();
}
One important point that people forget to mention is the life time of the Broadcast Receiver. The difference of programmatically registering it from registering in AndroidManifest.xml is that. In the manifest file, it doesn't depend on application life time. While when programmatically registering it it does depend on the application life time. This means that if you register in AndroidManifest.xml, you can catch the broadcasted intents even when your application is not running.
Edit: The mentioned note is no longer true as of Android 3.1, the Android system excludes all receiver from receiving intents by default if the corresponding application has never been started by the user or if the user explicitly stopped the application via the Android menu (in Manage → Application). https://developer.android.com/about/versions/android-3.1.html
This is an additional security feature as the user can be sure that only the applications he started will receive broadcast intents.
So it can be understood as receivers programmatically registered in Application's onCreate() would have same effect with ones declared in AndroidManifest.xml from Android 3.1 above.
It sounds like you want to control whether components published in your manifest are active, not dynamically register a receiver (via Context.registerReceiver()) while running.
If so, you can use PackageManager.setComponentEnabledSetting() to control whether these components are active:
http://developer.android.com/reference/android/content/pm/PackageManager.html#setComponentEnabledSetting(android.content.ComponentName, int, int)
Note if you are only interested in receiving a broadcast while you are running, it is better to use registerReceiver(). A receiver component is primarily useful for when you need to make sure your app is launched every time the broadcast is sent.
Define a broadcast receiver anywhere in Activity/Fragment like this:
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG," onRecieve"); //do something with intent
}
};
Define IntentFilter in onCreate()
mIntentFilter=new IntentFilter("action_name");
Now register the BroadcastReciever in onResume() and Unregister it in onPause() [because there is no use of broadcast if the activity is paused].
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
#Override
protected void onPause() {
if(mReceiver != null) {
unregisterReceiver(mReceiver);
mReceiver = null;
}
super.onPause();
}
For detail tutorial, have a look at broadcast receiver-two ways to implement.
package com.example.broadcastreceiver;
import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
UserDefinedBroadcastReceiver broadCastReceiver = new UserDefinedBroadcastReceiver();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/**
* This method enables the Broadcast receiver for
* "android.intent.action.TIME_TICK" intent. This intent get
* broadcasted every minute.
*
* #param view
*/
public void registerBroadcastReceiver(View view) {
this.registerReceiver(broadCastReceiver, new IntentFilter(
"android.intent.action.TIME_TICK"));
Toast.makeText(this, "Registered broadcast receiver", Toast.LENGTH_SHORT)
.show();
}
/**
* This method disables the Broadcast receiver
*
* #param view
*/
public void unregisterBroadcastReceiver(View view) {
this.unregisterReceiver(broadCastReceiver);
Toast.makeText(this, "unregistered broadcst receiver", Toast.LENGTH_SHORT)
.show();
}
}
Two choices
1) If you want to read Broadcast only when the Activity is visible
then,
registerReceiver(...) in onStart() and unregisterReceiver(...) in onStop()
2) If you want to read Broadcast even if Activity is in Background
then,
registerReceiver(...) in onCreate(...) and unregisterReceiver(...) in onDestroy()
Bonus:
If you are lazy
If you don't want to write boilerplate code for registering and unregistering a BroadcastReceiver again and again in each Activity then,
Create an abstract Activity
Write boilerplate code in Activity
Leave the implementation as abstract methods
Here is the code snippet:
Abstract Activity
public abstract class BasicActivity extends AppCompatActivity {
private BroadcastReceiver broadcastReceiver;
private IntentFilter filter;
private static final String TAG = "BasicActivity";
/**********************************************************************
* Boilerplate code
**********************************************************************/
#Override
public void onCreate(Bundle sis){
super.onCreate(sis);
broadcastReceiver = getBroadcastReceiver();
filter = getFilter();
}
#Override
public void onStart(){
super.onStart();
register();
}
#Override
public void onStop(){
super.onStop();
unregister();
}
private void register(){
registerReceiver(broadcastReceiver,filter);
}
private void unregister(){
unregisterReceiver(broadcastReceiver);
}
/**********************************************************************
* Abstract methods
**********************************************************************/
public abstract BroadcastReceiver getBroadcastReceiver();
public abstract IntentFilter getFilter();
}
Using this approach you can write more boilerplate code such as
writing common animations, binding to a service, etc.
See full code:
HERE
According to Listening For and Broadcasting Global Messages, and Setting Alarms in Common Tasks and How to Do Them in Android:
If the receiving class is not
registered using in its
manifest, you can dynamically
instantiate and register a receiver by
calling Context.registerReceiver().
Take a look at registerReceiver (BroadcastReceiver receiver, IntentFilter filter) for more info.
It is best practice to always supply the permission when registering the receiver, otherwise you will receive for any application that sends a matching intent. This can allow malicious apps to broadcast to your receiver.
for LocalBroadcastManager
Intent intent = new Intent("any.action.string");
LocalBroadcastManager.getInstance(context).
sendBroadcast(intent);
and register in onResume
LocalBroadcastManager.getInstance(
ActivityName.this).registerReceiver(chatCountBroadcastReceiver, filter);
and Unregister it onStop
LocalBroadcastManager.getInstance(
ActivityName.this).unregisterReceiver(chatCountBroadcastReceiver);
and recieve it ..
mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("mBroadcastReceiver", "onReceive");
}
};
where IntentFilter is
new IntentFilter("any.action.string")
Create a broadcast receiver
[BroadcastReceiver(Enabled = true, Exported = false)]
public class BCReceiver : BroadcastReceiver
{
BCReceiver receiver;
public override void OnReceive(Context context, Intent intent)
{
//Do something here
}
}
From your activity add this code:
LocalBroadcastManager.getInstance(ApplicationContext)
.registerReceiver(receiver, filter);