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

时间:2018-08-11 07:57:02

标签: android broadcastreceiver

我有一个BroadcastReciever名称NetworkReciver.java,该名称在Internet连接或断开连接时执行。而且效果很好。

但是,当应用程序从最近的应用程序中关闭时,NetworkReciver.java不能在One Plus 6 Phone中执行,而在Samsung Phones中可以正常运行。

我不明白为什么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>

NetworkReciever.java:

  public class NetworkReciever extends BroadcastReceiver 
  {

       @Override
     public void onReceive(Context context, Intent intent)
     {
            Log.i("TAG", "Network REceiver Executed");
     }
}

问题:

从One Plus设备中的最近应用关闭应用后,NetworkReciever不执行。

5 个答案:

答案 0 :(得分:4)

从Android N开始,系统不会向目标N +的应用程序的接收方发送CONNECTIVITY_ACTION广播。

通过BroadcastReceivers注册的明确Context.registerReceiver()继续接收这些广播。

解决方案:请参见ConnectivityManager.CONNECTIVITY_ACTION deprecated

答案 1 :(得分:2)

面向Android 7.0+的应用如果注册为在清单中接收它们,则不会接收CONNECTIVITY_ACTION广播,并且依赖于此广播的进程也不会启动。

因此,如果您想在互联网连接可用时做一些工作。您可以使用Job schedulerwork manager

例如,这是作业调度程序的示例代码。

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()方法

Android JobScheduler Sample

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

答案 2 :(得分:2)

在Android Nougat中,Android不会广播网络更改以显示已注册的BroadcastReceiver。

Android Nogout Changes起,在ConnectivityManager中也提到

  

监控连接的变化

     

针对Android 7.0(API级别24)及更高版本的应用不会收到   CONNECTIVITY_ACTION广播,如果它们声明广播接收者   在他们的清单上。应用仍将收到CONNECTIVITY_ACTION   如果他们向其注册了BroadcastReceiver广播   Context.registerReceiver(),并且该上下文仍然有效。

解决方案

  

从最近使用的应用程序关闭应用程序后,NetworkReciever不执行

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

背景解决方案(仅在您需要时执行)

public class MyWorker extends Worker {
    @Override
    public Worker.Result doWork() {

        // get online status

         boolean isOnline =  isOnline(getApplicationContext());

        // Indicate success or failure with your return value:
        return Result.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }

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

并在应用启动时安排这项工作。

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中。或如果还没有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,因为我之前创建了一个示例    JobScheduler EvernoteJobs    AlarmManager [JobService] [7] WorkManager 。在其中,我分别开始了15分钟的定期任务。和   调用时将它们的日志记录在单独的文件中。

     

该测试的结论是。 WorkManager EvernoteJobs   最有效的工作。现在,因为EvernoteJobs将使用   下一版本的WorkManager。所以我想出了WorkManager。

答案 3 :(得分:0)

根本原因:

从Android N开始,OnePlus引入了类似于Mi设备的功能,该功能可防止某些应用在重启后自动启动。我怀疑相同的功能也阻止了您的应用接收BroadcastReceiver

解决方案

在您的应用程序中使用AccessibilityService服务,并要求用户从“设置”中为您的应用程序打开AccessibilityService,并且在您的应用程序中BroadcastReceiver都可以正常工作。

由于AccessibilityService是系统级服务,因此通过注册自己的服务,您将通过这些制造商应用的特定过滤器,并且一旦{{1} },您的应用就会开始接收您已经注册的合格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_accessibility_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文件中添加<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>

AccessibilityService

您完成了!

以下是检查AndroidManifest.xml状态的方法:

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

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

答案 4 :(得分:0)

Oreo不支持将广播接收器作为清单标签,您必须通过context.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();
 }

并将其从Manifest

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