Android 网络更改广播接收器无法在One Plus手机中执行

Android 网络更改广播接收器无法在One Plus手机中执行,android,broadcastreceiver,Android,Broadcastreceiver,我有一个broadcastReceivernamenetworkReceiver.java,在连接或断开Internet时执行。而且它工作得很好 但当应用程序从最近的应用程序中关闭时,NetworkReciver.java不会在One Plus 6手机上运行,而在三星手机上运行正常 我不明白为什么One Plus设备的行为不同 我的代码: 清单 <uses-permission android:name="android.permission.INTERNET" /> <

我有一个
broadcastReceiver
name
networkReceiver.java
,在连接或断开Internet时执行。而且它工作得很好

但当应用程序从最近的应用程序中关闭时,
NetworkReciver.java
不会在One Plus 6手机上运行,而在三星手机上运行正常

我不明白为什么One Plus设备的行为不同

我的代码:

清单

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


  <receiver android:name=".NetworkReciever" >
       <intent-filter>
          <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
       </intent-filter>
  </receiver>
问题:

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


  <receiver android:name=".NetworkReciever" >
       <intent-filter>
          <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
       </intent-filter>
  </receiver>

当从One Plus设备中最近的应用关闭应用时,NetworkReceiver不会执行。

根本原因:

安卓N OnePlus推出了一项类似于Mi设备的功能,可防止某些应用程序在重新启动后自动启动。我怀疑同样的功能也阻止了你的应用程序接收
BroadcastReceiver

解决方案

在你的应用程序中使用
AccessibilityService
服务,并要求用户从设置中为你的应用程序打开
AccessibilityService
,在你的应用程序中执行此操作
BroadcastReceiver
将按预期工作

由于
AccessibilityService
是一项系统级服务,因此通过注册您自己的服务,您就通过了这些制造商应用的特定过滤器,并且只要您的自定义
AccessibilityService
OS
触发,您的应用程序在接收您注册的符合条件的
BroadcastReceiver
时变为活动状态

下面是您如何注册自己的
AccessibilityService

创建自定义
AccessibilityService

public class MyAccessibilityService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {//do nothing }

    @Override
    public void onInterrupt() { //do nothing}
}
创建配置文件
my\u accessibility\u service.xml
,并添加以下代码:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityFeedbackType="feedbackSpoken"
    android:description="@string/service_desc"
    android:notificationTimeout="100"/>
AndroidManifest.xml
文件中添加您的
AccessibilityService

<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>
<service
    android:name=".MyAccessibilityService"
    android:label="@string/app_name"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService"/>
    </intent-filter>

    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/my_accessibility_service"/>
</service>

注意:我没有尝试过,但它可能会有所帮助。

从Android N开始,系统不会向以N+为目标的应用程序的清单接收者发送
连接\u操作
广播

Explicit
broadcastReceiver
通过
上下文注册。registerReceiver()
继续接收这些广播


解决方案:请参阅以Android 7.0+为目标的应用程序,如果它们在其清单中注册接收连接性行动广播,则不会接收连接性行动广播,并且依赖此广播的进程将不会启动

所以,如果你想在互联网连接可用时做一些工作。您可以使用或

例如,下面是作业调度器的示例代码

public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
  JobScheduler js =
      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
  JobInfo job = new JobInfo.Builder(
    MY_BACKGROUND_JOB,
    new ComponentName(context, MyJobService.class))
      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
      .setRequiresCharging(true)
      .build();
  js.schedule(job);
}
当满足作业的条件时,应用程序将收到一个回调,以在指定的JobService.class中运行onStartJob()方法


此外,在活动的onCreate中注册广播并在onDestroy中注销广播对您的情况不起作用,因为在应用程序被终止后,您将不会收到广播。

Oreo不支持广播接收器作为清单标记,您必须将其注册为具有上下文的服务/活动。registerReceiver()。或者,您可以使用WorkManager为特定的网络条件安排某些工作

OnCreate

    NetworkReciever  receiver = NetworkReciever ()
    IntentFilter filter = new IntentFilter();
    filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    registerReceiver(receiver, filter);
别忘了在
onDestroy中注销它

@Override
 protected void onDestroy() {
  if (receiver != null) {
   unregisterReceiver(receiver);
   receiver = null;
  }
  super.onDestroy();
 }
并从
清单

<receiver android:name=".NetworkReciever" >
       <intent-filter>
          <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
       </intent-filter>
  </receiver>

