执行网络操作(二):管理网络的使…

- 如果程序频繁访问网络,应当提供给用户相关的设置,允许用户控制程序的数据使用习惯:
> 程序同步数据的周期
> 是否仅在Wifi下执行上传下载操作
> 是否允许在漫游时使用数据
> 这样,用户才不会断然禁止你的程序访问网络
- 参考:

检查设备的网络连接
- Wifi:快,便宜
- 移动网络:贵
- 通常的策略:仅在Wifi下进行大数据传输

- 最佳实践:在执行网络操作前检查网络连接状态:
- ConnectivityManager:应答对网络连接状态的查询,也在网络连接发生变化时发出通知
- NetworkInfo:针对给出的类型描述其网络接口状态
- 例子:测试Wifi和移动网络的状态 - 是否可用,是否连接等:
> 关键组件:ConnectivityManager, NetworkInfo 
> 关键方法:ConnectivityManager.getNetworkInfo(), NetworkInfo.isConnected()
private static final String DEBUG_TAG = "NetworkStatusExample";
...      
ConnectivityManager connMgr = (ConnectivityManager)
        getSystemService
(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
boolean isWifiConn = networkInfo.isConnected();
networkInfo
= connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
boolean isMobileConn = networkInfo.isConnected();
Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);
Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);
- 注意:你的决策不应当基于连接是否“可用”,而总是要检查isConnected(),因为移动网络可能不正常,设备可能处于飞行模式,诸如此类。

- 以下是一种更精确的网络接口检测方法:
> getActiveNetworkInfo()返回一个NetworkInfo对象,标识能找到的第一个已经连接的网络接口
> 返回null,则表示无连接,即网络不可用
> 关键方法: ConnectivityManager.getActiveNetworkInfo()
public boolean isOnline() {
   
ConnectivityManager connMgr = (ConnectivityManager)
            getSystemService
(Context.CONNECTIVITY_SERVICE);
   
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
   
return (networkInfo != null && networkInfo.isConnected());
}  

管理网络使用
- 可以提供给用户一个设置屏幕,让他们显式的控制网络资源的使用,如:
> 设置是否只在Wifi下上传视频
> 设置根据网络可用性或者时间周期之类的标准来执行同步

- 开发支持网络访问和网络使用管理的应用,需要使用相关的权限和intent filters
android.permission.INTERNET:允许应用打开网络套接字
android.permission.ACCESS_NETWORK_STAT:允许应用访问网络相关信息

- 为 ACTION_MANAGE_NETWORK_USAGE行为声明intent filter:
> 以示你的应用定义了一个提供数据使用控制选项的活动
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   
package="com.example.android.networkusage"
    ...
>

   
<uses-sdk android:minSdkVersion="4"
           
android:targetSdkVersion="14" />
       
   
<uses-permission android:name="android.permission.INTERNET" />
   
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

   
<application
        ...
>
        ...
       
<activity android:label="SettingsActivity" android:name=".SettingsActivity">
             
<intent-filter>
               
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
               
<category android:name="android.intent.category.DEFAULT" />
         
</intent-filter>
       
</activity>
   
</application>
</manifest>

实现一个设置活动
Preferences panel Setting a network preference
- SettingsActivity实现了 OnSharedPreferenceChangeListener接口。用户改变了选项后即触发 onSharedPreferenceChanged(),将 refreshDisplay设为true。主活动因此会刷新显示:
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
   
   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
       
// Loads the XML preferences file
        addPreferencesFromResource
(R.xml.preferences);
   
}
 
   
@Override
   
protected void onResume() {
       
super.onResume();

       
// Registers a listener whenever a key changes            
        getPreferenceScreen
().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
   
}
 
   
@Override
   
protected void onPause() {
       
super.onPause();

       
// Unregisters the listener set in onResume().
       
// It's best practice to unregister listeners when your app isn't using them to cut down on
       
// unnecessary system overhead. You do this in onPause().            
       getPreferenceScreen
().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);    
   
}
 
   
// When the user changes the preferences selection,
   
// onSharedPreferenceChanged() restarts the main activity as a new
   
// task. Sets the the refreshDisplay flag to "true" to indicate that
   
// the main activity should update its display.
   
// The main activity queries the PreferenceManager to get the latest settings.
   
   
@Override
   
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {    
       
// Sets refreshDisplay to true so that when the user returns to the main
       
// activity, the display refreshes to reflect the new settings.
       
NetworkActivity.refreshDisplay = true;
   
}
}


