【问题标题】:How to make the app's broadcast receiver keep listening without having a service running in the background如何让应用程序的广播接收器在没有服务在后台运行的情况下继续收听
【发布时间】:2014-11-26 10:05:42
【问题描述】:

我正在尝试制作一个 android 应用程序来监听 wifi 更改广播并执行一些操作。但问题是当进程被杀死时它不起作用。我发现这个问题说没有活动就无法工作
How to create BroadcastReceiver without Activity/Service?

所以这不是一个选择。因此,我创建了一个空的活动。我不想创建一个在后台运行的服务。我怎样才能让我的应用程序即使在它被杀死时也能继续监听。我已经在清单中注册了广播。

<activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <receiver android:name="com.background.service.BroadCastReceiver">  
        <intent-filter>
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>  
    </receiver>

这是我的课

public class BroadCastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    //do some action
   }
}

【问题讨论】:

  • 服务是为了什么?在 Manifest 中注册就足够了。
  • 好吧,当应用程序被杀死时,onReceive 不会被调用
  • @Alex:你如何杀死应用程序?可以提一下步骤吗?
  • “使用预安装的应用程序杀死所有正在运行的进程”——使用更可靠的技术,例如通过 DDMS 终止进程。可能是您的设备正在为这些进程执行强制停止,这将非常愚蠢,但在某些设备上会发生。除此之外,您使用什么来确定您的BroadCastReceiver 是否获得控制权?此外,自安装应用程序以来,您是否至少启动过一次该活动?否则,清单注册的接收器将无法工作(它们处于与强制停止相同的“停止”状态)。
  • 我设法找出了为什么以及如何重现我所看到的行为。这是因为我正在调试应用程序。附加调试器后,从概览屏幕中删除应用程序会导致它每次都移动到“强制停止”状态(通过转到“设置”>“应用程序”并看到“强制停止”按钮被禁用来确认)。在模拟器和真实设备中都发生。在不附加调试器的情况下运行应用程序没有问题 :) 希望此信息对某人有所帮助!

标签: android android-intent android-broadcast


【解决方案1】:

看起来您在清单中的定义是正确的,但有一个例外。如果广播接收器未在 10 秒内完成,它将触发 ANR。 http://developer.android.com/training/articles/perf-anr.html

在您的广播接收器中只需启动一个服务。

public class ReceiverUpload extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    context.startService(new Intent(context, ServiceUploader.class));
}
}

然后在您的服务中启动一个异步任务,因为您不想在 UI 线程上,例如您从应用中的活动启动相同的服务。

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // start asynctask to get off this thread
    new MyBackGround().execute(startId);
    return Service.START_REDELIVER_INTENT;
}

在 asynctask 中要做的第一件事是检查 wifi

下面是我调用来检查网络的函数的摘录,如果它返回 false,则 asynctask 刚刚完成,如果它是 true,它执行网络工作,嘿,无论如何都必须在后台,所以 asynctask 更有意义。

// check for network connection
        ConnectivityManager connMgr = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connMgr == null) {
            return false;
        }

        // check ok to process
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo == null || !networkInfo.isConnected()) {
            return false;
        }

        boolean isWifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
        if (!isWifi) {

                return false;

        }

        return true;

请注意,在此示例中,传递给 asynctask 的 startId 用于取消操作系统重新传递意图。

 @Override
    public void onPostExecute(Integer startId) {
        if (startId != null) {
            stopSelfResult(startId);
        }
    }

【讨论】:

  • 在过去的几天里,我对此投了几票。我想指出,您启动服务然后是异步任务的主要原因是,您可以发布一个很酷的通知,上面写着“嘿,我正在后台上传”,进度条甚至可能是一个取消按钮。让用户知道您的应用在后台运行时是公平的。
【解决方案2】:

您已经正确使用广播接收器并将其声明为清单。这就是你需要做的。不需要在后台运行任何服务。

只需确保至少安装并运行一次应用程序,否则广播接收将不会被注册

【讨论】:

    【解决方案3】:

    最适合我的:

    AndroidManifest

    <receiver android:name="com.AEDesign.communication.WifiReceiver" >
      <intent-filter android:priority="100">
        <action android:name="android.net.wifi.STATE_CHANGE" />
      </intent-filter>
    </receiver>
    

    BroadcastReceiver 类

    public class WifiReceiver extends BroadcastReceiver {
    
    @Override
    public void onReceive(Context context, Intent intent) {
    
      NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
      if(info != null) {
         if(info.isConnected()) {
            // Do your work. 
    
            // e.g. To check the Network Name or other info:
       WifiManager wifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            String ssid = wifiInfo.getSSID();
         }
      }
     }
     }           
    

    权限

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    

    【讨论】:

      【解决方案4】:

      最好的解决方案是制作一个广播接收器,它会工作

      public class NetworkChangeReceiver extends BroadcastReceiver {
      
      @Override
      public void onReceive(final Context context, final Intent intent) {
          final ConnectivityManager connMgr = (ConnectivityManager) context
                  .getSystemService(Context.CONNECTIVITY_SERVICE);
      
          final android.net.NetworkInfo wifi = connMgr
                  .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
      
          final android.net.NetworkInfo mobile = connMgr
                  .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
      
          if (wifi.isAvailable() || mobile.isAvailable()) {
              // Enjoy coding here 
      
              Log.d("Netowk Available ", "Flag No 1");
          }
      }}
      

      在 manifest.xml 中

       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.broadcastreceiverforinternetconnection"
      android:versionCode="1"
      android:versionName="1.0" >
      
      <uses-sdk
          android:minSdkVersion="8"
          android:targetSdkVersion="17" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
      
      <application
          android:allowBackup="true"
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" >
          <receiver android:name=".NetworkChangeReceiver" >
              <intent-filter>
                  <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                  <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
              </intent-filter>
          </receiver>
      </application>
      

      【讨论】:

        【解决方案5】:

        通常,如果应用程序被杀死并广播,您的应用程序进程将由系统为您启动。绝对没有必要让某些东西保持活力或进行任何额外的操作(否则,如果您可以使用 Service,为什么还需要 BroadcastReceiver?)

        【讨论】:

          猜你喜欢
          • 2019-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-15
          • 1970-01-01
          • 2013-01-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多