读书人

Android Training - 网络操作(二) - 管

发布时间: 2012-09-24 13:49:41 作者: rapoo

Android Training - 网络操作(2) - 管理网络用途
如果程序需要执行很多网络操作,那么你应该让用户能够设置网络连接和管理数据,比如,多久同步一次数据,是否只有Wi-Fi连接时才上传和下载数据,漫游情况下是否使用数据等。
检查设备的网络连接设备可以使用多种方式连接网络,下面我们只关注Wi-Fi和移动网络。
Wi-Fi比较快,移动网络一般是计费的,通常的做法是在Wi-Fi状态下获取大数据。
在使用网络前,我们应该检查网络连接状态,然后根据状态执行操作或者返回提示,检查网络需要下面这些类:ConnectivityManager:返回网络状态,网络连接改变时发出通知。NetworkInfo:网络接口状态的类型。下面的代码判断什么网络类型可用,并且已连接:

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表示没有网络连接:
public boolean isOnline() {    ConnectivityManager connMgr = (ConnectivityManager)             getSystemService(Context.CONNECTIVITY_SERVICE);    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();    return (networkInfo != null && networkInfo.isConnected());}  

管理网络用途你可以使用一个activity来让用户显式的控制网络资源,例如:你可以允许用户在有Wi-Fi网络的时候上传视频。可以根据网络可用性,时间间隔来同步数据等。开发支持网络权限和管理网络用途的程序,你需要有下面这些权限:清单文件中要有下面的权限:
android.permission.INTERNET - 允许程序打开网络。
android.permission.ACCESS_NETWORK_STATE - 允许程序获取网络信息。你可以在intent filter中添加ACTION_MANAGE_NETWORK_USAGE action(4.0开始使用)来声明程序定义一个activity来控制网络用途。
<?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>
实现一个网络选择Activity上面的SettingsActivity是PreferenceActivity的子类,它显示一个选择窗口让用户选择:为每个XML feed entry展示概要,还是只显示链接。有任何网络连接就下载XML,还是只是有Wi-Fi时才下载。 Android Training - 网络操作(二) - 管理网络用途 Android Training - 网络操作(二) - 管理网络用途下面是SettingsActivity的代码。实现了onSharedPreferenceChangeListener接口。当用户改变选项时,触发onSharedPreferenceChanged()方法,设置refreshDisplay为true。当用户返回主activity时刷新页面:
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()中检查选项设置,这里有一个设置和网络连接的匹配,比如,设置为“Wi-Fi”,而网络连接也是Wi-Fi,那么程序下载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子类,NetworkReceiver。当网络连接方式改变时,NetworkReceiver拦截CONNECTIVITY_ACTION动作,判断网络连接状态,然后设置wifiConnected和mobileConnected为true或者false。结果就是当用户下一次返回程序时,如果NetworkActivity.refreshDisplay为true就下载最新的feed,更新显示。
程序在onCreate()中注册BroadcastReceiver,前提是需要在清单文件中声明<receiver>:
public class NetworkReceiver extends BroadcastReceiver {         @Overridepublic 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();    }}


读书人网 >网络基础

热点推荐