在安卓牛轧糖中,安卓不会对清单注册广播接收器的网络更改进行广播。

来自&中也提到了

监控连接的变化 针对Android 7.0(API级别24)及更高版本的应用程序不会收到 如果他们声明广播接收器,则广播 在他们的舱单上。应用程序仍将收到 如果他们将其广播接收器注册到 这一背景仍然有效

解决方案 从最近的应用关闭应用时,不会执行NetworkReceiver

我不知道你为什么要在应用程序关闭后更改网络。但是在这种情况下,您必须使用进行一些定期任务。我建议您使用WorkManager,因为它适用于所有设备。作业调度器是否仅适用于>=21版本的设备。是WorkManager的一个很好的例子(非常简单)

后台解决方案(仅在需要时执行) 并在应用程序启动时安排此工作

public static void scheduleWork() {

    int TIME_INTERVAL_IN_SECONDS = 15;
    PeriodicWorkRequest.Builder photoCheckBuilder = new PeriodicWorkRequest.Builder(MyWorker .class, TIME_INTERVAL_IN_SECONDS, TimeUnit.SECONDS);
    PeriodicWorkRequest photoCheckWork = photoCheckBuilder.build();
    WorkManager instance = WorkManager.getInstance();
    if (instance != null) {
        instance.enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP, photoCheckWork);
    }
}
前景解决方案(推荐) 或者,如果您只是想在应用程序运行时接收网络更改。您可以使用下面的解决方案

  • 基本活动中注册此接收器。如果您还没有任何BaseActivity,也可以创建一个
  • onStart()
    上注册,在
    onStop()上注销。因为您可能不想在
    onStop()
    之后调用UI
下面是BaseActivity.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

/**
 * Created by KHEMRAJ on 9/5/2018.
 */
public class BaseActivity extends AppCompatActivity {
    NetworkReceiver receiver;
    public boolean isOnline;

    @Override
    protected void onStart() {
        super.onStart();
        isOnline = isOnline(this);
        // register network change receiver
        receiver = new NetworkReceiver();
        registerReceiver(receiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
    }

    @Override
    protected void onStop() {
        super.onStop();
        // unregister network change receiver
        unregisterReceiver(receiver);
        receiver = null;
    }

    public class NetworkReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            isOnline = isOnline(context);
            Log.i("TAG", "Network REceiver Executed");
        }
    }

    public boolean isOnline(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        //should check null because in airplane mode it will be null
        return (netInfo != null && netInfo.isConnected());
    }
}
我建议您只使用WorkManger,因为我之前创建了一个示例 有的天数, [JobService][7]。在这篇文章中,我开始了一项15分钟的周期性任务。和 调用时将每个日志写入单独的文件中

本试验的结论是:是 工作效率最高。现在因为EvernoteJobs将使用 下一版本的WorkManager。所以我想到了工作经理


从最近的抽屉中删除应用程序与
networkreceiver
没有关系,当你的应用程序正在运行且internet连接更改其状态时,将调用你的接收器是的,它必须工作。但它在1+6中不起作用。我检查了很多次,然后在这里发布。你的android设备的API版本是什么?1加6 android 8.1 API级别27可能重复这回答了你的问题吗?
public static void scheduleWork() {

    int TIME_INTERVAL_IN_SECONDS = 15;
    PeriodicWorkRequest.Builder photoCheckBuilder = new PeriodicWorkRequest.Builder(MyWorker .class, TIME_INTERVAL_IN_SECONDS, TimeUnit.SECONDS);
    PeriodicWorkRequest photoCheckWork = photoCheckBuilder.build();
    WorkManager instance = WorkManager.getInstance();
    if (instance != null) {
        instance.enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP, photoCheckWork);
    }
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

/**
 * Created by KHEMRAJ on 9/5/2018.
 */
public class BaseActivity extends AppCompatActivity {
    NetworkReceiver receiver;
    public boolean isOnline;

    @Override
    protected void onStart() {
        super.onStart();
        isOnline = isOnline(this);
        // register network change receiver
        receiver = new NetworkReceiver();
        registerReceiver(receiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
    }

    @Override
    protected void onStop() {
        super.onStop();
        // unregister network change receiver
        unregisterReceiver(receiver);
        receiver = null;
    }

    public class NetworkReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            isOnline = isOnline(context);
            Log.i("TAG", "Network REceiver Executed");
        }
    }

    public boolean isOnline(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        //should check null because in airplane mode it will be null
        return (netInfo != null && netInfo.isConnected());
    }
}