Android 网络属性详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zxw136511485/article/details/72956055

    在实际开发中,我们可能会遇到需要判断当前Android设备的网络等方面的需求,这里所说的网络是指WiFi和手机移动网络,也就是指手机的上网方式。最近有空,就来总结有关Android网络方面的。废话不多说,速度进入下文!

一、前言。

    正文开始之前,先了解几个类。

 1.ConnectivityManager。

Class that answers queries about the state of network connectivity. It also notifies applications when network connectivity changes. 
Get an instance of  The primary responsibilities of this class are to:
    Monitor network connections (Wi-Fi, GPRS, UMTS, etc.)
    Send broadcast intents when network connectivity changes
    Attempt to "fail over" to another network when connectivity to a network is lost
    Provide an API that allows applications to query the coarse-grained or fine-grained state of the available networks
    Provide an API that allows applications to request and select networks for their data traffic

简单翻译:

    这个类,用来答复网络连接状态的查询。它也通知应用当网络连接发生改变时。得到这个类的实例通过Context.getSystemService(Context.CONNECTIVITY_SERVICE)。

这个类的主要职责:

(1).监控网络连接(WIFI ,GPRS , UMTS 等);

(2).当网络连接发生改变时,发生广播;

扫描二维码关注公众号,回复: 2924620 查看本文章

(3).当网络连接丢失时,尝试连接另一个网络;

(4).提供了一个接口允许应用程序用来查询可用网络的粗粒度和细粒度;

(5).提供了一个接口允许应用程序请求和选择网络进行数据通信。

2.NetworkInfo。

Describes the status of a network interface.

Use getActiveNetworkInfo() to get an instance that represents the current network connection. 
描述网络接口的状态。

使用 getActiveNetworkInfo() 来获取当前网络连接的实例。

(1). getType()

报告此NetworkInfo中所属的网络类型。

返回值可为:TYPE_MOBILE, TYPE_WIFI, TYPE_WIMAX, TYPE_ETHERNET, TYPE_BLUETOOTH。

可以看出还可以监控蓝牙的连接状态。

(2).isAvailable()

指示是否可以进行网络连接。该设备不在任何此类网络类型覆盖范围内;该设备在除了家庭网络的以外的网络上(例如,漫游),并且数据漫游已被禁止;设备的无线电被关闭,例如开启了飞行模式。

返回值 如果网络可用,返回true,否则返回false。

(3).isConnected()

指示网络是否连接并且可以建立连接并传递数据。在数据传递之前,总要调用它。

返回值 如果网络连接存在,返回true,否则返回false。
(4).isConnectedOrConnecting()

指示网络是否连接或者正在建立过程中。这对于需要执行网络相关的任何操作而不是读或者写数据的应用程序来说很有用。对于后者,调用isConnected()替代,保证网络完全可用。

返回 如果网络连接存在或者正在建立过程中,返回true,否则返回false。

(5).getTypeName()

返回一个可读的名称用来描述网络的类型,例如“WIFI”和“MOBILE”。

(6).int getSubtype ()

返回描述网络子类型的网络类型特定整形。

(7).NetworkInfo getNetworkInfo (int networkType)

6.0已经废弃了该方法。该方法不支持相同类型的多个连接网络。可以使用getAllNetworks() 和etNetworkInfo(android.net.Network)代替。

返回特定网络类型的连接状态信息。使用时,需要添加权限‘ACCESS_NETWORK_STATE’。

3.TelephonyManager
Provides access to information about the telephony services on the device. Applications can use the methods in this class to 
determine telephony services and states, as well as to access some types of subscriber information. Applications can 
also register a listener to receive notification of telephony state changes.

You do not instantiate this class directly; instead, you retrieve a reference to an instance through 
Context.getSystemService(Context.TELEPHONY_SERVICE). The returned TelephonyManager will use the default subscription for all 
calls. To call an API for a specific subscription, use createForSubscriptionId(int). 
e.g. telephonyManager = defaultSubTelephonyManager.createForSubscriptionId(subId);

