首先只是简单显示网络是否变化,代码如下,
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!
没有评论:
发表评论