11.5. NetworkReceiver

优质
小牛编辑
129浏览
2023-12-01

11.5.NetworkReceiver

现在,我们的Service已经可以跟随系统启动,并每分钟定时尝试连接服务端以获取数据。但这样的设计存在一个问题,那就是即使设备没有联网,程序仍定时试图连接服务端抓取数据,这样只会无谓地浪费电能。假如你正在坐一趟国际航班,上面没有网络连接,几个小时下来不难想像这将多么浪费。电能与网络连接都不是永久的,我们应尽量减少无谓的操作。

一个解决方案是监听网络的连接情况,并由它来决定Service的启动关闭。系统会在网络连接情况发生变化时发送一条Intent,另外也有系统服务可用于查看当前的网络连接情况。

接下来,我们创建一个新的Receiver:NetworkReceiver。步骤同前面一样,新建一个Java类,并继承BroadcastReceiver,然后在Manifest文件中注册它。

例 11.8. NetworkReceiver.java

package com.marakana.yamba6;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.net.ConnectivityManager;

import android.util.Log;

public class NetworkReceiver extends BroadcastReceiver { //

public static final String TAG = "NetworkReceiver";

@Override

public void onReceive(Context context, Intent intent) {

boolean isNetworkDown = intent.getBooleanExtra(

ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); //

if (isNetworkDown) {

Log.d(TAG, "onReceive: NOT connected, stopping UpdaterService");

context.stopService(new Intent(context, UpdaterService.class)); //

} else {

Log.d(TAG, "onReceive: connected, starting UpdaterService");

context.startService(new Intent(context, UpdaterService.class)); //

}

}

}

  1. 同前面一样,它也是BroadcastReceiver的子类。
  2. 系统会在发送广播时,在这条Intent中加入一组附加数据,表示网络的连接情况,也就是ConnectivityManager.EXTRA_NO_CONNECTIVITY所对应的布尔值。前面我们曾为自己的Intent加入附加数据,在这里相反,只管取出数据即可。若这个值为true,则表示网络断开。
  3. 如果网络断开,则向UpdaterService发送一条Intent,令它停止。通过系统传入的Context对象。
  4. 如果网络连接,则启动UpdaterService,与前面相反。

Note:

在Activity或者Service中,我们可以直接调用startActivity()、startService()、stopService()等方法。这是因为Activity与Service都是Context的子类,它们自身就是一个Context对象。但BroadcastReceiver并不是Context的子类,因此发送Intent,仍需通过系统传递的Context对象。

新的Receiver已经编写完毕,接下来将它注册到Manifest文件。

例 11.9. AndroidManifest.xml: 在<application>标签之下

...

<receiver android:name=".NetworkReceiver">

<intent-filter>

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

</intent-filter>

</receiver>

...

我们还需要更新应用程序所需的权限。在系统中,网络连接状况是受保护的信息,要获取它,我们需要用户赋予应用程序以专门的权限。

例 11.10. AndroidManifest.xml: 在<manifest>标签之下

...

<uses-permission android:name="android.permission.INTERNET" /> <!-- -->

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- -->

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

...

  1. 访问网络所需的权限。这是在第六章Android用户界面中定义的。如果没有这项权限,应用程序就无法连接到网络。
  2. 监视系统启动所需的权限。如果没有这项权限,应用程序就无法捕获系统启动这一事件,而且没有任何错误提示。
  3. 监视网络连接情况所需的权限。与上面相似,如果没有这项权限,应用程序就无法获知网络连接情况的变化,而且没有任何错误提示。