【问题标题】:wifi connectivity changed broadcast receiver repeats multiple timeswifi连接改变广播接收器重复多次
【发布时间】:2014-11-25 05:32:25
【问题描述】:

我有以下广播接收器。

public class TestNetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        String TAG = "TEST:";

        if (intent.getAction().equals("android.net.wifi.WIFI_STATE_CHANGED")) {

            Log.i(TAG, "Wifi toggled");

        } else if (intent.getAction().equals("android.net.conn.CONNECTIVITY_CHANGE")) {

            Log.i(TAG, "Network connection changed");

            ConnectivityManager cm = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo networkInfo = cm.getActiveNetworkInfo();

            if (networkInfo != null && networkInfo.isConnected()) {

                Log.i(TAG, "Network connecion is:" + networkInfo.getTypeName());

                Log.i(TAG, "Detail:"+networkInfo.isFailover());
            }
        }
    }
}

当我打开和关闭 wifi 时

I/TEST:﹕ Wifi toggled
I/TEST:﹕ Network connection changed
I/TEST:﹕ Network connecion is:WIFI
I/TEST:﹕ Detail:false
I/TEST:﹕ Network connection changed
I/TEST:﹕ Network connecion is:WIFI
I/TEST:﹕ Detail:false
I/TEST:﹕ Network connection changed
I/TEST:﹕ Network connecion is:WIFI
I/TEST:﹕ Detail:false

I/TEST:﹕ Network connection changed
I/TEST:﹕ Network connecion is:mobile
I/TEST:﹕ Detail:true
I/TEST:﹕ Network connection changed
I/TEST:﹕ Network connecion is:mobile
I/TEST:﹕ Detail:true

我想要实现的是知道连接何时变为“移动”或“wifi”并且处于活动状态但只有一次。否则它会运行我的例程 3 或 4 次。我尝试更改 networkInfo.whatever() 但所有内容都重复 3 或 4 次或更多或更少次。有没有一种方法可以让我知道连接发生了变化,以及它在接收器中的某处只发生了一次?

