Android 广播未触发接收器

Android Broadcast not triggering Receiver

几天来我一直在努力找出这个错误...

问题:sendBroadcast(intent) 未触发 BroadcastReceiver

我的代码成功启动了一个前台服务...这应该在activity中广播给接收者,但意图从未到达接收方。

我已经尝试完全按照文档中给出的示例编写代码,甚至从此处复制了早期帖子中的代码,但没有任何效果。


我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.julescarboni.speedcamerawarning">

    <!-- Request permissions  -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.SpeedCameraWarning"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="@style/Theme.SpeedCameraWarning.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Mention the Location Service here -->
        <service android:name=".LocationService"
            android:foregroundServiceType="location"
            android:enabled="true" />
        <receiver android:name=".ProcessActivity$LocationReceiver"
            android:exported="true">
            <intent-filter>
                <!-- Sample filter to listen when device boot is completed -->
                <!-- This type of receiver cant be declared in codes -->
                <action android:name="com.julescarboni.speedcamerawarning.LocationService" />
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

正在广播的服务

public class LocationService extends Service {

    public static final String INTENT_ID = "com.julescarboni.speedcamerawarning.LocationService";
    private static final int ONGOING_NOTIFICATION_ID = 1;
    public static final String CHANNEL_ID = "ForegroundServiceChannel";
    //private final Context context = getApplicationContext();
    private Timer timer = new Timer(); // Timer for the service to use
    public static final int SERVICE_INTERVAL = 1000; // TODO: Set to 10 seconds

    /*@Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        startService();
    }*/

    @Override
    public void onCreate() {
        super.onCreate();
    }

    // Execution of service will start on calling this method
    public int onStartCommand(Intent intent, int flags, int startId) {

        // Create foreground service notification
        // TODO: Add icon to notification

        String input = intent.getStringExtra("inputExtra");
        createNotificationChannel();
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,
                0, notificationIntent, 0);
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Foreground Service")
                .setContentText(input)
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentIntent(pendingIntent)
                .build();
        startForeground(1, notification);

        // Activate timer with location getting task
        timer.scheduleAtFixedRate(new ProcessTrigger(), 0, SERVICE_INTERVAL);

        // Return status of the service
        return START_NOT_STICKY;
    }

    @Override
    // Execution of the service will stop on calling this method
    public void onDestroy() {
        super.onDestroy();

        // Stop the timer and task
        timer.cancel();
        timer = null;

        // Stop the process
        stopForeground(true);
    }

    // This is what the service actually runs
    // It simply sends a signal that it is time to run the process code

    private class ProcessTrigger extends TimerTask {
        @Override
        public void run() {
            // This is the process we do every time the timer triggers
            Log.d("LocationService", "Timer triggered");
            Intent intent = new Intent();
            intent.setAction(INTENT_ID);
            //intent.putExtra("data", "null");
            sendBroadcast(intent);
        }
    }

    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void createNotificationChannel() {
        // Create notification channel for foreground service notifications
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library

        // Build API level must be 26 or greater (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O).
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                    CHANNEL_ID,
                    "Foreground Service Channel",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(serviceChannel);
        }
    }
}

activity与接收者:

public class ProcessActivity extends AppCompatActivity {

    LocationReceiver locationReceiver = null;
    Boolean myReceiverIsRegistered = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        locationReceiver = new LocationReceiver();
        // Register receiver
        registerReceiver(locationReceiver, new IntentFilter(LocationService.INTENT_ID));
        myReceiverIsRegistered = true;
    }
    @Override
    protected void onResume() {
        super.onResume();
        /*if (!myReceiverIsRegistered) {
            registerReceiver(locationReceiver, new IntentFilter(LocationService.INTENT_ID));
            myReceiverIsRegistered = true;
        }*/
    }
    @Override
    protected void onPause() {
        super.onPause();
        /*if (myReceiverIsRegistered) {
            unregisterReceiver(locationReceiver);
            myReceiverIsRegistered = false;
        }*/
    }

    private void doProcess() {

        // THIS CODE HERE HAS BEEN REMOVED TO KEEP THIS SECTION CONCISE.
        // SEE BELOW FOR THIS doProcess() FUNCTION.
        // Its main purpose is to get the last known location from a fused location manager.

    }

    public static class LocationReceiver extends BroadcastReceiver {
        // RECEIVES TIMER TRIGGERS FROM LOCATION SERVICE

        // Create new instance of the process activity
        // This instance contains all the code that we need to run each time the timer is triggered
        // I.e. it is the foreground process code
        ProcessActivity processActivity = new ProcessActivity();

        @Override
        public void onReceive(Context context, Intent intent ) {
            Log.d("LocationReceiver", "Trigger received, calling process now");
            processActivity.doProcess();
        }
    }

}

来自activitydoProcess()函数到目前为止从未被调用过,因为接收器从未被触发过,所以我删除它使问题更简洁(如果它很重要,我会把它添加到问题中).

首先,如果您在清单中声明了接收器,则不需要创建实例并以编程方式注册它,因为。

The system package manager registers the receiver when the app is installed. The receiver then becomes a separate entry point into your app which means that the system can start the app and deliver the broadcast if the app is not currently running.

The system creates a new BroadcastReceiver component object to handle each broadcast that it receives. This object is valid only for the duration of the call to onReceive(Context, Intent). Once your code returns from this method, the system considers the component no longer active. https://developer.android.com/guide/components/broadcasts#manifest-declared-receivers 2) For what purposes do you use this line inside of IntentFilter tag:

3)这一行不应该存在:

ProcessActivity processActivity = new ProcessActivity();

您不能只创建 activity 的对象,因为它是一个系统组件,它正在创建 activity.

的实例

修复后尝试检查日志。

我建议你吃香肠,让这条线不存在:

ProcessActivity processActivity = new ProcessActivity();