首页 > 解决方案 > 始终接收 API 级别 +26 的广播(即使在后台)的广播接收器

问题描述

我将其设置为问答风格,因为我发现这个想法有效。它解决了 Android 初学者难以破解的难题。

谷歌已弃用Broadcast Receiver从 API 级别 26+ 注册到下面这样的清单(除了一些

<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
    <intent-filter>
        <action android:name="android.net.wifi.STATE_CHANGE" />
    </intent-filter>
</receiver>

但是,如果一个人想要在应用程序处于后台时接收特定的设备状态更改,例如Internet 连接更改(这是不允许的),并且如果这对他的应用程序的任何功能都很重要,他应该怎么做?

标签: androidandroid-intentservicebroadcastreceiverandroid-broadcastreceiver

解决方案


当我浏览文档时,我的眼睛卡在这里:

只要注册上下文有效,上下文注册的接收者就会接收广播。例如,如果您在 Activity 上下文中注册,只要该 Activity 未被销毁,您就会收到广播。如果您在应用程序上下文中注册,只要应用程序正在运行,您就会收到广播。

这实际上意味着如果我可以持有一个 Context,注册它的广播接收器将在后台运行。

为此,aService将是最佳实践。

STICKY_SERVICE这是在杀死后再次启动的代码下面,因此上下文仍然有效

AlwaysOnService.class

package app.exploitr.auto;

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.support.annotation.Nullable;

public class AlwaysOnService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        registerReceiver(new ClickReceiver(), new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
        return Service.START_STICKY;
    }

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

    @Override
    public void onLowMemory() {  // rem this if you want it always----
        stopSelf();
        super.onLowMemory();
    }
}

现在,实际做事的接收者:

ClickReceiver.class

package app.exploitr.auto;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import java.util.Objects;

public class ClickReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent) {

        switch (Objects.requireNonNull(intent.getAction())) {

            case AutoJob.NOTIFICATION_CANCEL_TAG:
                System.out.println("Not related");
                break;

            case AutoJob.LOGIN_CANCEL_TAG:
                System.out.println("Not related");
                break;

            case "android.net.conn.CONNECTIVITY_CHANGE":
                System.out.println("Oops! It works...");
                break;
        }
    }
}

从任何活动类启动代码

private void setUpBackOffWork() {
    if (DataMan.getInstance(getBaseContext()).getPeriodic()) {
        AutoJob.schedulePeriodic();
        //Not related
    }
    if (DataMan.getInstance(getBaseContext()).getPureAutoLogin()) {
        startService(new Intent(this, AlwaysOnService.class));
    }
}

所以我的目标是在我打开我的安卓 WiFi 时自动登录到我的 isp,并且代码运行流畅。它永远不会失败(到目前为止,它已经运行了 7 小时 37 分钟并且运行良好 |不会在重新启动后运行)。


要使接收器在重新启动后继续运行,请尝试清单可注册BOOT_COMPLETED操作。它就像旧的一样工作。

<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>


更新 1

现在,由于谷歌采取了限制后台执行的步骤,因此您还必须使服务成为foreground服务。因此,程序如下。

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, new Intent(THIS_SERVICE_CLASS_NAME.this, ACTIVITY_TO_TARGET.class), 0);

    /*Handle Android O Notifs as they need channel when targeting 28th SDK*/
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        NotificationChannel notificationChannel = new NotificationChannel(
        "download_check_channel_id", 
        "Channel name",
        NotificationManager.IMPORTANCE_LOW);

        if (notificationManager != null) {
            notificationManager.createNotificationChannel(notificationChannel);
        }

        builder = new Notification.Builder(this.getBaseContext(), notificationChannel.getId())
                .setContentTitle("Hi! I'm service")
                .setContentIntent(pendingIntent)
                .setOngoing(true);

        notification = builder.build();
        startForeground("StackOverflow".length(), notification);
    }

    return START_STICKY;
}

推荐阅读