Note that access to some telephony information is permission-protected. Your application cannot access the protected 
information unless it has the  appropriate permissions declared in its manifest file. Where permissions apply, 
they are noted in the the methods through which you access the protected information. 
提供对设备上的有关电话服务的访问信息。应用程序能使用该类的方法来缺点电话服务和状态,以及访问一些类型的订阅信息。应用程序也可以注册一个监听器来解出电话状态改变通知。
你不用直接去实例化这个类,相反,你通过Context.getSystemService(Context.TELEPHONY_SERVICE)来获取它的实例。它返回TelephonyManager 是一个默认地订阅为所有的调用者,要调用一个特定的订阅的接口,使用createForSubscriptionId(int),例如telephonyManager = defaultSubTelephonyManager.createForSubscriptionId(subId);请注意,访问某些电话信息是权限保护的,你的应该程序无法受保护的信息除非你在它的清单文件中声明了相应的权限。当权限申请后,在方法中可以访问受包含的信息。
(1).getDataState()
返回一个常量表示当前数据连接状态(蜂窝)。常量有以下4种:
    DATA_DISCONNECTED --数据连接状态为断开状态,IP流量不可用;
    DATA_CONNECTING----数据连接状态为当前正在设置数据连接;
    DATA_CONNECTED----数据连接状态为连接状态,IP流量应该可用;
    DATA_SUSPENDED----数据连接状态为暂停状态,连接已启动,但IP流量暂时不可用,例如,在2G网络中,当语音呼叫到达时,数据活动可能被停止;
4.WifiManager
This class provides the primary API for managing all aspects of Wi-Fi connectivity. Get an instance 
of this class by calling Context.getSystemService(Context.WIFI_SERVICE). It deals with several categories of items:

    The list of configured networks. The list can be viewed and updated, and attributes of individual entries can be modified.
    The currently active Wi-Fi network, if any. Connectivity can be established or torn down, 
      and dynamic information about the state of the network can be queried.
    Results of access point scans, containing enough information to make decisions about what access point to connect to.
    It defines the names of various Intent actions that are broadcast upon any sort of change in Wi-Fi state. 

This is the API to use when performing Wi-Fi specific operations. To perform operations that pertain to 
network connectivity at an abstract level, use ConnectivityManager. 
简单翻译
      这个类提供了管理有关WiFi连接的所有主要的接口。得到这个类的实例通过调用 Context.getSystemService(Context.WIFI_SERVICE)。它涉及几个类别的项目:
             已配置的网络列表。可以查看和更新列表。并且可以修改各个条目的属性。
             当前活动的WiFi网络(如果有),连接可以建立或拆除,并且查询有关网络状态的动态信息。
             接入点扫描的结果,包含足够的信息来决定要连接的接入点。
             它定义了WiFi在任何改变之后广播的各种意图动作的名称。
     这是在执行特定WiFi的操作时使用的接口,执行与之相关的操作在抽象的层面上的网络连接,使用ConnectivityManager。
