文档章节

Android文档学习06_网络2

larryee
 larryee
发布于 2015/01/14 21:35
字数 1760
阅读 4
收藏 0

如果你的程序要执行大量的网络操作,你应该提供用户设置来允许用户控制你应用程序数据的习惯。 比如你的程序多久会进行数据同步,是否只有在拥有Wi-Fi的情况下才执行上传和下载操作,是否使用数据漫游等等。将这些控制变量提供给他们,当用户接近自己的(网络流量)限制时,就不太可能禁用你应用程序对后台数据的访问通道。因为他们可以精确的控制你的应用程序使用多少数据。


所以应用程序的一般策略是只有在Wi-Fi可用的情况下才会获取大量数据


检查网络连接一般使用以下类:

  • ConnectivityManager: 响应网络连接状态查询,同时能在网络连接状态发生改变时通知程序。
  • NetworkInfo:描述给定类型的网络接口状态(无论是移动网络还是Wi-Fi)

以下代码片段测试了Wi-Fi和移动网络连接,它决定了这些网络接口是否可用(即网络连接是否存在) 和/或 是否已经连接网络(即网络连接存在以及是否有可能建立socket通道并传输数据):


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);
 


需要在执行网络操作之前检查isConnectioned() (看该方法返回是否已经网络连接成功了),在连接成功了之后再执行操作(因为有可能你的移动网络不够稳定,手机处于飞行模式,限制后台数据等状态;译者注:在这种情况下,你可能会得到当前网络可用,但是无法连接的情况;)


更简洁的检查网络接口是否可用的方式如下: getActiveNetworkInfo()方法返回一个NetworkInfo实例,这个实例表示的是系统能够找到并连接的第一个网络接口。如果网络接 口是可以连接的,但是getNetworkInfo返回的是null(这表示当前网络连接无效)


public boolean isOnline() {
    ConnectivityManager connMgr = (ConnectivityManager) 
            getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    return (networkInfo != null && networkInfo.isConnected());
}  
 


permission权限:

android.permission.INTERNET 允许用户打开网络通道。
android.permission.ACCESS_NETWORK_STATE允许程序访问网络相关信息。

intent filter:

可以为ACTION_MANAGE_NETWORK_USAGE action声明一个intent filter(在Android4.0中有介绍)表明你的应用程序定义了一个提供控制(网络)数据运用选项的activity。 ACTION_MANAGE_NETWORK_USAGE显示了管理特定程序的网络数据运行的设置。当你的应用程序有了一个“设置选项”的activity,用以允许用户控制网络使用,你应该为这个activity定义一个intent filter。在这个简单的例子中,这个action是由SettingActivity类控制的,这个activity显示了一个“设置选项”的UI给用户,让用户决定什么时候下载数据源。


<?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>


这里的SettingActivity,注意它实现了OnSharedPreferenceChangeListener,当用户改变了设置,就会触发java.lang.String) onSharedPreferenceChanged()方法,并在这方法中设置refresDisplay为true。这样导致当用户返回主activity时显示会刷新。



public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        // 加载XML设定文件(XML preferences file)
        addPreferencesFromResource(R.xml.preferences);
    }
 
    @Override
    protected void onResume() {
        super.onResume();
 
        // 每当键发生变化注册一个监听事件
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }
 
    @Override
    protected void onPause() {
        super.onPause();
 
       // 注销onResume()方法中设置的监听.  
       // 注销监听最好是当你的程序不使用它们以减少系统不必要的开销, 你可以在onPause()方法中做这件事        
       getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);    
    }
 
    // 当用户改变设置的选项,onSharedPreferenceChanged()重新启动主activity作为一个新任务,
    // 设置refreshDisplay为true以表明主activity应该更新它的显示, 主activity查询PreferenceManager得到最新的设置.
 
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {    
        // 设置refreshDisplay为true,这样当用户返回主activity,显示会根据新设置进行刷新.
        NetworkActivity.refreshDisplay = true;
    }
}


当用户在设置界面修改了选项时,通常都会对应用程序的行为产生影响。在这节代码片段中,应用在onStart()方法中检查设置选项,如果设置和设备的网络连接能够匹配(比如设置中是“Wi-Fi”并且设备也拥有Wi-Fi连接),应用就下载数据源并刷新显示。


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";
 
    // 是否有一个Wi-Fi连接.
    private static boolean wifiConnected = false; 
    // 是否有一个手机移动网络连接.
    private static boolean mobileConnected = false;
    // 显示是否需要刷新.
    public static boolean refreshDisplay = true;
 
    // 用户当前网络优先设置.
    public static String sPref = null;
 
    // BroadcastReceiver追踪网络连接变化.
    private NetworkReceiver receiver = new NetworkReceiver();
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        // 注册BroadcastReceiver追踪网络连接变化.
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        receiver = new NetworkReceiver();
        this.registerReceiver(receiver, filter);
    }
 
    @Override 
    public void onDestroy() {
        super.onDestroy();
        // 当应用销毁,注销BroadcastReceiver.
        if (receiver != null) {
            this.unregisterReceiver(receiver);
        }
    }
 
    // 如果网络连接和优先设置允许,刷新显示。
 
    @Override
    public void onStart () {
        super.onStart();  
 
        // 得到用户网络设置
        SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
 
        // 获取设置的字符串,第二个参数为当获取不到设置的值时默认使用的值.
        sPref = sharedPrefs.getString("listPref", "Wi-Fi");
 
        updateConnectedFlags(); 
 
        if(refreshDisplay){
            loadPage();    
        }
    }
 
    // 检查网络连接并设置wifiConnected和mobileConnected变量. 
    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;
        }  
    }
 
    // 使用AsyncTask子类从stackoverflow.com下载XML数据源.
    public void loadPage() {
        if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
                || ((sPref.equals(WIFI)) && (wifiConnected))) {
            // AsyncTask的子类
            new DownloadXmlTask().execute(URL);
        } else {
            showErrorPage();
        }
    }
