我注册了一个侦听网络事件的接收器:
<receiver
android:label="NetworkConnection"
android:name=".ConnectionChangeReceiver" >
<intent-filter >
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
接收器也很简单:
public class ConnectionChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetInfo != null) {
Log.v("@@@","Receiver : " + activeNetInfo);
} else {
Log.v("@@@","Receiver : " + "No network");
}
}
}
问题是,当连接Wifi时,我连续收到3条相同的消息,如下所示:
Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true
Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true
Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true
它们都是“连接/连接”(它们不应该像CONNECTING / OBTAINING_IPADDR等),所以问题是如何确定它何时真正连接?当wifi实际连接时我有一些我想做的例程,我不希望连续三次调用它们。
PS:3G只发送一条消息,所以这里没问题。
更新:
似乎是设备特定的问题。
为了测试我拿了2个Desire HD和4个随机Android手机(不同的Aquos型号和一些无名的中文内容)。在DHD和wifi上的一个随机电话连接上我收到3条消息,在剩下的手机上我只收到一条消息。 WTF。
答案 0 :(得分:56)
接收多个广播是设备特定的问题。有些手机只发送一个广播而另一个发送2或3.但是有一个解决方法:
假设你在wifi断开连接时收到断开连接的消息,我猜第一个是正确的,另外两个只是由于某种原因的回声。
要知道消息已被调用,你可以有一个静态布尔值,它在connect和disconnect之间切换,只在你收到一个连接并且boolean为true时调用你的子例程。类似的东西:
public class ConnectionChangeReceiver extends BroadcastReceiver {
private static boolean firstConnect = true;
@Override
public void onReceive(Context context, Intent intent) {
final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetInfo != null) {
if(firstConnect) {
// do subroutines here
firstConnect = false;
}
}
else {
firstConnect= true;
}
}
}
答案 1 :(得分:8)
您还可以在静态字段中缓存上次处理的连接类型,并检查收到的广播。这样,每种连接类型只能获得一个广播。
当连接类型发生变化时,它显然会起作用。当设备不连接时,activeNetworkInfo
将为空,currentType
将为NO_CONNECTION_TYPE
,与默认情况相同。
public class ConnectivityReceiver extends BroadcastReceiver {
/** The absence of a connection type. */
private static final int NO_CONNECTION_TYPE = -1;
/** The last processed network type. */
private static int sLastType = NO_CONNECTION_TYPE;
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
final int currentType = activeNetworkInfo != null
? activeNetworkInfo.getType() : NO_CONNECTION_TYPE;
// Avoid handling multiple broadcasts for the same connection type
if (sLastType != currentType) {
if (activeNetworkInfo != null) {
boolean isConnectedOrConnecting = activeNetworkInfo.isConnectedOrConnecting();
boolean isWiFi = ConnectivityManager.TYPE_WIFI == currentType;
boolean isMobile = ConnectivityManager.TYPE_MOBILE == currentType;
// TODO Connected. Do your stuff!
} else {
// TODO Disconnected. Do your stuff!
}
sLastType = currentType;
}
}
答案 2 :(得分:3)
在我的情况下,我在onResume
注册了我的BroadcastReceivers,并且仅在onDestroy.
这导致每个广播接收者注册3到4次,具体取决于活动恢复的次数。
根据活动生命周期将广播接收器设置在正确的位置,可以让您停止多次混乱的呼叫。
答案 3 :(得分:1)
在oncreate()
内注册您的LocalBroadcastreceiver,而不是onResume()
。未注册onDestroy
答案 4 :(得分:0)
我有一个应用程序在用户重新联机时上传数据。由于我的广播接收器可以多次接收该意图,因此可能导致数据不止一次上传。为了解决这个问题,我使用的服务如果已经运行则不会做任何事情。
广播接收器:
public class ConnectionChangeReceiver extends BroadcastReceiver {
private static boolean firstConnect = true;
@Override
public void onReceive(Context context, Intent intent) {
final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetInfo != null) {
startService();
}
}
}
服务:
public class MyService extends Service {
private boolean mRunning;
@Override
public void onCreate() {
super.onCreate();
mRunning = false;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!mRunning) {
mRunning = true;
uploadTheData();
}
return super.onStartCommand(intent, flags, startId);
}
}
答案 5 :(得分:0)
我对Aleksander提出的方法感到担忧的是,它没有考虑相同类型的网络更改,例如从一个WiFi网络到另一个WiFi网络。
我建议比较活动网络的extraInfo,其中包含网络名称,例如WiFi SSID或移动网络名称(例如VZW)
services.AddAuthentication(HttpSys.DefaultsAuthenticationSchme)