(1).SSID  
SSID(Service Set Identif)用于标识无线局域网(无线网名),SSID不同的无线网络是无法进行互访的。
网络的SSID。可以是ASCII字符串,必须用双引号引起来(例如,“mynetwork”,或一个字符串进制数字,不加引号(例如,01a243f405)。
(2).setWifiEnabled (boolean enabled)
启用或禁用WiFi。
参数:true 启用,false 禁用。
返回值:如果操作成功返回true(或者现有状态与请求状态相同)。
(3).boolean isWifiEnabled ()
返回WiFi是否启用或禁用。
(4).boolean startScan ()
请求扫描接入点。立即返回。结果的可用性稍后通过扫描完成后发送的异步事件知道。
(5).WifiInfo getConnectionInfo ()
返回当前WiFi连接的动态信息,如果有的话。
(6).int getWifiState ()
获取启用WiFi的状态。
返回值有: 
     WIFI_STATE_DISABLED,       WiFi 禁用;
     WIFI_STATE_DISABLING,      WiFi正在禁用中。如果成功完成,状态将改变为WIFI_STATE_DISABLED;
     WIFI_STATE_ENABLED,        WiFi开启
     WIFI_STATE_ENABLING,       WiFi正在开启中。如果成功完成,状态将改变为WIFI_STATE_ENABLED;
     WIFI_STATE_UNKNOWN       WiFi状态未知。当启用或禁用发生错误时,状态为WIFI_STATE_UNKNOWN    。
(7).List<ScanResult> getScanResults ()
返回最新接入点扫描结果。
返回值:在最近扫描中找到的接入点列表。应用必需有ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限才能取得有效结果。如果存在远程异常(例如,系统服务的通讯问题或框架内的异常)将返回空列表。
5.WifiConfiguration
表示WiFi网络的配置类,包括安全配置。
(1).SSID
SSID(Service Set Identif)用于标识无线局域网(无线网名),简单来说,就是网络的名称。 可以是一个ASCII字符串,它必须用双引号(例如“MyNetwork”)或十六进制数字的字符串括起来,不用引号括起来(例如01a243f405)。
(2).networkId
supplicant用于标识此网络配置项的ID。它必须作为一个参数参数给调用的supplicant。
(3).int addNetwork (WifiConfiguration config)
添加一个新的网络描述到网络配置集合中。提供的配置对象的networkId将被忽略。默认情况下,新网络被标记为禁用,如果要启用,调用enableNetwork(int, boolean)。
(4).boolean enableNetwork (int netId,  boolean disableOthers)
允许先前配置的网络与之关联。如果disableOthers为true,则所有的其他配置的网络都被禁用,并且尝试连接到所选网络,这可能会触发异步状态更改事件。
参数:
    int netId  ,配置网络列表中网络的id;
    boolean disableOthers, 如果为true,则禁用调用所有其他的网络。选择要连接网络,那么该参数是true。
(5).boolean removeNetwork (int netId)
从配置的网络列表中删除指定的网络。这可能会触发异步状态更改事件。
参数:  netId,用于标识网络配置;
返回值:操作成功返回true。
PS: 
了解几个权限。
1.String ACCESS_WIFI_STATE
允许应用程序访问有关WiFi网络信息。在清单文件中,使用时值为"android.permission.ACCESS_WIFI_STATE" 。
2.String CHANGE_WIFI_STATE
允许应用程序改变WiFi的连接状态。在清单文件中,使用时值为"android.permission.CHANGE_WIFI_STATE" 。
3.String CHANGE_WIFI_MULTICAST_STATE
允许应用程序进入多播模式。在清单文件中,使用时值为"android.permission.CHANGE_WIFI_MULTICAST_STATE" 。
在使用WiFi时,需要添加权限
<manifest ...>
    <uses-feature android:name="android.hardware.wifi" />
    ...
</manifest>
二、简单示例。
   首先新建项目。(不列举了)记得加入权限。
    1.WiFi。
     首先是布局文件,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.test.MainActivity" >

   
    <Button
        android:id="@+id/btn1"
        android:text="开启wifi"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
      />
    <Button
        android:id="@+id/btn2"
        android:text="关闭wifi"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
      />
   
</LinearLayout>
运行后的效果图,如下所示,有两个按钮,一个是打开WiFi,另一个是关闭WiFi。

下面是主要代码。
public class MainActivity extends Activity {
    private WifiManager wifiManager;  
	private String tag="MainActivity";  

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);  
		findViewById(R.id.btn1).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if (!wifiManager.isWifiEnabled())  
                {  
                    wifiManager.setWifiEnabled(true);  
                    Log.e(tag, "正在打开wifi");
                }  
			}
		});
		findViewById(R.id.btn2).setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if (wifiManager.isWifiEnabled())  
				{  
					wifiManager.setWifiEnabled(false);  
					Log.e(tag, "正在关闭wifi");
				}  
			}
		});
	
	
	}

}
打开、关闭WiFi需要几秒的执行过程。代码比较简单,就不多说了!下面是应用运行的视频,


该实例只是简单的开启、禁用WiFi,有关WiFi更多的管理,后续会有相关的文章。
     2.网络判断。
