当我从后台删除我的程序时,我的接收器 Class 失败

My Receiver Class fails when I remove my program from background

我有一个接收器 class 用于检查手机是否已插入或从充电器上拔下。我想在拔掉手机时播放声音(使用通知)。

以下是我的 class,它工作正常。但是当我从 "launch recent programs" window 关闭我的程序时,只有这部分强制关闭(我仍然可以看到 Toast "CONNECTED"),为什么?

MyReceiver.java

public class MyReceiver extends BroadcastReceiver {
static int num = 0;
public static SharedPreferences sharedPreferences;
Notification notification = new Notification();
@Override
public void onReceive(Context context, Intent intent) {

    String action = intent.getAction();

    if(action.equals(Intent.ACTION_POWER_CONNECTED)) {
        Toast.makeText(context, "CONNECTED", Toast.LENGTH_LONG).show();
    }
    else if(action.equals(Intent.ACTION_POWER_DISCONNECTED)) {

        Toast.makeText(context, "" + num, Toast.LENGTH_LONG).show();

        NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
        String strRingtonePreference = sharedPreferences.getString("song", null);
        Toast.makeText(context, "" +strRingtonePreference, Toast.LENGTH_LONG).show();
        notification.sound = Uri.parse(strRingtonePreference);
        nm.notify(0, notification);
        num++;
    }
}

这是我的 mainActivity.java

public class MainActivity extends Activity {
public String path = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button b = (Button) findViewById(R.id.button);
    b.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
            intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION | RingtoneManager.TYPE_RINGTONE);
            intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
            intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
            path = load();
            Toast.makeText(getBaseContext(),"" + (path == null), Toast.LENGTH_SHORT).show();
            startActivityForResult(intent, 1);
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (resultCode == RESULT_OK) {
        Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
        if (uri != null) {
            String ringTonePath = uri.toString();
            TextView t = (TextView)findViewById(R.id.textView);
            t.setText(ringTonePath);
            save(ringTonePath);
        }
    }
}

private void save(String ringTonePath) {

    MyReceiver.sharedPreferences = getPreferences(Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = MyReceiver.sharedPreferences.edit();
    editor.putString("song", ringTonePath);
    editor.putInt("times" , 3);
    editor.apply();
}
private String load() {
    MyReceiver.sharedPreferences = getPreferences(Context.MODE_PRIVATE);
    return MyReceiver.sharedPreferences.getString("song", null);
}

}

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.n.receiver" >
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".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>
        <receiver android:name=".MyReceiver">
            <intent-filter>
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

感谢您的帮助。

正如我所怀疑的,您在清单中的 BroadcastReceiver 上附加了 <intent-filter>。这意味着即使您的应用不是 运行,Android 也会实例化您的 BroadcastReceiver 并调用 onReceive()。在这种情况下,MyReceiver 中的变量 sharedpreferences 为 null,因为它尚未初始化,并且 onReceive() 抛出一个 NullPointerException.

如果您只想在您的应用 运行 时获得这些广播 Intent,请从清单中删除 <intent-filter> 并在代码中注册您的 BroadcastReceiver 使用registerReceiver() 相反。