广播接收器,始终接收API级别+26的广播(即使在后台) [英] Broadcast-receiver which always receives broadcast (even in background) for API Level +26

查看:155
本文介绍了广播接收器,始终接收API级别+26的广播(即使在后台)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将其伪称为 Q& A风格,因为我发现此想法可行.这是针对使用Android的初学者来说很难解决的难题的解决方案.

I'm posing this as Q&A style because I found this idea working. And it's a fix to the hard problem to crack for beginners with Android.

Google已从API级别26+开始弃用将Broadcast Receiver注册到以下清单中的清单(

Google has deprecated registering Broadcast Receiver into manifest like this below from API Level 26+ ( Except Some )

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

但是,如果在后台运行应用程序时希望接收特定的设备状态更改(例如 Internet连接更改(不允许) ),并且该设置对于其应用程序的任何功能都很重要,该怎么办?他应该怎么做?

But, If one wants to receive particular device state changes like Internet Connectivity Changes (Which isn't allowed) while the app is in background and if it's important for any feature of his application, what should he do?

推荐答案

在阅读文档时,我的眼睛卡在了这里:

When I was going through the documentation, My eyes got stuck here :

上下文已注册的接收者只要其注册上下文有效就可以接收广播.例如,如果您在 活动上下文,只要活动是 没有被摧毁.如果您在Application上下文中注册,则您 只要应用程序正在运行,就可以接收广播.

Context-registered receivers receive broadcasts as long as their registering context is valid. For an example, if you register within an Activity context, you receive broadcasts as long as the activity is not destroyed. If you register with the Application context, you receive broadcasts as long as the app is running.

这实际上意味着,如果我可以保留上下文,则向其注册的广播接收器将在后台运行.

That practically means if I can hold a Context, the broadcast-receiver registered with it will run in the background.

为此,Service将是最佳做法.

这是STICKY_SERVICE的以下代码,该代码在被杀死后会重新启动,因此上下文仍然有效.

This is below code for a STICKY_SERVICE which is started again after killed and thus the context remains valid.

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

现在,实际执行操作的接收方:

Now, the receiver which actually does things :

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

所以我的目标是当我打开android的WiFi时自动登录到isp,并且代码运行流畅.它永远不会失败(到现在为止,它已经运行了7个小时37分钟,并且运行良好| 在两次重启之间都没有问题).

So my target was to Login into my isp automatically when I turn up my android's WiFi, and the code works smooth. It doesn't fail ever (It's running for 7 hours and 37 minutes till now and working well | not across reboots).

要使接收器在重新引导期间运行,请尝试清单可注册的BOOT_COMPLETED操作.它的工作方式就像旧的一样.

To keep the receiver running across reboots, try manifest registerable BOOT_COMPLETED actions. It works just like the old one.

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



更新1



Update 1

现在,由于Google采取了一项措施来限制后台执行&因此,您还必须将该服务设置为foreground服务.因此,过程如下.

Now, as Google took one step to limit background execution & as a result you've also to make the service a foreground service. So, the procedure goes below.

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

这篇关于广播接收器,始终接收API级别+26的广播(即使在后台)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