【问题讨论】:

    标签: android broadcastreceiver


    【解决方案1】:

    广播 [CONNECTIVITY_ACTION ] 似乎在少数设备上具有粘性,因此当您注册接收器时,它会立即使用最近发送的广播调用 onReceive()。

    因此建议您需要在清单上做接收者的静态声明。

    这是我用过的:

    @Override
    protected void onResume() {
        super.onResume();
        setMyReceiverStayus(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        setMyReceiverStayus(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
    }
    
    
    private void setMyReceiverStayus(int receiverState) {
        ComponentName receiver = new ComponentName(this, MyReceiver.class);
        PackageManager pm = this.getPackageManager();
        pm.setComponentEnabledSetting(receiver, receiverState,       
        PackageManager.DONT_KILL_APP);
    }
    

    AndroidManifest.xml

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

    【讨论】:

    • 对不起,你能澄清一下吗?我不确定我是否明白这里的想法。我已经创建了 ComponentName 并且 Manifest 与我已经拥有的相同,但结果是相同的。 wifi 为 3x,移动设备为 2x,当我启用/禁用 wifi 时会来回切换。
    • 基本上我的意思是将您的接收器声明更改为清单中的静态
    • 抱歉,这里的静态是什么意思?如果您的意思是只输入接收者的全名,我已经这样做了。
    【解决方案2】:

    你可以试试这个

    public class TestNetworkReceiver extends BroadcastReceiver {
        public static boolean firstTime = true;
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
            String TAG = "TEST:";
    
            if (firstTime) {
                firstTime = false;
                //do stuff
            }
        }
    }
    

    可能不是最优雅的方式,但它可以解决问题

    【讨论】:

    • 哈哈。这正是我最终做的事情,你是对的,它一点也不优雅。还好我没画图!
    • 你能把它标记为正确答案吗?或者至少有一些支持:)
    【解决方案3】:

    对于想要从连接向上/向下处理程序执行一些后台活动并维护线程安全的人来说,迟到的帖子可能很有用。

    我使用了 AtomicBoolean 变量,

    private AtomicBoolean networkUp = new AtomicBoolean(false);
    
    private void onConnectivityUp() {
        Log.d("TAG", "onConnectivityUp");
    
        if (networkUp.compareAndSet(false, true)) {
            // Do something
        } else {
            // Duplicate event ignoring
            Log.d("TAG", "onConnectivityUp - ignoring");
        }
    }
    
    private void onConnectivityDown() {
        Log.d("TAG", "onConnectivityDown");
        if (networkUp.compareAndSet(true, false)) {
            // Do something
        } else {
            // Duplicate event ignoring
            Log.d("TAG", "onConnectivityDown - ignoring");
        }
    }
    

    PS:我的广播接收器正在调用 onConnectivityUp 和 onConnectivityDown

    【讨论】:

      【解决方案4】:

      切换wifi时,由于多次wifi状态变化,多次收到广播。您可以使用getWifiState 接收这些更新。

      您需要在清单文件中添加ACCESS_WIFI_STATE 的权限,因为应用正在访问 wifi 状态。

      <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
      <application
          ....
          <activity android:name=".MainActivity">
            ....
          </activity>
      </application>
      

      例子:

      在 BroadcastReceiver 类中,

      @Override
      public void onReceive(Context context, Intent intent) {
      
          Log.i("[Broadcast]", "intent - " + intent.getAction());
      
          switch (intent.getAction()) {
              case WifiManager.WIFI_STATE_CHANGED_ACTION:
                  ReceivedWifiStateChangedAction(context, intent);
                  break;
      
              default:
                  Log.i("[Broadcast]", "Default case!!");
          }
      }
      
      
      private void ReceivedWifiStateChangedAction (Context context, Intent intent) {
      
          WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
      
          switch (wifi.getWifiState()) {
      
              case WifiManager.WIFI_STATE_DISABLED:
                  Log.i("[Broadcast]", "WIFI_STATE_DISABLED");
                  break;
      
              case WifiManager.WIFI_STATE_DISABLING:
                  Log.i("[Broadcast]", "WIFI_STATE_DISABLING");
                  break;
      
              case WifiManager.WIFI_STATE_ENABLED:
                  Log.i("[Broadcast]", "WIFI_STATE_ENABLED");
                  break;
      
              case WifiManager.WIFI_STATE_ENABLING:
                  Log.i("[Broadcast]", "WIFI_STATE_ENABLING");
                  break;
          }
      }
      

      在Activity类中,

      private static Receiver myReceiver;
      
      // Register broadcasts
      public void RegisterBroadcast () {
      
          myReceiver = new Receiver();
          IntentFilter filter = new IntentFilter();
      
          filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
      
          registerReceiver(myReceiver, filter);
      }
      

      输出:

      打开wifi时,

      I/[Broadcast]: intent - android.net.wifi.WIFI_STATE_CHANGED
      I/[Broadcast]: WIFI_STATE_ENABLING
      I/[Broadcast]: intent - android.net.wifi.WIFI_STATE_CHANGED
      I/[Broadcast]: WIFI_STATE_ENABLED
      

      您可以丢弃 ENABLING/DISABLING 广播并使用 ENABLED/DISABLED 广播。

      【讨论】:

        【解决方案5】:
        public void onReceive(Context context, Intent intent) {
             ConnectivityManager cm = (ConnectivityManager)  
             context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
                NetworkInfo info = cm.getActiveNetworkInfo();
                if (info != null) {
                    if (info.isConnected()) {
                        // you got a connection! tell your user!
                        Log.i("Post", "Connected");
        
                    }
                } 
            }
        

        将此添加到清单中

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

        试试这个

        【讨论】:

        • 是的,我收到了两个来自连接到 mobil 的回复和三个来自 wifi 的回复。这就是问题所在。
        • 你想要什么 2 个来自手机,2 个来自 Wifi
        • 使用我的接收器,它将被称为 onconnectivityChanged 但它包含检查。 if (info.isConnected()) { 把你的代码放在这里 }
        • 如果您查看我的原始代码,我也有一个 isConnected()。我的问题是我从手机收到 2 个 isConnected() 回复,从 wifi 收到 3 个回复。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多