Discovering if Android activity is running - android

I'm using C2DM, my BroadcastReceivers propagate the C2DM events to a local service. the service complete the registration by sending the id to my webserver pus it's responsible for letting the device know about new messages, however if the application (one of the activities) is up we want to send an intent to that activity with the new data so it can be updated, if not than the NotificationManager is used to notify the user.
The issue is, how to know the activity is running ? the Application object is not an option since the Service is part of the application it's obviously going to be present. unregister in the onDesroy of each application is also not an option since it may occur in orientation change...
Any standard way to get it done ?

Solution 1:
You can use ActivityManager for Checking if Activity is Running or not:
public boolean isActivityRunning() {
ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> activitys = activityManager.getRunningTasks(Integer.MAX_VALUE);
isActivityFound = false;
for (int i = 0; i < activitys.size(); i++) {
if (activitys.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.example.testapp/com.example.testapp.Your_Activity_Name}")) {
isActivityFound = true;
}
}
return isActivityFound;
}
need to add the permission to your manifest..
<uses-permission android:name="android.permission.GET_TASKS"/>
Solution 2:
Your can use an static variable in your activity for which you want to check it's running or not and store it some where for access from your service or broadcast receiver as:
static boolean CurrentlyRunning= false;
public void onStart() {
CurrentlyRunning= true; //Store status of Activity somewhere like in shared //preference
}
public void onStop() {
CurrentlyRunning= false;//Store status of Activity somewhere like in shared //preference
}
I hope this was helpful!

The next approach would work well if you want to handle incoming Google Cloud message (C2DM) by your activity (if any is running) or issue a notification if no activities are running.
Register one BroadcastReceiver in the manifest file. This receiver will handle C2D messages whenever application not running. Register another BroadcastReceiver programmatically in your activity. This receiver will handle C2D messages whenever activity is running.
AndoroidManifest.xml
<receiver
android:name=".StaticReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.mypackage" />
</intent-filter>
</receiver>
MyReceiver.java
public class StaticReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Trigger a Notification
}
}
MyActivity.java
public class MyActivity extends ActionBarActivity {
#Override
protected void onResume() {
super.onResume();
final IntentFilter filter = new
IntentFilter("com.google.android.c2dm.intent.RECEIVE");
filter.addCategory("com.mypackage");
filter.setPriority(1);
registerReceiver(dynamicReceiver, filter,
"com.google.android.c2dm.permission.SEND", null);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(dynamicReceiver);
}
private final BroadcastReceiver dynamicReceiver
= new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Handle C2DM
// blocks passing broadcast to StaticReceiver instance
abortBroadcast();
}
};
}
Note! To catch broadcasts first, the priority of dynamicReceiver IntentFilter must be higher than priority of StaticReceiver instance IntentFilter (default priority is '0').
PS. It looks like broadcasts issued by Google Cloud Messaging Service are ordered broadcasts. Original idea author: CommonsWare

Copied from here.
you can use a static variable within the activity.
class MyActivity extends Activity {
static boolean active = false;
public void onStart() {
active = true;
}
public void onStop() {
active = false;
}
}

Easiest way to check that whether an Activity is running or not is:
Context context = MyActivity.this;
if (! ((Activity) context).isFinishing()) {
// Activity is running
} else {
// Activity has been finished
}
Note: If activity is not running you should not perform any UI related operation.

Related

how to make register battery Broadcast work in Manifest instead of in an Activity

I am trying to get actions performed on battery change. For that I have used the following code:
public class BatteryBroadcastReceiver extends
BroadcastReceiver {
DatabaseHelper db;
#Override
public void onReceive(Context context, Intent intent) {
db = new DatabaseHelper(context);
String cont1 = db.usercontact().toString();
String action = intent.getAction();
if (action != null && action.equals(Intent.ACTION_BATTERY_CHANGED)) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL,-1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE,-1);
int percentage = level * 100 / scale;
if(percentage <= 20){
// doing something like getting location
}
}
}
I have registered my broadcast in my activity:
public class Battery extends AppCompatActivity {
private BatteryBroadcastReceiver batteryReceiver = new BatteryBroadcastReceiver();
private IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auto_location);
}
#Override
protected void onResume(){
super.onResume();
registerReceiver(batteryReceiver,intentFilter);
}
#Override
protected void onPause(){
unregisterReceiver(batteryReceiver);
super.onPause();
}
This general piece of code is working fine but it is restricting me to just this activity (may be because broadcast is registered in this activity). Like as long as this activity remains open I can perform some task but as I closes it, when battery gets low it perform no task. Now I don't know what to do. I have other activities too in my application and I want it to work even when I am not on this activity. Is there any way that I can register it in manifest so that it could work overall. I have tried doing that but then nothing happens on battery change. Thanks for help in advance :).
It is no longer possible to register for ACTION_BATTERY_CHANGED in the manifest. See https://developer.android.com/reference/android/content/Intent.html#ACTION_BATTERY_CHANGED
If you want to get triggered by this broadcast Intent in all of your activities, you can do this one of 2 ways:
Register and unregister the receiver in each and every one of your activities. You could simplify this by creating a BaseActivity that handles the register and unregister of the BroadcastReceiver and then extending all your activities from BaseActivity.
Register the receiver when your app starts in a custom Application class, or in onCreate() of your first Activity. Don't unregister the receiver. This causes a small memory leak, but I wouldn't worry about it.