...
 
}



简单的应用在onCreate方法中注册了BroadcastReceiver NetworkReceiver,并在onDestroy方法中将其注销。这比在manifest文件中声明<receiver>标签更轻量级

如果你在manifest中声明了一个<receiver>,并且确切的知道在哪里你需要用到它,你可以用int, int) 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();
 
    // 检查用户首选项和网络连接.基于这个结果,决定刷新界面或保持当前显示.
    // 如果用户偏好Wi-Fi, 检查设备是否拥有Wi-Fi连接.
    if (WIFI.equals(sPref) && networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
        // 如果设备有Wi-Fi连接,设置refreshDisplay为true
        // 这是因为当用户返回到应用时,显示应该被刷新.
        refreshDisplay = true;
        Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show();
 
    // 如果设置为任何网络并且这里有一个网络连接,设置refreshDisplay为true.
    } else if (ANY.equals(sPref) && networkInfo != null) {
        refreshDisplay = true;
 
    // 否则, 应用无法下载内容--可能是因为没有网络连接(mobile或Wi-Fi), 
    // 或者是应为用户首选项是Wi-Fi,但没有Wi-Fi连接.设置refreshDisplay为false。
    } else {
        refreshDisplay = false;
        Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();
   




本文转载自:http://blog.csdn.net/u012992171/article/details/17225067

larryee
粉丝 0
博文 51
码字总数 393
作品 0
浦东
私信 提问
Android NDK 编程环境搭建

标 题: HWOTO install and setup Android NDK for Windows 发布日期: 2009-06-27 18:00 作 者: Androidin Emck 说 明: 此文档严格遵循GPL协议,转贴请保持此文档的完整性! 1. 下载Android 1.5...

红薯
2009/12/22
5.8K
7
社会化分享组件友推服务评测

评测环境 WIFI网络下: 测试环境 Windows 7旗舰版(64x)+Eclipse+红米 测试对象 友推 测试手机 红米 系统版本 Android 4.2.1 手机网络 WIFI 测试方法 客户端运行DEMO+触屏测试 测试时间 20...

bidaround
2014/07/25
79
1
[初学嵌入式]完全没有接触过linux也可以轻松玩转4412开发板

需要按照以下方法和步骤来学习,轻松玩转开发板。 以下学习内容均有配套视频。 1.开发板上电测试以及提供的基本资料介绍:所 学手册的章节包括(第一章节) 2.安装超级终端,理解uboot模式和...

topeet
2015/08/03
779
0
介绍一个Android UI设计网站

十分有趣。“Ice Cream Sandwich (Android 4.0) 是我们目前为止最大的一次重新设计——对用户和开发者皆是如此。我们用新的交互和样式增强了UI框架,能让你创建比以往更加简单更加炫丽的And...

xyxzfj
2012/01/16
299
0
[无线] Android 系统开发学习杂记

本文旨在记录在研究和开发 Android 系统的过程中学习到的星星点点,以备日后之用~ 内容包括:开发环境、安装程序、系统分区、目录概览、进程分析、内核对比。 > 开发环境 1、安装 Eclipse 和...

长平狐
2012/11/19
338
0

没有更多内容

加载失败,请刷新页面

加载更多

高速PCB设计软件allegro中与网络有关的约束规则设置

在allegro pcb的设计过程中,设计约束规则包括时序规则、间距规则、信号完整性规则以及物理规则等,本期主要详细讲解与物理、间距与电气约束中的线宽、线间距物理规则的设置。 一、线宽设置 ...

demyar
6分钟前
1
0
Linux 启动停止SpringBoot jar 程序部署Shell 脚本

#!/bin/bash #这里可替换为你自己的执行程序,其他代码无需更改 APP_NAME=algorithm.jar #使用说明,用来提示输入参数 usage() { echo "Usage: sh 执行脚本.sh [start|stop|restart|status]...

草庐过客
7分钟前
2
0
mysql-connector-java驱动升级到8.0后数据库保存时间出现时差

1.问题:在一个新项目中用到了新版的mysql jdbc 驱动后,发现保存到数据库的时间出现了时差 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId>......

ValSong
9分钟前
2
0
好程序员大数据教程Scala系列之隐式转换和隐式参数

5.1. 概念 隐式转换和隐式参数是Scala中两个非常强大的功能,利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节。 5.2. 作用 隐式的对类的方法进行增强...

好程序员官网
13分钟前
1
0
多线程必备

初次接触线程,可能有很多初学者搞不明白,始终云里雾里,那么本篇文章直接带大家介绍多线程必须知道的几个点 接下来没有多余,直接上干货 1. 进程和线程的区别是什么? 进程是执行着的应用程序,...

理性思考
16分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部