首先只是简单显示网络是否变化,代码如下,
public class MainActivity extends Activity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");//网络发生变化时,系统发出android.net.conn.CONNECTIVITY_CHANGE广播;想监听什么,就在这里添加相应action值即可
networkChangeReceiver = new NetworkChangeReceiver();
//将NetworkChangeReceiver的实例和IntentFilter实例都传进去,故前者就收到所有值为android.net.conn.CONNECTIVITY_CHANGE的广播;实现了监听网络变化的功能
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver); //动态注册的广播接收器一定逗得取消注册
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
//每当网络发生变化,onReceive会得到执行
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
}
}
}
运行正常,当网络变化时,toast会显示“network is changed”,但是依旧不知道此时是有网络还是没有网络。
为了准确告诉是有网络还是没有网络,引入ConnectivityManager,创建其实例,调用它的getActiveNetworkInfo()方法得到NetworkInfo实例,然后通过使用NetworkInfo的isActivity()方法判断当前是否有网络。代码如下,只修改了NetworkChangeReceiver类部分。
public class MainActivity extends Activity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");//网络发生变化时,系统发出android.net.conn.CONNECTIVITY_CHANGE广播;想监听什么,就在这里添加相应action值即可
networkChangeReceiver = new NetworkChangeReceiver();
//将NetworkChangeReceiver的实例和IntentFilter实例都传进去,故前者就收到所有值为android.net.conn.CONNECTIVITY_CHANGE的广播;实现了监听网络变化的功能
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver); //动态注册的广播接收器一定逗得取消注册
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
//每当网络发生变化,onReceive会得到执行
public void onReceive(Context context, Intent intent) {
// Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
//准确告诉是有网络还是没有网络
ConnectivityManager connectionManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()) {
Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(context, "network is not available", Toast.LENGTH_SHORT).show();
}
}
}
}
再次运行之,应用崩溃,熟悉的Unfortunately, APP has stopped映入眼帘,娘希匹的!问题如LogCat所示,
05-23 23:57:48.666: E/AndroidRuntime(16389): FATAL EXCEPTION: main
05-23 23:57:48.666: E/AndroidRuntime(16389): Process: com.example.broadcasttest, PID: 16389
05-23 23:57:48.666: E/AndroidRuntime(16389): java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x4000010 (has extras) } in com.example.broadcasttest.MainActivity$NetworkChangeReceiver@41fd2280
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:769)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.os.Handler.handleCallback(Handler.java:733)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.os.Handler.dispatchMessage(Handler.java:95)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.os.Looper.loop(Looper.java:136)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.app.ActivityThread.main(ActivityThread.java:5086)
05-23 23:57:48.666: E/AndroidRuntime(16389): at java.lang.reflect.Method.invokeNative(Native Method)
05-23 23:57:48.666: E/AndroidRuntime(16389): at java.lang.reflect.Method.invoke(Method.java:515)
05-23 23:57:48.666: E/AndroidRuntime(16389): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
05-23 23:57:48.666: E/AndroidRuntime(16389): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
05-23 23:57:48.666: E/AndroidRuntime(16389): at dalvik.system.NativeStart.main(Native Method)
05-23 23:57:48.666: E/AndroidRuntime(16389): Caused by: java.lang.SecurityException: ConnectivityService: Neither user 10118 nor current process has android.permission.ACCESS_NETWORK_STATE.
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.os.Parcel.readException(Parcel.java:1465)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.os.Parcel.readException(Parcel.java:1419)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.net.IConnectivityManager$Stub$Proxy.getActiveNetworkInfo(IConnectivityManager.java:817)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.net.ConnectivityManager.getActiveNetworkInfo(ConnectivityManager.java:604)
05-23 23:57:48.666: E/AndroidRuntime(16389): at com.example.broadcasttest.MainActivity$NetworkChangeReceiver.onReceive(MainActivity.java:47)
05-23 23:57:48.666: E/AndroidRuntime(16389): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:759)
05-23 23:57:48.666: E/AndroidRuntime(16389): ... 9 more
很明显,是修改了NetworkChangeReceiver类后出现的问题。那就对这几行代码肉眼排查。
基本没有发现问题。如果非要鸡蛋挑骨头的话,那就是networkInfo可能会是null,而null.isActivityable()是行不通的,但是我的条件语句杜绝了这样的情况发生。那是怎么回事儿呢?
再仔细查看LogCat输出内容,可见一行,
05-23 23:57:48.666: E/AndroidRuntime(16389): Caused by: java.lang.SecurityException: ConnectivityService: Neither user 10118 nor current process has android.permission.ACCESS_NETWORK_STATE.
这就是问题所在了!
解决方案
在AndroidManifest中的<manifest> </manifest>间添加如下代码,重新运行,问题解决了!LogCat输出的刷刷绿色看起来真漂亮!
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
可是,这是为什么呢?
谷歌了一番,了解到,Android系统为了保证安全,在程序需要访问一些系统关键信息,如本次访问系统网络情况,必须在配置文件中声明权限,否则程序会崩溃。
LOL!
没有评论:
发表评论