How to send a custom event to AccessibilityService?

My program purpose: trigger the BACK button in a service
I tried many ways, no one can achieve this purpose, finally I discovered AccessibilityService, it may be the most possible ways to implement this function.
I created this AccessibilityService, and tested it is work
package com.accessibilityservice;
public class MyAccessibilityService extends AccessibilityService {
public MyAccessibilityService() {
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
#Override
public void onInterrupt() {
}
}
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackSpoken"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="desc"
android:notificationTimeout="100"
android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" />
And then I tried to move performGlobalAction to service, but it does not perform the action.
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyAccessibilityService mas=new MyAccessibilityService();
mas.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
}
I also tried to send a custom event in different way, but no one can send to MyAccessibilityService
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//method1
AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_CLICKED);
event.setContentDescription("this is description");
View view = new View(this);
ViewParent parent = view.getParent();
if (parent != null) {
parent.requestSendAccessibilityEvent(view, event);
}
//method2
AccessibilityManager manager = (AccessibilityManager) getApplicationContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
AccessibilityEvent event = AccessibilityEvent.obtain();
event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
event.setPackageName("p");
event.setClassName("c");
manager.sendAccessibilityEvent(event);
}
How can I send a custom event or message to MyAccessibilityService, so that I can recognize the event and message to perform the action?
1 Create a static field of your service
public static MyAccessibilityService instance;
2 then initialize it in onServiceConnected()
#Override
protected void onServiceConnected() {
super.onServiceConnected();
instance = this;
}
3 don't foget to clear it in onUnbind()
#Override
public boolean onUnbind(Intent intent) {
instance = null;
return super.onUnbind(intent);
}
onServiceConnected() is called by the System when user gives permission to your app in device Settings
onUnbind() is when users revokes that permission
4 Use your instance everywhere you want
if(MyAccessibilityService.instance != null)
MyAccessibilityService.instance.performGlobalAction(....)
You can't run an Accessibility service the way in which you are attempting. Accessibility services can only be run as accessibility services. The reason here is obvious, if you understand the capabilities of accessibility services. Things they can do:
Track keyboard events
Investigate contents of text fields
arbitrarily send action events
These can be easily used for malicious purposes. Allowing an application, or even a standard service, to launch a process that can do such things would be terrible security. As such only the system can launch an accessibility service, with all of the relevant permissions. The only place it does this is from the accessibility settings menu. This way users know, at least, when an accessibility service is running, and can be more cautious about the types of these services that they run.
This also leads to the overall answer: You can't. At least not without running an actual accessibility service, and then sending intents directly to that. But the user would have to separately launch your service themselves.
I am not sure if this is the correct way to go but it will get your work done. Have a broadcast receiver registered within your Accessibility service method onServiceConnected() like below.
#Override
protected void onServiceConnected() {
super.onServiceConnected();
registerReceiver(listener, new IntentFilter("my_custom_event_listener));
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(listener);
}
And your broadcast receiver within your accessibility service
private class MyCustomListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if(extras != null){
String action = extras.getString("action");
if(action.equals("back")
performGlobalAction(GLOBAL_ACTION_BACK);
}
}
Instead of creating an event, send a broadcast like below to perform back action:
Intent back = new Intent("my_custom_event_listener");
Bundle data = new Bundle();
data.putString("action", "back");
back.putExtras(data);
sendBroadcast(back);

Detect if the application is manually closed or not

I've written an android app which checks the network status by using a BroadcastReceiver inherited class:
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d("mylog", "NetworkChangeReceiver Hit");
}
}
which is registered in the manifest file like this:
<receiver
android:name="foo.NetworkChangeReceiver"
android:label="NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
I needed to handle the internet connection whenever it connects or disconnects. Actually, it works perfectly in normal situations.
But the problem is that when the application is closed manually (by minimizing the app and then closing it by swiping out the app icon in the Recents button menu), it still receives the network status changes. This sometimes causes some exceptions.
Even I have included all the code in receiver function in try/catch block, but still sometimes a toast message containing an error message is shown. This sometimes happen even after some days after the closure of the app.
Please note that the code in the receiver function is more complicated than the code that is shown here and has some access to internal classes and variables.
Your app will still receive events, even if it isn't running. Before you do anything in onReceive(), you can check if the activity is running by:
Option 1: Use a static variable in your activity to check it's state for access from the receiver :
public class YourActivity extends Activity {
public static boolean isRunning = false;
#Overrride
public void onCreate(Bundle savedInstanceState){
isRunning = true;
....
}
//We need receiver to work when app is minimized
/*
#Override
public void onStart() {
super.onStart();
isRunning = true;
}
#Override
public void onStop() {
super.onStop();
isRunning = false;
}
*/
}
And in the receiver:
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d("mylog", "NetworkChangeReceiver Hit");
if(!YourActivity.isRunning)
return;
}
}
Option 2 : Using the ActivityManager
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
if (isAppForground(context))
return;
}
public boolean isAppForground(Context mContext) {
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(mContext.getPackageName())) {
return false;
}
}
return true;
}
}
You'll need the permission:
<uses-permission android:name="android.permission.GET_TASKS" />
If you define receivers in your manifest, the app will receive events, even if it is not started.
http://developer.android.com/guide/topics/manifest/receiver-element.html
Broadcast receivers enable applications to receive intents that are broadcast by the system or by other applications, even when other components of the application are not running.
To fix this, just don't define the Receiver in the manifest, but do it programatically in onStart and unregister it again in onStop. The problem with this solution is, that you won't get messages if your app is in the background.
private BroadcastReceiver receiver;
#Overrride
public void onStart(){
super.onStart();
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
receiver = new NetworkChangeReceiver();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onStop();
//don't forget to unregister the receiver again
unregisterReceiver(receiver);
}
EDIT: onCreate and onDestroy won't work, as onDestroy will not be called in every instance the app is closed (e.g. if it is closed with the task manager)
Solution Found:
I found a perfect solution to my problem. Thanks to the correct answer in Android service crashes after app is swiped out of the recent apps list, I found out that when an app is closed via Recents list, the whole process will be created again and all the static variables will be freshed to their default values, and the onCreate and all other methods will not be called.
So the solution is something like:
public static boolean appStarted = false;
protected void onCreate(Bundle savedInstanceState) {
appStarted = true;
...
}
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
if (!MyActivity.appStarted)
return;
...
}
}
The key is to just keep track of when the app starts, and not when the app is closed (because the closing event of app is not dependable and in some situations doesn't work properly)

How to detect SMS only when application is running in android?

I am developing an android application. In my application, I need to detect incoming SMS.
I have tried a sample example with broadcast receiver. But the problem with broadcast receiver is that even when your application is not running it detects sms. My requirement is to detect sms on when my application is running.
Thanks in advance.
There are 2 Solutions to your problem: (See This for refernce)
1. By Registering Dynamic Broadcast receiver:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do your sms receive logic here
}
}
And Register this Receiver in your activity like this:
// Global
BroadcastReceiver smsReceiver = new MyReceiver();
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
registerReceiver(smsReceiver , new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
unregisterReceiver(smsReceiver);
super.onPause();
}
2. By Checking that your app is running or not in your static Broadcast Receiver:
If you want to implement this method you have to do alot more work:
a) Add "android.permission.GET_TASKS" permission in Manifest
b) Call this method in your broadcast receiver's onReceive() Method before doing anything
public boolean checkRunningApps() {
ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTasks = mActivityManager
.getRunningTasks(Integer.MAX_VALUE);
int pos = -1;
// Checking that your app is in running task list or not
for (int i = 0; i < runningTasks.size(); i++) {
if ((runningTasks.get(i).topActivity.getPackageName()
.contains(AppSettings.REQUIRED_PACKAGENAME))) {
isAppRunning = true;
pos = i;
break;
}
}
if (pos == -1) {
// App is not running, do nothing
return false;
}
if (pos >= 0) {
// App is running, do your logic here
// If you want to check that app is on top, check for only 0 position of runningTasks arrayList
return true;
}
return false;
}
If this method returns true then do your logic, else do nothing.
There is no easy way to track whether your app is visible to user or not. You have to track it by yourself simply counting screens when they enter onResume() and onPause(). When the app hits onResume() of any activity, increment a counter and when hits to onPause() decrement. You can simply create a base Activity and place those counting system in it and extend it from every Activity you created in your application.
Check out the Android Activity Lifecycle.
http://developer.android.com/reference/android/app/Activity.html
Try this !!
Your broadcast receiver must specify android:exported="false" for not receiving broadcasts created outside your own application.
Sample broadcast receiver is defined in the manifest as follows:
<receiver
android:name=".IncomingSmsBroadcastReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

