Android广播没有触发接收器

发布于 2025-01-30 12:56:55 字数 8144 浏览 2 评论 0原文

我一直在尝试几天来弄清楚这个错误...

问题:sendBroadcast(Intent)没有触发broadcastreceiver

我的代码成功启动了一个前景服务 ...这应该在活动中广播给接收器,但是意图永远不会归于接收器。

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


我的清单文件:

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

接收者:

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

}

doprocess()来自活动到目前为止从未被调用,因为接收器从未触发过,所以我将其删除要使问题更简洁(如果很重要,我将其添加到问题中)

I've been trying to figure out this bug for days...

Issue: sendBroadcast(intent) isn't triggering BroadcastReceiver.

My code successfully starts a foreground service... This is supposed to broadcast to a receiver in an activity, but the intent never makes it to the Receiver.

I've tried writing the code out exactly as the examples are given in the documentation, and even copied code from earlier posts here, but nothing has worked.

My manifest file:

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

The service that's broadcasting:

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

The activity with the receiver:

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

}

The doProcess() function from the activity has so far never been called because the reciever has never been triggered, so I removed it to make the question more concise (if it's important, I'll add it into the question).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦里梦着梦中梦 2025-02-06 12:56:55

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

系统软件包管理器在应用程序时注册接收器
安装。然后,接收器成为您的单独入口点
应用程序意味着系统可以启动应用程序并交付
如果应用程序当前不运行,则广播。

该系统创建一个新的broadcastreceiver组件来处理
每个收到的广播。此对象仅适用于
通话持续时间(上下文,意图)。一旦您的代码
从此方法返回,系统不再考虑组件
积极的。
https://developer.android..android.com/guide/guide/guide/guide/components/broadcastspcastsp.明确宣布的获奖者
2)出于什么用途,您在intentFilter标签的内部使用此行:

3)应该删除此行:

ProcessActivity processActivity = new ProcessActivity();

您不能仅仅创建活动对象,因为它是系统组件,并且正在创建活动实例。

修复后尝试检查日志。

First of all, if you declared receiver in manifest you don't need to create an instance and register it programmatically, because.

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)This line should be removed:

ProcessActivity processActivity = new ProcessActivity();

You can't just create an object of activity, because it's a system component and it's creating instance of the activity.

try to check logs after fixes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文