before marking this post as closed or duplicate i want to say that i have done all the things that are mentioned on similar posts but none of them worked.
I have 2 receivers which i get data from. So i want to register the receivers when the activity starts and unregister them when the activity is not visible.
My Code:
public class MainActivity extends AppCompatActivity {
private CheckNetworkStatusReceiver checkNetworkStatusReceiver;
private CheckBatteryStatusReceiver checkBatteryStatusReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkConnection();
}
public void checkConnection() {
if(!ConnectionManager.isNetworkAvailable(MainActivity.this)){
ConnectionManager.wifiSettingsDialog(MainActivity.this).show();
}else{
registerReceivers();
}
}
public void registerReceivers() {
checkNetworkStatusReceiver = new CheckNetworkStatusReceiver();
checkBatteryStatusReceiver = new CheckBatteryStatusReceiver();
registerReceiver(checkNetworkStatusReceiver, new IntentFilter(Constants.INTENT_FILTER_CONNECTIVITY_CHANGE));
registerReceiver(checkBatteryStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
#Override
protected void onDestroy() {
super.onDestroy();
try{
unregisterReceiver(checkNetworkStatusReceiver);
unregisterReceiver(checkBatteryStatusReceiver);
}catch (Exception e){
e.printStackTrace();
}
}
#Override
protected void onResume() {
registerReceivers();
super.onResume();
}
#Override
protected void onRestart() {
registerReceivers();
super.onRestart();
}
#Override
protected void onStop() {
super.onStop();
try{
unregisterReceiver(checkNetworkStatusReceiver);
unregisterReceiver(checkBatteryStatusReceiver);
}catch (Exception e){
e.printStackTrace();
}
}
}
The receiver code:
public class CheckNetworkStatusReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null){
Log.e("Action ",intent.getAction());
if(intent.getAction().equalsIgnoreCase(Constants.INTENT_FILTER_CONNECTIVITY_CHANGE)) {
if (!ConnectionManager.isNetworkAvailable(context)){
Toast.makeText(context, R.string.no_internet, Toast.LENGTH_SHORT).show();
}
if (MobileDataManager.slowInternetConnection(context)){
Toast.makeText(context, R.string.slow_internet_delay, Toast.LENGTH_SHORT).show();
}
}
}
}
}
and the battery receiver:
public class CheckBatteryStatusReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null){
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
if (level <= 15){
Toast.makeText(context, "Batter level " + level + "% is very low. Please connect to a charger.", Toast.LENGTH_SHORT).show();
}
}
}
}
i get the error on the registerReceivers() method. Any ideas?
You register the receivers in onCreate() and then again in onResume(). This will leak the receivers that you registered in onCreate(), because you overwrite the variables you are using to hold references to them every time registerReceivers() is called.
This is not very robust code. You don't need to create new instances of the BroadcastReceiver every time. What you should do is to create one instance of each BroadcastReceiver in onCreate(). Then declare a boolean member variable in your class called receiversRegistered. In registerReceivers() you should check this boolean. If it is true, the receivers are already registered and you should do nothing. If not, register the receivers and then set the boolean to true. When you unregister the receivers, set the boolean to false.
EDIT: Here it is all done for you:
public class MainActivity extends AppCompatActivity {
private CheckNetworkStatusReceiver checkNetworkStatusReceiver;
private CheckBatteryStatusReceiver checkBatteryStatusReceiver;
private boolean receiversRegistered;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkNetworkStatusReceiver = new CheckNetworkStatusReceiver();
checkBatteryStatusReceiver = new CheckBatteryStatusReceiver();
checkConnection();
}
public void checkConnection() {
if(!ConnectionManager.isNetworkAvailable(MainActivity.this)){
ConnectionManager.wifiSettingsDialog(MainActivity.this).show();
}else{
registerReceivers();
}
}
public void registerReceivers() {
// Only register if not already registered
if (!receiversRegistered) {
registerReceiver(checkNetworkStatusReceiver, new IntentFilter(Constants.INTENT_FILTER_CONNECTIVITY_CHANGE));
registerReceiver(checkBatteryStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
receiversRegistered = true;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (receiversRegistered) {
unregisterReceiver(checkNetworkStatusReceiver);
unregisterReceiver(checkBatteryStatusReceiver);
}
}
#Override
protected void onResume() {
registerReceivers();
super.onResume();
}
#Override
protected void onRestart() {
registerReceivers();
super.onRestart();
}
#Override
protected void onStop() {
super.onStop();
if (receiversRegistered) {
unregisterReceiver(checkNetworkStatusReceiver);
unregisterReceiver(checkBatteryStatusReceiver);
receiversRegistered = false;
}
}
}
Move the unregisterReceiver inside onPause not in onDestroy.
When your activity is moved in background onDestroy is not called. The activity is only paused. onDestroy is called when the app is closed manually or by the system.
(onPause is called before onDestroy in above situation)
Related
I can't stop receiving broadcasts. Why?
This is the code I have:
public class MainActivity extends AppCompatActivity {
BroadcastReceiver br = new CustomReceiver();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BroadcastReceiver br = new CustomReceiver();
filter.addAction(Intent.ACTION_POWER_CONNECTED);
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
this.registerReceiver(br, filter);
}
#Override
protected void onStart() {
super.onStart();
if(!br.isOrderedBroadcast())
this.registerReceiver(br, filter);
}
#Override
protected void onStop() {
super.onStop();
if(br.isOrderedBroadcast())
this.unregisterReceiver(br);
}
#Override
protected void onPause() {
super.onPause();
if(br.isOrderedBroadcast())
this.unregisterReceiver(br);
}
#Override
protected void onResume() {
super.onResume();
if(!br.isOrderedBroadcast())
this.registerReceiver(br, filter);
}
#Override
protected void onDestroy() {
super.onDestroy();
if(br.isOrderedBroadcast())
this.unregisterReceiver(br);
}
}
public class CustomReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
String toastMessage = "TOAST";
switch (intentAction){
case Intent.ACTION_POWER_CONNECTED:
toastMessage="Power Connected!";
break;
case Intent.ACTION_POWER_DISCONNECTED:
toastMessage="Power Disconnected!";
break;
}
Toast.makeText(context, toastMessage, Toast.LENGTH_SHORT).show();
}
}
When I go to onPause() and onStop() the app continues to show toast message of connect and disconnect charge. I don't know why.
My guess is that condition (which you're using in onPause() and onStop()) br.isOrderedBroadcast() is false so CustomReceiver won't get unregistered.
Also, according to the documentation, you should register/unregister CustomReceiver either in onCreate()/onDestroy() or in onResume()/onPause().
From an Android Service, I would like to call an Activity method, but only if the Activity is in the foreground.
I would like nothing to happen in case the Activity is not in the foreground.
Which is the simplest way to achieve that?
From a Service always better to broadcast events if the activity is listening to that broadcast will respond. If the activity is not listening then nothing will happen it will ignore.
This is the better solution than the one which you have asked.
I found a very simple solution, adapted from this previous answer:
On the Service:
Intent intent = new Intent(MainActivity.RECEIVER_INTENT);
intent.putExtra(MainActivity.RECEIVER_MESSAGE, myMessage);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
On the Activity:
public static final String RECEIVER_INTENT = "RECEIVER_INTENT";
public static final String RECEIVER_MESSAGE = "RECEIVER_MESSAGE";
Create a listener on onCreate():
public void onCreate(Bundle savedInstanceState) {
...
mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra(RECEIVER_MESSAGE);
// call any method you want here
}
};
}
register it in onStart():
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((mBroadcastReceiver),
new IntentFilter(RECEIVER_INTENT)
);
}
unregister it in onStop():
#Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
super.onStop();
}
You can do this using a Interface just to check if the activity is in background or in foreground.
I am sharing some code to have some idea.
public interface CheckAppInForeground {
boolean isAppInForGround();
}
In your Activity
public class MainActivity extends AppCompatActivity implements CheckAppInForeground {
Boolean isAppInForeGround;
#Override
protected void onResume() {
super.onResume();
isAppInForeGround = true;
}
#Override
protected void onStop() {
super.onStop();
isAppInForeGround = false;
}
#Override
public boolean isAppInForGround() {
return isAppInForeGround;
}
}
And your service class
public class MyService extends Service {
Activity activity;
public MyService(Activity activity) {
this.activity = activity;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MainActivity mainActivity = (MainActivity) activity;
if (activity != null) {
boolean isActivityInForGround = mainActivity.isAppInForGround();
if (isActivityInForGround) {
// Do what you want to do when activity is in foreground
} else {
// Activity is in background
}
} else {
// Activity is destroyed
}
return super.onStartCommand(intent, flags, startId);
}
}
I think i am clear with the code. If you find something missing or unclear please let me know
I want to make a broadcast only for particular activity. If activity get destroy then broadcast will not trigger.
I am using like this
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((receiver),
new IntentFilter(GCMIntentService.COPA_RESULT)
);
}
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int count = intent.getIntExtra(GCMIntentService.COPA_MESSAGE, 0);
int youCount = intent.getIntExtra(GCMIntentService.COUNT_YOU, 0);
int reqCount = intent.getIntExtra(GCMIntentService.COUNT_REQ, 0);
if (count != 0) {
notificationcount.setVisibility(View.VISIBLE);
notificationcount.setText("" + count);
} else {
notificationcount.setVisibility(View.GONE);
}
AppCommon.notification_requestcount = reqCount;
AppCommon.notification_youcount = youCount;
AppCommon.notification_total_count = count;
}
};
What I am missing please suggest this
If you want to do this then , simply do one thing register Broadcast receiver in Activity itself and unregister in same Activity. Like following
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((receiver),
new IntentFilter(GCMIntentService.COPA_RESULT)
);
}
#Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
super.onStop();
}
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int count = intent.getIntExtra(GCMIntentService.COPA_MESSAGE, 0);
int youCount = intent.getIntExtra(GCMIntentService.COUNT_YOU, 0);
int reqCount = intent.getIntExtra(GCMIntentService.COUNT_REQ, 0);
if (count != 0) {
notificationcount.setVisibility(View.VISIBLE);
notificationcount.setText("" + count);
} else {
notificationcount.setVisibility(View.GONE);
}
AppCommon.notification_requestcount = reqCount;
AppCommon.notification_youcount = youCount;
AppCommon.notification_total_count = count;
}
};
Create receiver inside Activity and add property. Same time if you want the receiver to be destroyed when Activity destroyed register and unregister on onResume() and onPause() respectively.
Demo:
Create BroadcastReceiver on your Activity:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// your methods and actions for receiver
}
};
Register broadcast in your activity's onCreate() method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
your_activity_.this.registerReceiver(receiver, new IntentFilter(your_filter_action));
..
...
....
}
Don't forget to unregistered/register on Activity cycle:
#Override
protected void onResume() {
super.onResume();
your_activity.this.registerReceiver(receiver, new IntentFilter(your_filter_action));
}
#Override
protected void onPause() {
super.onPause();
your_activity.this.unregisterReceiver(receiver);
}
You forgot to unregister your broadcast receiver, Please check.
#Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
super.onStop();
}
Hi friends i have a one problem to solve...I want to destroy the service completely, once i call onDestroy() method from Activity. But my problem is that i am unable to destroy it completely.. in background its keep on running, i am sharing the sample code what i tried..
//Activity Class
public class ServiceToAct extends Activity {
private static final String TAG = "BroadcastEvent";
private Intent intent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
intent = new Intent(this, BroadcastService.class);
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(myService.BROADCAST_ACTION));
}
/*#Override
protected void onResume() {
super.onResume();
}*/
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
#Override
protected void onDestroy() {
stopService(intent);
Toast.makeText(this, "Destroy Completely", Toast.LENGTH_LONG).show();
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
};
}
// service class
public class myService extends Service {
private static final String TAG = "BroadcastEvent";
public static final String BROADCAST_ACTION = "com.service.activity.myService";
private final Handler handler = new Handler();
Intent intent;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "created", Toast.LENGTH_LONG).show();
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this, "start", Toast.LENGTH_LONG).show();
handler.removeCallbacks(sendToUI);
handler.postDelayed(sendToUI, 1000);
}
#Override
public void onDestroy() {
super.onDestroy();
stopSelf();
//stopService(intent);
Toast.makeText(this, "Destroy", Toast.LENGTH_LONG).show();
}
private Runnable sendToUI = new Runnable() {
#Override
public void run() {
myData();
handler.postDelayed(this, 10000);
}
};
private void myData() {
Log.d(TAG, "keep on entering");
Toast.makeText(this, "Keep on despling in UI", Toast.LENGTH_LONG).show();
sendBroadcast(intent);
}
}
Here Actually i want to update my UI from service, Mine everything is working, but if i destroy the service its keep on calling myData() method, and i am getting the Toast msg if i close the application also.
My issue is i don't want that toast msg once the service is desroyed
I used stopService(intent) method, which destroy the service, but background method myData() is keep on calling
for stop service completely use this ..
myActivity.java
#Override
public void onDestroy() {
stopService(intent);
super.onDestroy();
Toast.makeText(this, "Destroy", Toast.LENGTH_LONG).show();
}
service.java
#Override
public void onDestroy()
{
stopSelf();
super.onDestroy();
}
You'd better never call onXxx() derectly.
Use stopService(Intent i) in your activity and stopSelf() in you service to stop instead.
use stopService() method after updating UI
or
Instead of using startService use bindService in the activity. When activity destroys, service also destroys
I have an Android Activity that needs to catch two different broadcasts. My current approach is to have a single BroadcastReceiver within the Activity and catch both the broadcasts with it:
public class MyActivity extends Activity {
private MyActivity.BroadcastListener mBroadcastListener;
private boolean mIsActivityPaused = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
// Create the broadcast listener and register the filters
mIsActivityPaused = false;
mBroadcastListener = new BroadcastListener();
IntentFilter filter = new IntentFilter();
filter.addAction(Params.INTENT_REFRESH);
filter.addAction(Params.INTENT_UPDATE);
registerReceiver(mBroadcastListener, filter);
}
#Override
protected void onResume() {
super.onResume();
mIsActivityPaused = false;
}
#Override
protected void onPause() {
super.onPause();
mIsActivityPaused = true;
}
#Override
protected void onDestroy() {
unregisterReceiver(mBroadcastListener);
super.onDestroy();
}
private void refresh() {
// refresh
}
private void update() {
// update
}
private class BroadcastListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Params.INTENT_REFRESH && !mIsActivityPaused)) {
refresh();
} else if (intent.getAction().equals(Params.INTENT_UPDATE)) {
update();
}
}
}
}
I want to execute refresh() only if my Activity is visible on the screen, but I want to catch INTENT_UPDATE and execute update() during the entire lifetime of the Activity, regardless of whether the Activity is visible or not.
I didn't find any way to unregister only one of the two filters that I register in onCreate, so I use a flag to enable or disable the action to be executed when the INTENT_REFRESH broadcast is caught, depending on the state of the Activity.
The question is: is this the correct approach?
Or, would it be better to have two separate BroadcastReceivers as follows:
public class MyActivity extends Activity {
private MyActivity.BroadcastListenerRefresh mBroadcastListenerRefresh;
private MyActivity.BroadcastListenerUpdate mBroadcastListenerUpdate;
private boolean mIsBroadcastListenerRefreshRegistered = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create the broadcast listeners
mBroadcastListenerRefresh = new BroadcastListenerRefresh();
mBroadcastListenerUpdate = new BroadcastListenerUpdate();
registerReceiver(mBroadcastListenerRefresh, new IntentFilter(Params.INTENT_REFRESH));
registerReceiver(mBroadcastListenerUpdate, new IntentFilter(Params.INTENT_UPDATE));
}
#Override
protected void onResume() {
super.onResume();
if (mBroadcastListenerRefresh != null && !mIsBroadcastListenerRefreshRegistered) {
registerReceiver(mBroadcastListenerRefresh, new IntentFilter(Params.INTENT_REFRESH));
mIsBroadcastListenerRefreshRegistered = true;
}
}
#Override
protected void onPause() {
super.onPause();
if (mBroadcastListenerRefresh != null && mIsBroadcastListenerRefreshRegistered) {
unregisterReceiver(mBroadcastListenerRefresh);
mIsBroadcastListenerRefreshRegistered = false;
}
}
#Override
protected void onDestroy() {
unregisterReceiver(mBroadcastListenerRefresh);
unregisterReceiver(mBroadcastListenerUpdate);
super.onDestroy();
}
private void refresh() {
// refresh
}
private void update() {
// update
}
private class BroadcastListenerRefresh extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Params.INTENT_REFRESH)) {
refresh();
}
}
}
private class BroadcastListenerUpdate extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Params.INTENT_UPDATE)) {
update();
}
}
}
}
And which one has better performance?
instead, you may provide two different intent filters:
filter for refresh only
IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);
filter for refresh and update
IntentFilter filterRefreshUpdate = new IntentFilter();
filterRefreshUpdate.addAction(Params.INTENT_REFRESH);
filterRefreshUpdate.addAction(Params.INTENT_UPDATE);
now you may switch between intent filters by registering and un-registering the desired one but your receiver's implementation would be same
For every action , create IntentFilter and register it.
#Override
protected void onResume() {
super.onResume();
BroadcastListener receiver = new BroadcastListener();
// Register the filter for listening broadcast.
IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);
IntentFilter filterUpdate = new IntentFilter(Params.INTENT_UPDATE);
registerReceiver(receiver, filterRefresh);
registerReceiver(receiver, filterUpdate);
}
private class BroadcastListener extends BroadcastReceiver {
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().equals(Params.INTENT_UPDATE)) {
update();
} else if(intent.getAction().equals(Params.INTENT_REFRESH)) {
refresh();
}
}
}
Using KOTLIN you can do it inline:
broadcastReceiver = NukeBroadcastReceiver()
registerReceiver(broadcastReceiver, IntentFilter().apply {
addAction(ACTION_DESTROY_EVERYTHING)
addAction(ACTION_RESTART_WORLD)
})