Why BroadcastReceiver works even when app is in background ?

I am checking Internet connectivity in my app using BroadcastReceiver and I show an alert dialog if the connection is lost. It works fine. But my problem is that BroadcastReceiver works even if my app is in backgroung. So dialog pops up when internet connection is lost even if user is in some other app. This is totally ruining my app.
Has anyone got any idea how to restrict Broadcast receiver in the app only?
Here is my BroadcastReceiver :
public class ConnectivityChangedReceiver extends BroadcastReceiver{
#Override
public void onReceive( Context context, Intent intent )
{
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
} else {
try{
Intent i=new Intent(context, InternetDialogActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
} catch(Exception e){
e.printStackTrace();
}
}
}
}
And the activity is:
public class InternetDialogActivity extends Activity implements OnClickListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.internet_dialog_box);
getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
Button retryButton = (Button) findViewById(R.id.retryInternetButton);
retryButton.setOnClickListener(this);
}
public boolean checkConnectivity(){
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo!=null && networkInfo.isConnected()) {
finish();
return true;
} else {
Intent intent = getIntent();
finish();
startActivity(intent);
return false;
}
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.retryInternetButton:
try{
checkConnectivity();
} catch(Exception e){
e.printStackTrace();
}
break;
}
}
}
Here is how I declared receiver and activity in manifest:
<receiver android:name="com.lisnx.service.ConnectivityChangedReceiver"
android:label="NetworkConnection">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
<activity android:name="com.lisnx.activity.InternetDialogActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="#android:style/Theme.Dialog" />
I have read that we can restrict BroadcastReceiver to work within the app by not declaring it in the manifest. But I don't know how will receiver work then? Please help me. I am stuck on it badly. Thanx in advance.
A BroadcastReceiver works when the app is in the background because the event that the receiver picks up are sent globally, and each app is registered to listen in on these, regardless of whether or not it is running.
To deal with this, in your BroadcastReceiver's onReceive code, check if your app is in the foreground.
There is one--and only one that I know of--consistently effective method to do this. You need to keep track of your pause/resume actions for your application. Ensure that you check this in every activity.
There is some sample code in this answer (solution #1). In your case, you would want to check MyApplication.isActivityVisible() == true as a validation before doing anything from your BroadcastReceiver.
Have you tried to remove the Intent filter from the manifest and register/unregister it in activity? So you can try to register Intent filter in onStart() and unregister it on onStop() methods. The code goes somethink like this:
static final String ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
IntentFilter filter = new IntentFilter(ACTION);
this.registerReceiver(ConnectivityChangedReceiver, filter);
unregisterReceiver(ConnectivityChangedReceiver);
You should also learn about Activity Lifecycle, if it's not familiar yet.
You should register/unregister your BroadcastReceiver in onPause() and onResume() of each activity. Then you know that the receiver is only "listening" when your app is in the foreground. You can easily do that by creating your own BaseActivity that extends Activity and overrides onPause() and onResume() and registers/unregisters your receiver. Just have all your activities extend BaseActivity and have them call through to super.onResume() and super.onPause() as usual. Here's example code:
public class BaseActivity extends Activity {
// Create an IntentFilter to listen for connectivity change events
static IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
// Create an instance of our BroadcastReceiver
static ConnectivityChangedReceiver receiver = new ConnectivityChangedReceiver();
#Override
protected void onPause() {
super.onPause();
// Stop listening for connectivity change events
unregisterReceiver(receiver);
}
#Override
protected void onResume() {
super.onResume();
// Listen for connectivity change events
registerReceiver(receiver, filter);
}
}
All your activities should extend BaseActivity and if they need to do anything special in onResume() or onPause() just make sure to call through to super.onXXXXX() like this:
public MyActivity extends BaseActivity {
#Override
protected void onResume() {
super.onResume();
// Here you do whatever you need to do in onResume() of your activity
...
}
#Override
protected void onPause() {
super.onPause();
// Here you do whatever you need to do in onPause() of your activity
...
}
}
I didn't run the code through a compiler so I apologize if there's a typo or I missed something.
I think you will have to make sure that you are not using the receiver when app is in background. For that you will have to use every activities onPause() and onResume() methods.
As far as I know, if Broadcast receiver is registered inside manifest.xml then broadcast receiver exists as long as application exists. Also, Dynamically registered receivers (that means, Register your BroadcastReceiver programmatically) are called on the UI thread. This means that your receivers blocks any UI handling and thus the onReceive() method should be as fast as possible.
However, I will try to discuss information about Broadcast Receiver. But, first should know some information. Firstly, Broadcast receiver is a standalone application component which means it will continue running even when other application component are not running. That's why we unregister broadcast receiver in onPause on the activity. Also, Developer should register this in Activity.onResume() implementation.
Secondly, Developer should not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack. I have put that information from BroadcastReceiver documentation.
Another point is that a BroadcastReceiver object is only valid for the duration of the call to onReceive(). As soon as the onReceive() method is finished, your BroadcastReceiver terminates.
Now, how to register your receiver programmatically:
public abstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter)
Here, BroadcastReceiver- receiver will be call when any broadcast intent match with filter.
And IntentFilter- Intent specifies which event your receiver should listen to.
Register:
YourConnectionListener receiver;
this.reciever = new YourConnectionListener();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(this.reciever, filter);
Sent your Broadcast Info:
Intent intent = new Intent();
intent.putExtra("Message", "Your connectivity info has Changed!!");
this.sendBroadcast(intent);
Receiver:
Now, need to receive the Broadcast. Android calls the onReceive() method on all registered broadcast receivers whenever the event occurs. Say you want to be notified whenever the connection is changed.
public class YourConnectionListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
// your Code
}
}
onReceive() has two arguments:
context: The Context object you can use to access additional information or to start services or activities.
intent: Intent used to register your receiver. This object contains additional information that you can use in your implementation.
Additionally, Developer should avoid any long-lasting tasks in your BroadcastReceiver. So, In statically and dynamically registered receivers, Developer should do minor tasks in the receiver itself.For any longer tasks you should start a service from within your receiver.
To make a Broadcast Receiver that fires only when you app is running follow the below code.
1. Create your Broadcast Receiver like this:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class InternetStatusNotifier extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//Recieve notification here
}
}
2. Make an activity or fragment where you want the Broadcast Receiver to work like this:
import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
public class MainActivity extends Activity {
private InternetStatusNotifier mInternetStatusNotifier;
#Override
protected void onCreate(Bundle savedInstanceState) {
mInternetStatusNotifier = new InternetStatusNotifier();
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
registerReceiver(mInternetStatusNotifier, new IntentFilter(
"android.net.conn.CONNECTIVITY_CHANGE"));
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(mInternetStatusNotifier);
super.onPause();
}
Note: That is how you use broadcasts receiver in a screen specific manner. Only the screen displaying will receive broadcasts in this way. When you register broadcast using manifest file then they are even received when app is closed
That is the way broadcast receivers work in Android. If you register for a broadcast in the manifest and your app is not running, Android will start a new process to handle the broadcast. It is generally a bad idea to directly show a UI from a broadcast receiver, because this may interrupt other apps. I'm also not convinced that a universal 'connection lost' dialog is a good idea either. This should probably be handled by each activity that uses network access.
As for the original question, you need to disable your receiver when your activity goes in the background (onPause(), etc.) and enable it when you come to the foreground (onResume(), etc). Put enabled=false in your manifest and then use something like this in your code to toggle it as necessary:
public static void toggle(Context context, boolean enable) {
int flag = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
ComponentName receiver = new ComponentName(context,
ConnectivityMonitor.class);
context.getPackageManager().setComponentEnabledSetting(receiver, flag,
PackageManager.DONT_KILL_APP);
}
A simple way of finding whether the app is in foreground or not
if((mContext.getPackageName().equalsIgnoreCase(
((ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE))
.getRunningTasks(1).get(0).topActivity.getPackageName())))
{
//app is in foreground;
}
I better suggest you to check the internet setting from the application when someone opens it, here is the piece of code how i do it.
public static boolean isNetworkConnected(Context ctx) {
ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni == null) {
return false; // There are no active networks.
} else
return true;
}

Categories

Resources