android学习(二十) 执行网络操作(二) 管理网络使用

检测设备的网络连接

一个设备有各种类型的网络连接。本篇只关注wifi和移动网络连接。
WIFI通常情况下很快,而移动数据通常按量收费,还很昂贵。APP的通常使用策略是在WIFI网络可用的情况下才去获取大量的数据。

在执行网络操作之前,最好是检查一下网络的连接状态。执行网络状态检查,通常会使用到下面的类:
· ConnectivityManager:可以获取当前网络的连接状况,还可以在网络连接状况发生变化时通知应用程序。
· NetworkInfo:描述了指定类型的网络接口状态。
例如:

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 connnected:"+isWifiConn);
        Log.d(DEBUG_TAG,"Mobile connected:"+isMobileConn);

注意:不应该关注网络是否可用,而是应该在每次执行网络操作之前检查isConnected(),因为isConnected()会处理这些状态:移动网络信号不好、飞行模式或者受限的后台数据。

有一个更简明的方法查看网络是否可用。getActiveNetworkInfo()方法会返回一个NetworkInfo的实例,这个对象代表了所能搜索到的第一个已连接的网络接口,如果没有搜索到任何网络连接则会返回null,null代表了互联网络连接不可用。

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

管理网络使用

你可以通过实现一个参数设置的Activity来让用户控制网络资源的使用。
· 你可能只允许用户在WIFI网络状态下才可以上传视频资源。
· 你可能要允许用户设置在指定的条件下才去同步数据,比如:网络可用状态下,或者隔多长时间等等。
·为了使应用可以支持网络的访问和网络管理,你的manifest必须有以下权限和intent过滤器。
- android.permission.INTERNET—允许应用打开网络sockets。
- android.permission.ACCESS_NETWORK_STATE—允许应用访问网络信息。
· 你可以通过声明ACTION_MANAGE_NETWORK_USAGE的Intetn过滤器来指明当前的Activity提供了控制数据使用策略的功能。当应用中含有允许用户管理网络数据使用策略的Activity时,应当声明该Intent过滤器。在这里的示例程序中,这个行为被SettingsActivity所处理,这个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

它实现了OnSharedPreferenceChangeListener接口。每当用户更改了参数,系统会调用onSharedPreferenceChanged()方法。

public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //加载一个preferences文件
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    protected void onResume() {
        super.onResume();
        //注册一个监听,监听key改变
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        //注销在onResume()方法里注册的监听
        //这是一个好习惯,当你的应用不使用它们取消
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }
    //当用户改变了首选项,onSharedPreferenceChanged()
    //会重新开始。为了显示设置refreshDisplay为true
    //这个主activiity应该更新显示
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        //设置refreshDisplay为true为了当使用者回到mainactivity使,
        //新的设置能刷新显示
        NetworkActivity.refreshDisplay = true;
    }
}

响应参数的变更

当用户更改了参数时,这个行为会使APP的习性也跟着发生了变化。在下面的代码段中,APP会在onStart()方法中检查参数配置,如果在设备的当前连接状态与设置之间有相匹配的,那么APP将会下载信息,并刷新界面。

public class NetworkActivity extends AppCompatActivity{
    public static final String WIFI = "Wi-Fi";
    public static final String ANY = "Any";
    private static final String URL = "";
    //wifi是否连接
    private static boolean wifiConnected = false;
    //移动数据是否连接
    private static boolean mobileConnected = false;
    //是否应该更新显示
    public static boolean refreshDisplay;

    //BroadcastReceiver监听网络连接的变化
    private NetworkReceiver receiver;
    public static String sPref;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        receiver = new NetworkReceiver();
        this.registerReceiver(receiver,filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //注销BroadcastReceiver
        if(receiver!=null){
            this.unregisterReceiver(receiver);
        }
    }
    //如果网络连接pref设置允许他刷新显示
    @Override
    protected void onStart() {
        super.onStart();
        //获取使用者的首选项设置
        SharedPreferences sharePrefs = PreferenceManager
                .getDefaultSharedPreferences(this);
        //检索首选项的字符串值。如果未找到偏好值,
        // 则使用第二个参数为默认值
        sPref = sharePrefs.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;
        }
    }
    //使用异步处理数据
    private void loadPage() {
        if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
                || ((sPref.equals(WIFI)) && (wifiConnected))) {
            //处理数据
        } else {
            //展示错误
        }
    }
}

监听连接变化

最后一个问题就是BroadcastReceiver的子类NetworkReceiver。当设备的网络连接发生变化时,NetworkReceiver会拦截CONNECTIVITY_ACTION的行为,这个行为用于检查当前是哪种网络连接状态,并会相应的将wifiConnected和mobileConnected设置为true或者false。那么在NetworkActivity.refreshDisplay设置为true时,那么APP会只下载最近一次的资源。

设置的广播监听器需要在系统不需要的情况下解除注册。示例应用中在onCreate()方法中将NetworkReceiver注册到系统,在onDestroy()方法中将其注销。这比在清单文件中注册更为轻量。当在清单文件中声明了广播接收器,系统会在任何时候调用该接收器,甚至是很久都没有启动过。在Activity中注册与注销广播接收器,可以确保用户在离开APP后系统不会再调用广播接收器。如果在清单文件中注册了广播接收器,那么你必须清楚在什么地方需要它,你可以适当的使用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();
        //检查使用者的prefs 并且进行网络连接。
        // 根据结果决定是否更新显示
        //如果如果userpref只有Wi-Fi,检查是否有Wi-Fi连接的设备
        if(WIFI.equals(sPref) && networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI){
            refreshDisplay = true;
            Toast.makeText(context,"wifi已连接",Toast.LENGTH_SHORT).show();
        } else if(ANY.equals(sPref)&&networkInfo!=null){
            refreshDisplay = true;
        } else {
            refreshDisplay = false;
            Toast.makeText(context, "无网络连接", Toast.LENGTH_SHORT).show();
        }
    }
}

摘自android developer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值