判断当前的网络连接信息。
    布局文件就不贴代码了(就一个按钮,点击时获取网络信息)。
(1).首先判断网络的类型,是移动网络还是WiFi。
下面直接看主要代码,
public class SecondActivity extends Activity {
	
	TextView tv;
	Button btn;
	ConnectivityManager mConnectivityManager;
	private static final String TAG="SecondActivity";  
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main2);
		tv=(TextView)findViewById(R.id.tv);
		btn=(Button)findViewById(R.id.btn1);
		mConnectivityManager =(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);//获取一个ConnectivityManager对象
		btn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				getNetworkInfo();
			}
		});
	}

	/**
	 * 获取网络信息
	 */
	private void getNetworkInfo(){
		NetworkInfo info=(NetworkInfo)mConnectivityManager.getActiveNetworkInfo();
		if(info!=null){
			int type=info.getType();
Log.e(TAG, "type="+type+", typeName="+info.getTypeName());
			tv.setText(info.getTypeName());
			if(info.isConnected()){
				switch (type) {
				case ConnectivityManager.TYPE_WIFI:
					
					break;
				case ConnectivityManager.TYPE_MOBILE:
				break;
				default:
					break;
				}
			}
		}else{
			Log.e(TAG, "无连接");
		}
	}
}
应用运行后,切换移动网络和WiFi后的log截图如下,(分别点了2次按钮)

PS: 切换移动网络和WiFi,这个过程有耗时!
(2).接着判断移动网络具体的类型,是2G、3G还是4G。
PS: 判断移动网络是哪种类型,TelephonyManager提供了一个方法getNetworkClass(int networkType) ,但是该方法是一个隐藏的,不能显示调用,但是可以使用反射,具体反射如何调用就不细说了。下面看看getNetworkClass(int networkType)方法,
    public static int getNetworkClass(int networkType) {
        switch (networkType) {
            case NETWORK_TYPE_GPRS:
            case NETWORK_TYPE_GSM:
            case NETWORK_TYPE_EDGE:
            case NETWORK_TYPE_CDMA:
            case NETWORK_TYPE_1xRTT:
            case NETWORK_TYPE_IDEN:
                return NETWORK_CLASS_2_G;
            case NETWORK_TYPE_UMTS:
            case NETWORK_TYPE_EVDO_0:
            case NETWORK_TYPE_EVDO_A:
            case NETWORK_TYPE_HSDPA:
            case NETWORK_TYPE_HSUPA:
            case NETWORK_TYPE_HSPA:
            case NETWORK_TYPE_EVDO_B:
            case NETWORK_TYPE_EHRPD:
            case NETWORK_TYPE_HSPAP:
                return NETWORK_CLASS_3_G;
            case NETWORK_TYPE_LTE:
                return NETWORK_CLASS_4_G;
            default:
                return NETWORK_CLASS_UNKNOWN;
        }
    }
该方法提供的移动网络类型有16种(其中有一种是隐藏类型-NETWORK_TYPE_GSM,并且笔者的Api版本是21(5.0.1))。至于该方法为何是隐藏的,笔者认为,该方法还不稳定,Api版本会持续更新。
下面是笔者使用反射获调用该方法的实例,
	  public void getNetworkClass(int networkType){
		  Class c;
		 
			try {
				c = Class.forName("android.telephony.TelephonyManager");
				  Method m = c.getMethod("getNetworkClass", new Class[] {int.class});
				  Object o = m.invoke(null, new Object[]{networkType});
				  Log.e(TAG, o.toString());
			} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
	  }
其中,参数int networkType值为NetworkInfo.getSubtype()。下面是运行后,手机切换移动网络后的log截图,



至此,本篇文章就介绍完了!本篇文章只是大概描述了Android 有关网络方面的信息,比较简单,这只是一个开始,后期会继续推出相关的博文。由于笔者水平有限,如有错误,欢迎指出!




猜你喜欢

转载自blog.csdn.net/zxw136511485/article/details/72956055
今日推荐