Why is my BroadCast Receiver not working?

2019-08-05 04:45发布

问题:

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);
 }
 }

回答1:

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.



回答2:

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
        }
    }


回答3:

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>


回答4:

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.



回答5:

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!



回答6:

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.