响应设置变化
- 当用户改变设置,通常会对应用行为产生重要影响。
- 本例中,程序在onStart()中检查preferences设置。如果设置与设备网络连接能够匹配,应用将下载feed并刷新显示:
public class NetworkActivity extends Activity {
   
public static final String WIFI = "Wi-Fi";
   
public static final String ANY = "Any";
   
private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
   
   
// Whether there is a Wi-Fi connection.
   
private static boolean wifiConnected = false;
   
// Whether there is a mobile connection.
   
private static boolean mobileConnected = false;
   
// Whether the display should be refreshed.
   
public static boolean refreshDisplay = true;
   
   
// The user's current network preference setting.
   
public static String sPref = null;
   
   
// The BroadcastReceiver that tracks network connectivity changes.
   
private NetworkReceiver receiver = new NetworkReceiver();
   
   
@Override
   
public void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
       
// Registers BroadcastReceiver to track network connection changes.
       
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        receiver
= new NetworkReceiver();
       
this.registerReceiver(receiver, filter);
   
}
   
   
@Override
   
public void onDestroy() {
       
super.onDestroy();
       
// Unregisters BroadcastReceiver when app is destroyed.
       
if (receiver != null) {
           
this.unregisterReceiver(receiver);
       
}
   
}
   
   
// Refreshes the display if the network connection and the
   
// pref settings allow it.
   
   
@Override
   
public void onStart () {
       
super.onStart();  
       
       
// Gets the user's network preference settings
       
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
       
       
// Retrieves a string value for the preferences. The second parameter
       
// is the default value to use if a preference value is not found.
        sPref
= sharedPrefs.getString("listPref", "Wi-Fi");

        updateConnectedFlags
();
       
       
if(refreshDisplay){
            loadPage
();    
       
}
   
}
   
   
// Checks the network connection and sets the wifiConnected and mobileConnected
   
// variables accordingly.
   
public void updateConnectedFlags() {
       
ConnectivityManager connMgr = (ConnectivityManager)
                getSystemService
(Context.CONNECTIVITY_SERVICE);
       
       
NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
       
if (activeInfo != null && activeInfo.isConnected()) {
            wifiConnected
= activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
            mobileConnected
= activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
       
} else {
            wifiConnected
= false;
            mobileConnected
= false;
       
}  
   
}
     
   
// Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
   
public void loadPage() {
       
if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
               
|| ((sPref.equals(WIFI)) && (wifiConnected))) {
           
// AsyncTask subclass
           
new DownloadXmlTask().execute(URL);
       
} else {
            showErrorPage
();
       
}
   
}
...
   
}

侦测连接变化

- 最后用一个BroadcastReceiver的子类来处理连接变化
- 拦截 CONNECTIVITY_ACTION行为,确定网络状态如何,从而设置两个标记
- NetworkReceiver在活动创建和销毁时注册、注销,这样只有在使用程序时才会工作,避免费电
- 如果在manifest中注册,则全程激活,只能通过  setComponentEnabledSetting()来开关
public class NetworkReceiver extends BroadcastReceiver {   
     
@Override
public void onReceive(Context context, Intent intent) {
   
ConnectivityManager conn =  (ConnectivityManager)
        context
.getSystemService(Context.CONNECTIVITY_SERVICE);
   
NetworkInfo networkInfo = conn.getActiveNetworkInfo();
       
   
// Checks the user prefs and the network connection. Based on the result, decides whether
   
// to refresh the display or keep the current display.
   
// If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
   
if (WIFI.equals(sPref) && networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
       
// If device has its Wi-Fi connection, sets refreshDisplay
       
// to true. This causes the display to be refreshed when the user
       
// returns to the app.
        refreshDisplay
= true;
       
Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();

   
// If the setting is ANY network and there is a network connection
   
// (which by process of elimination would be mobile), sets refreshDisplay to true.
   
} else if (ANY.equals(sPref) && networkInfo != null) {
        refreshDisplay
= true;
                 
   
// Otherwise, the app can't download content--either because there is no network
   
// connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
   
// is no Wi-Fi connection.
   
// Sets refreshDisplay to false.
   
} else {
        refreshDisplay
= false;
       
Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();
   
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值