End to end BroadcastReceiver linking - android

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);

Related

I want my app to receive an sms to start the MainAcitivity. Even when the app is closed

I have developed an app that receives a specific text message and then do a pre-defined task. This app works fine when it is running. but when it is closed it does not do the pre-defined task. I believe there is some problem that my app do not receive broadcast when it is closed. maybe i'm not properly registering the receiver in the manifest file.
I have two classes. one is SMSReceiver that extends the broadCast Receiver. and the second one is MainActivity that is calling the broadcast receiver to receive the text message and perform a specific task.
My manifest file is:
<receiver android:name=".SMSReceiver" android:exported="true"
android:enabled="true" android:directBootAware="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity">
</activity>
SMSReceiver Class Code:
public class SMSReceiver extends BroadcastReceiver {
public String number;
public String nn;
public String v;
#Override
public void onReceive(Context context, Intent intent) {
}
}
MainActivity class code
public class MainActivity extends AppCompatActivity{
public String r_num;
Button btn;
EditText msg;
EditText num;
IntentFilter intentFilter;
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//MYCODE
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("SMS_RECEIVED_ACTION");
btn = (Button) this.findViewById(R.id.sendbtn);
msg = (EditText) this.findViewById(R.id.message);
num = (EditText) this.findViewById(R.id.numbertxt);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}} });
}
private void sendMsg(String n, String m) {
}
protected void onResume()
{
registerReceiver(intentReceiver,intentFilter);
super.onResume();
}
protected void onPause()
{
unregisterReceiver(intentReceiver);
super.onPause();
}}
This code works fine when my app is running. i want my app to respond to the message even when the app is closed/not running. Thanks in advance
Remove broadcast receiver from MainActivity. In SMSReceiver's onReceive() start MainActivity instead sending broadcast. Put extra datas to intent and receive it in MainActivity's onNewIntent().
Intent intent = Intent(context, MainActivity.java)
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
context.startActivity(intent)
In MainActivity override onNewIntent(). Put broadcast receiver's code in MainActivity into onNewIntent()
Or put this code inside SMSReceiver instead sending broadcast.
if(v.equalsIgnoreCase("call.me")) {
Toast.makeText(context, "Generating Call, Please Wait", Toast.LENGTH_LONG).show();
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse(number));
context.startActivity(callIntent);
}
put extras to intent from SMSReceiver like this
intent.putExtra("message", str);
intent.putExtra("me", v);
intent.putExtra("num", number);
receive it from onNewIntent() like this
Bundle bundle = intent.getExtras();
String message = bundle.getString("message");
String me = bundle.getString("me");
String number = bundle.getString("num");

Limiting Broadcast Receiver for Fragment only

I have created a BroadCast Receiver to notify the GPS state as below :
public class GpsLocationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {
Toast.makeText(context, "asdsadasdsaD", Toast.LENGTH_SHORT).show();
}
}
Receiver in Manifest as below :
<receiver android:name=".utility.GpsLocationReceiver">
<intent-filter>
<action android:name="android.location.PROVIDERS_CHANGED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Now, the issue is that What if I want to check gps state only in single Fragment ? Right now it broadcasting for overall app.
Thanks.
ReceiverActivity.java
A Activity that watches for notifications for the event named "custom-event-name"
#Override
public void onCreate(Bundle savedInstanceState) {
...
// Register to receive messages.
// We are registering an observer (mMessageReceiver) to receive Intents
// with actions named "custom-event-name".
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
SenderActivity.java
Intent intent = new Intent("custom-event-name");
// You can also include some extra data.
intent.putExtra("message", "This is my message!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
in OnResume() of your fragment write
LocalBroadcastManager.getInstance(context).registerReceiver(gpsChangeReceiver , new IntentFilter("android.location.PROVIDERS_CHANGED"));
An in onPause() of your fragment write
LocalBroadcastManager.getInstance(context).unregisterReceiver(gpsChangeReceiver );
At bottom of your fragment write
private BroadcastReceiver gpsChangeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "asdsadasdsaD", Toast.LENGTH_SHORT).show();
}
};

BroadcastReceiver does not receive intent Intent.ACTION_LOCALE_CHANGED

I want my app to be aware anytime the user changes the locale. So in my Application class, I create a receiver to listen to the system intent ACTION_LOCALE_CHANGED:
public final class MyApp extends Application {
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override public void onReceive(Context context, Intent intent) {
String locale = Locale.getDefault().getCountry();
Toast.makeText(context, "LOCALE CHANGED to " + locale, Toast.LENGTH_LONG).show();
}
};
#Override public void onCreate() {
IntentFilter filter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, filter);
}
}
When I press home and go to the settings app to change my locale, the Toast is not shown. Setting the breakpoint inside onReceive shows it never gets hit.
Why do you want the BroadcastReceiver in Application class. My suggestion is to have a separate class for BroadcastRecevier.
public class LocaleChangedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction (). compareTo (Intent.ACTION_LOCALE_CHANGED) == 0)
{
Log.v("LocaleChangedRecevier", "received ACTION_LOCALE_CHANGED");
}
}
}
and register your Brodcast receiver in Manifest file.
<receiver
android:name=".LocaleChangedReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
Intent.ACTION_LOCALE_CHANGED is not a local broadcast, so it won't work when you register it with LocalBroadcastManager. LocalBroadcastManager is used for the broadcast used inside your app.
public class MyApp extends Application {
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String locale = Locale.getDefault().getCountry();
Toast.makeText(context, "LOCALE CHANGED to " + locale,
Toast.LENGTH_LONG).show();
}
};
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
registerReceiver(myReceiver, filter);
}
}

BroadcastReceiver with IntentFilter for Intent.ACTION_PACKAGE_REPLACED not working within a service

I am trying to set up a service that checks when a new update of an activity is installed in a device. I have already done so within an application activity, declaring the Broadcastreceiver in the manifest and it works perfectly.
However, when I try to run that receiver within a Service and dynamically declare it, my onReceive never gets called. This is my Service code:
public class UpdateService extends Service {
private static String mPackage = "com.my.package";
private static String mActivityName = "myActivity";
private BroadcastReceiver mUpdateReceiver;
#Override
public void onCreate() {
super.onCreate();
mUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("mTag","In the BroadcastReceiver onReceive()");
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_PACKAGE_REPLACED)) {
// Log that a new update is has been found
Log.d("mTag","New version of the app has been installed.");
Log.d("mTag", "Intent data: " + intent.getDataString());
Log.d("mTag","My package: " + mPackage);
}
}
};
Log.d("mTag","In the service onCreate() method.");
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
registerReceiver(mUpdateReceiver,filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("mTag","UpdateService started");
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mUpdateReceiver);
Log.d("mTag","Service destroyed");
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
The Log in the Service onCreate() gets called, which tells me that the service is up and running. However, after installing and replacing some apps through the adb, none of the logs in the BroadcastReceiver the method onReceive() get called.
This is my MainActivity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, UpdateService.class));
}
}
Do you guys have any ideas why the onReceive() does not get called?
Thank you.
I based my code in these two references:
BroadcastReceiver within a Service
How to know Android app upgraded?
you should add the data schema to your IntentFilter.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
registerReceiver(mUpdateReceiver,filter);
If you are trying to listen to the ACTION_PACKAGE_REPLACED broadcast, this cannot be done from service. Most probably, the replacement will happen when your application is closed. That`s why you will not listen to it.
You should register from the Manifest to let your OS know that you want to listen to this Intent then Create a class that extentsBroadcastReceiver` as the following:
Manifest:
<receiver android:name="PackageChangeReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
Receiver:
public class PackageChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED) && intent.getDataString().contains(context.getPackageName())) {
Log.d("Tag", "Package has been replaced");
Log.d("Tag", "Intent data: " + intent.getDataString());
Log.d("Tag", "Action: " + intent.getAction());
}
}
}
I have checked if intent.getDataString().contains(context.getPackageName()) to make sure that the replacement of the package is mine not any other application.

Start Broadcast Receiver from an activity in android

I would like to start a broadcast receiver from an activity. I have a Second.java file which extends a broadcast receiver and a Main.java file from which I have to initiate the broadcast receiver.
I also tried doing everything in Main.java as follows but didn't know how to define in manifest file...
Main.java:
public class Main extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String rec_data = "Nothing Received";
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if( intent.getStringExtra("send_data")!=null)
rec_data = intent.getStringExtra("send_data");
Log.d("Received Msg : ",rec_data);
}
};
}
protected void onResume() {
IntentFilter intentFilter = new IntentFilter();
//intentFilter.addDataType(String);
registerReceiver(myReceiver, intentFilter);
super.onResume();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
this.unregisterReceiver(this.myReceiver);
}
}
If I cannot do everything in one class as above, how can I call the Broadcast Receiver from Main.java? Can anyone please let me know where I'm doing it wrong? Thanks!
use this why to send a custom broadcast:
Define an action name:
public static final String BROADCAST = "PACKAGE_NAME.android.action.broadcast";
AndroidManifest.xml register receiver :
<receiver android:name=".myReceiver" >
<intent-filter >
<action android:name="PACKAGE_NAME.android.action.broadcast"/>
</intent-filter>
</receiver>
Register Reciver :
IntentFilter intentFilter = new IntentFilter(BROADCAST);
registerReceiver( myReceiver , intentFilter);
send broadcast from your Activity :
Intent intent = new Intent(BROADCAST);
Bundle extras = new Bundle();
extras.putString("send_data", "test");
intent.putExtras(extras);
sendBroadcast(intent);
YOUR BroadcastReceiver :
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle extras = intent.getExtras();
if (extras != null){
{
rec_data = extras.getString("send_data");
Log.d("Received Msg : ",rec_data);
}
}
};
for more information for Custom Broadcast see Custom Intents and Broadcasting with Receivers
check this tutorial here you will get all help about broadcast including how to start service from activity or vice versa
http://www.vogella.de/articles/AndroidServices/article.html
For that you have to broadcast a intent for the receiver, see the code below :-
Intent intent=new Intent();
getApplicationContext().sendBroadcast(intent);
You can set the action and other properties of Intent and can broadcast using the Application context, Whatever action of Intent you set here that you have to define in the AndroidManifest.xml with the receiver tag.
Check this answer:
https://stackoverflow.com/a/5473750/928361
I think if you don't specify anything in the IntentFilter, you need to tell the intent the receiver class.

Categories

Resources