I am learning about BroadCast Receivers. What I am trying to achieve with the following piece of code is, I would like to see a toast when I switch to airplane mode, where the app is on or not. What am I not doing / Doing wrong? Please Help. Thanks
ConnectivityChangedReceiver.java class
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
public class ConnectivityChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive( Context context, Intent intent )
{
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<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=".ConnectivityChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE">
</action>
</intent-filter>
</receiver>
</application>
MainActivity.java`
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private TextView switchStatus;
private Switch mySwitch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
From the android documentation :
https://developer.android.com/guide/components/broadcast-exceptions
As part of the Android 8.0 (API level 26) Background Execution Limits,
apps that target the API level 26 or higher can no longer register
broadcast receivers for implicit broadcasts in their manifest.
However, several broadcasts are currently exempted from these
limitations. Apps can continue to register listeners for the following
broadcasts, no matter what API level the apps target.
and
https://developer.android.com/distribute/best-practices/develop/target-sdk
Google Play will require that new apps target at least Android 8.0
(API level 26) from August 1, 2018, and that app updates target
Android 8.0 from November 1, 2018.
"android.intent.action.AIRPLANE_MODE" is no longer in the list of exempted broadcasts. So, register your broadcast receiver in activity rather than in AndroidManifest.
Try it like this,try adding,android:exported="true":
//Add this permission too
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<receiver android:enabled="true" android:name=".ConnectivityChangedReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.ACTION_AIRPLANE_MODE_CHANGED"/>
</intent-filter>
</receiver>
The Real state is determined like this:
@Override
public void onReceive(Context context, Intent intent) {
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
if(isAirplaneModeOn){
// handle Airplane Mode on
} else {
// handle Airplane Mode off
}
}
You have to enable your broadcast in your manifest.xml file :
<receiver android:enabled="true" android:name=". ConnectivityChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
The Official document of Broadcast Receivers Says:
android:exported
Whether or not the broadcast receiver can receive messages from sources outside its application — "true" if it can, and "false" if not. If "false", the only messages the broadcast receiver can receive are those sent by components of the same application or applications with the same user ID.
So I just found the solution to my problem above.
I changed
<receiver android:name=".ConnectivityChangedReceiver">
to
<receiver android:name="ConnectivityChangedReceiver">
(Without the '.' at the beginning of name. Hope it helps a stranded one!
You need to put the receiver in the bundles package:
package my.bundles.id;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
public class ConnectivityChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive( Context context, Intent intent )
{
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
You should put it in a package thats the same as the bundleId and that will let the above work. The first dot in the name field means that the Class is a member of the bundles namespace. So, since it wasnt in a package, the dot made it look in the wrong place.