I faced to one problem on android 4.0.3 (on 4.1.2 it works fine). I have in my Activity BroadcastReceiver. When I send a broadcast, method onReceive() called always twice. P
You can avoid getting this problem, If you register your broadcast receiver from custom Application class. This will make sure that your broadcast receiver will be registered only once for the entire application life cycle.
For Xamarin developers:
I had a similar problem and for me it was because I registered the broadcast receiver in two places, one somewhere in my codes:
Android.App.Application.Context.RegisterReceiver(myReceiver, new IntentFilter("MY_INTENT_ACTION"));
And the other via Attributes:
[BroadcastReceiver(Enabled = true, Exported = true)]
[IntentFilter(new[] { "MY_INTENT_ACTION" })]
public class MyReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
}
}
I removed Attributes and the problem solved!
In my case, I decorated the broadcast class with [BroadcastReceiver(Enabled = true)]
and at the same time registered it in OnResume
. I fixed it by commenting out //[BroadcastReceiver(Enabled = true)]
I have found the reason for this issue.
Basically when we register the receiver for BLUETOOTH_STATE_CHANGE then if we are Turning ON the bluetooth then its onReceive() method will call twice for the following two Bluetooth States:
STATE 1: STATE_TURNING_ON Indicates the local Bluetooth adapter is turning on.
STATE 2: STATE_ON Indicates the local Bluetooth adapter is on, and ready for use.
Same while Turing OFF the bluetooth then its onReceive() method will again call twice for the following two Bluetooth States:
STATE 1: STATE_TURNING_OFF Indicates the local Bluetooth adapter is turning off.
STATE 2: STATE_OFF Indicates the local Bluetooth adapter is off.
So basically we can handle this situation in the following way:
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action != null && action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_ON) {
// When Bluetooth adapter is on, and ready for use
//DO YOUR CODE HERE FOR "BLUETOOTH ON" CASE
}
else if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) {
//When local Bluetooth adapter is off
//DO YOUR CODE HERE FOR "BLUETOOTH OFF" CASE
}
}
}
After looking to your code(@girlOnSledge), it seems that if you will follow the above procedure, your code will also work fine in that case.
Short answer: there isn't a difference. The BroadcastReceiver
class for both is from Android 2.3.2 r1.
I've had a similar problem, but for me it was with an HTC Desire HD with Android 2.3.5 on it - the notifications from GCM would always get received twice. I didn't manage to find the root of the problem, but there is a workaround. You can generate a unique ID for each notification in the server and send it along with the actual data. Then, in your receiver, you can update a mapping of unique ID to notification data, and if there is already data for the given ID, just ignore it.
I probably didn't make that very clear, so here's an example:
public void onReceive(Context context, Intent intent) {
String id = intent.getStringExtra("notificationID");
if (myMap.get(id) != null)
return;
final String action = intent.getAction();
if (action != null && action.equals(MyBroadcastReceiver.ACTION)) {
Log.d("tag", intent.getStringExtra("alert"));
myMap.put(id, *any value you need*);
}
}
If you don't need to store additional data, you can use a HashSet instead of a Map and just check if it contains the ID.
I had fixed this issue by using a static value.
Please find my code below.
My Activity
private static Snackbar mSnackbar;
private NetworkChangeReceiver mNetworkChangeReceiver;
@Override
protected void onResume() {
super.onResume();
registerReceivers();
}
@Override
protected void onPause() {
super.onPause();
unRegisterReceivers();
}
private void registerReceivers() {
mNetworkChangeReceiver = new NetworkChangeReceiver() {
@Override
protected void onNetworkChange(boolean status) {
if (!status) {
if (mSnackbar == null) {
mSnackbar = Snackbar
.make(drawer, R.string.no_internet, Snackbar.LENGTH_INDEFINITE)
.setActionTextColor(Color.YELLOW)
.setAction(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
mSnackbar.show();
}
} else {
if (mSnackbar != null) {
mSnackbar.dismiss();
mSnackbar = null;
}
}
}
};
IntentFilter nwStateChangeFilter = new IntentFilter();
nwStateChangeFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
nwStateChangeFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(mNetworkChangeReceiver, nwStateChangeFilter);
}
private void unRegisterReceivers() {
unregisterReceiver(mNetworkChangeReceiver);
}
NetworkChangeReceiver.Class
public abstract class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) { // connected to the internet
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI){
// connected to wifi
onNetworkChange(true);
} else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
// connected to the mobile provider's data plan
onNetworkChange(true);
} else {
// not connected to the internet
onNetworkChange(false);
}
} else {
// not connected to the internet
onNetworkChange(false);
}
}
protected abstract void onNetworkChange(boolean status);
}