I have a Broadcast Receiver for connectivity changes and it works fine for all the devices running below android N but its not working on android N. I cannot find any thing relevant regarding this whether they changes something in N or not. DO anyone has any idea why this is happening?
MANIFEST FILE
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.admin.movies">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MovieSingleton"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".NetworkBroadcastReceiver"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
Here is my broadcast receiver
public class NetworkBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = NetworkBroadcastReceiver.class.getSimpleName();
public NetworkBroadcastReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive: network change");
if(isOnline(context)){
Log.d(TAG, "onReceive: connected");
} else {
Log.d(TAG, "onReceive: not connected");
}
}
public boolean isOnline(Context mContext) {
ConnectivityManager connMgr = (ConnectivityManager)
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
}
Since many apps register to receive this broadcast, a single network switch can cause them all to wake up and process the broadcast at once.
In Android Nougat, You have to register your BroadcastReceiver with Context.registerReceiver().
This change is part of Android 7.0 background optimizations and performance improvements.
Related
I'm using a BroadcastReceiver to check network state which extends a class rather than initializing BroadcastReceiver. So, is it possible to unregister it anywhere?
If yes then how, if not then what would be the alternate solution of doing that.
I see a solution here but it isn't the actual answer of the question.
Here's my class where I am using BroadcastReceiver.
public class CheckNetworkState extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
/*check WIFI state*/
final android.net.NetworkInfo wifi = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
/*check network state*/
final android.net.NetworkInfo mobile = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable()) {
//Toast.makeText(context, "connection established", Toast.LENGTH_SHORT).show();
} else {
/*shows dialogue*/
Intent alertDialogueIntent = new Intent(context, DialogueUtils.class);
alertDialogueIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(alertDialogueIntent);
}
}
}
And here's my Manifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.hardware.camera" />
<uses-permission android:name="android.hardware.camera.autofocus" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".Utils.DialogueUtils" />
<receiver
android:name=".Utils.CheckNetworkState"
android:enabled="true">
<intent-filter>
<action
android:name="android.net.conn.CONNECTIVITY_CHANGE"
tools:ignore="BatteryLife" />
</intent-filter>
</receiver>
<activity android:name=".UserAuth.ChangePassword"></activity>
<activity android:name=".QRScanner.CustomScanner" />
<activity android:name=".WaterMetersList.WaterMeters" />
<activity android:name=".UserAuth.Login" />
<activity
android:name=".ControlCharts.Charts"
android:label="#string/title_activity_bottom_navigation" />
<activity android:name=".Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
In your application class create static receiver as follows:
public class YourApplication extends Application {
public static BroadcastReceiver receiver;
public void onCreate() {
super.onCreate();
receiver = new CheckNetworkState();
}
}
After that you can register your receiver anywhere as:
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
this.registerReceiver(YourApplication.receiver, filter);
After that you can unregister it as:
getContext().unregisterReceiver(YourApplication.receiver);
I've got a following problem:
Why does my CallReceiver works on older android version, while on the newer one nothing happens? Is it any change of permission rules, or what?
There is my code:
public class CallReceiver extends BroadcastReceiver {
static boolean isRinging=false;
static boolean isReceived=false;
static String callerPhoneNumber;
#Override
public void onReceive(Context mContext, Intent intent){
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
isRinging =true;
Bundle bundle = intent.getExtras();
callerPhoneNumber= bundle.getString("incoming_number");
}
if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
isReceived=true;
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
// detect missed call
if(isRinging==true && isReceived==false){
Toast.makeText(mContext, "Missed call from : "+callerPhoneNumber, Toast.LENGTH_LONG).show();
}
}
}
}
Manifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".CallReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
Thank you for any help
As per your question, it seems you didn't asked for Run time permissions on higher versions(>=API level 23), so enable them by requesting permissions.
For more check this.
I have an activity on which I am initialising a broadcast receiver. I want this broadcast receiver to to call a function in my activity once it has received the message that the network status of the phone has changed.
Unfortunately it seems like the broadcast receiver never receives this message since the onReceive function is never called.
Here the Receiver:
private BroadcastReceiver NetworkReceiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (!wifi.isAvailable() || !mobile.isAvailable()) {
Log.d("debug"," in the if");
Handler handler = new Handler();
handler.postDelayed(sendUpdatesToUI, 10);
Log.d("Network Available ", "Flag No 1");
}
}
};
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
update();
}
};
private void update() {
Log.d("debug", "got update");
}
I call register it with this line in the onCreate function:
registerReceiver(NetworkReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
and here is my manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rtuya.secmere">
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".LoginActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar" />
</application>
</manifest>
EDIT
I have added this in my manifest but still no result:
<receiver
android:name="NetworkReceiver"
android:label="NetworkReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Broadcast receiver also needs to be declared in your manifest.xml
Add
<receiver android:name=".ReceiverName" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
You might want to place receiver in it's own class instead of doing it anonymously.
Don't you have to register receiver in manifest ? Like this:
<receiver
android:name="Receiver"
android:label="Receiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
I have the following code in a service which is called with an AlarmManager (this works well) but when when I start the wifi scan (which returns true) I never receive the results in the BroadcastReceiver I created:
public class WifiCheckerService extends IntentService {
WifiManager wifiManager;
List<Wifi> savedWifis;
List<Wifi> wifisInRange;
List<ScanResult> wifisInRangeResults;
BroadcastReceiver broadcastReceiver;
public WifiCheckerService() {
super("WifiCheckerService");
}
#Override
public void onCreate() {
super.onCreate();
setScanAlwaysAvailable();
if(broadcastReceiver == null)
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
check();
}
};
if (wifiManager == null)
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
registerReceiver(broadcastReceiver,
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
wifiManager.startScan();
}
}
private void check() {
// irrelevant stuff
Intent intent = new Intent(Constants.BROADCAST_UPDATE_WIFI);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendBroadcast(intent);
}
}
public List<Wifi> getSavedWifisInRange(List<Wifi> savedWifis,
List<ScanResult> wifisInRangeResults) {
List<Wifi> wifisInRange = new ArrayList<Wifi>();
for (Wifi wifi : savedWifis) {
for (int i = 0; i < wifisInRangeResults.size(); i++) {
if (wifi.getSsid().equals(wifisInRangeResults.get(i).SSID)) {
wifi.setRssi(String.valueOf(wifisInRangeResults.get(i).level));
wifisInRange.add(wifi);
}
}
}
return wifisInRange;
}
public void setScanAlwaysAvailable() {
/* Set scan always available if it is turned off*/
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (!wifiManager.isScanAlwaysAvailable()) {
startActivity(new Intent(WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE));
}
}
}
public boolean isTetheringActive() {
//irrelevant stuff
return false;
}
private boolean isAnySavedWifiInRange() {
//irrelevant stuff
return true;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(wifiScanReceiver);
}
}
I have used BroadcastReceiver's with wifi scans before, but I don't know why this is not working.
What's wrong?
EDIT: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.vending.BILLING" />
<application
android:name=".WifiSentinelApp"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".activities.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.DonateActivity"
android:label="#string/donate"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".activities.SettingsActivity"
android:label="#string/settings"
android:screenOrientation="portrait" />
<receiver android:name=".receivers.AlarmReceiver" />
<receiver android:name=".receivers.BootReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".services.WifiCheckerService" />
</application>
My understanding of the IntentService is that it will only be active for the time needed to handle the request (ie, the time needed to run onHandleIntent()). I haven't tested your code, but my guess is that your broadcast receiver is being unregistered right away when onDestroy() runs, before the scan results are delivered. Probably an IntentService is not right for this. You might need to create a "regular" (long living background) service. Or, maybe it just makes more sense to have your BroadcastReceiver in the activity where you will show the scan results and get rid of this IntentService altogether. WifiManager::startScan() is asynchronous so it shouldn't be necessary to call that on a background service anyway.
I'm trying to call my AlarmReceiver which extends BroadcastReceiver. After I run this code, i can't see any of logs. Could you please help me in this issue. :D
Here's where I try to call AlarmReceiber
public void downloadTweets(Context context) {
ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
Intent alarmIntent = new Intent(context,AppService.AlarmReceiver.class);
alarmIntent.putExtra(AppService.SCREEN_NAME, ScreenName);
PendingIntent pi = PendingIntent.getBroadcast(context,0,alarmIntent,PendingIntent.FLAG_UPDATE_CURRENT);//getBroadcast(context, 0, i, 0);
AlarmManager am=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Log.v(LOG_TAG, "shot");
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1, pi);
Log.v(LOG_TAG, "shot finish");
} else {
Log.v(LOG_TAG, "No network connection available.");
}
}
and here's my AlarmReceiver class which is a sub-class of AppService
public static class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v(LOG_TAG, "AlarmReceiver");
Intent sendIntent = new Intent(context,AppService.class);
sendIntent.putExtra(AppService.SCREEN_NAME,intent.getStringExtra(AppService.SCREEN_NAME));
context.startService(sendIntent);
Log.v(LOG_TAG, "AlarmReceiver done");
}
}
And my manifest has this...
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.nutjane.android.rainalert.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<service android:name=".service.AppService"/>
<receiver android:name=".service.AppService$AlarmReceiver" android:enabled="true"/>
When I run, the log shows only shot and shot finish
Could you please help me solve this issue.
Add:
sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
in your AlarmReceiver class
Change your manifest file to:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.nutjane.android.rainalert.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".AppService"
android:enabled="true" />
<receiver android:name=".AlarmReceiver" >
<intent-filter>
<action android:name="myintent" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />