最近在做mobile data on/off的功能,可能我说mobile data大家没什么概念,但是我如果说wifi on/off大家一定知道,而且也晓得如何去实现,mobile data其实就是我们不用wifi的时候,用自己手机里的SIM卡上网流量,即那个数据交换的开关。
这部分对我来说其实也是陌生的地方,不过通过上网查资料,也逐渐了解了一些,下面跟大伙分享一下:
实现这个功能,我们需要根据Android系统的版本将其分成两个阶段,分别实现。
在2.3版本以下,我们需要用所谓的Java反射机制去实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public
void
switchMobileData(
boolean
on)
throws
Exception{
try
{
Method dataConnSwitchMethod;
Class telephonyManagerClass;
Object ITelephonyStub;
Class ITelephonyClass;
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
switch
(telephonyManager.getDataState()){
case
TelephonyManager.DATA_CONNECTED:
System.out.println(
"DATA_CONNECTED"
);
break
;
case
TelephonyManager.DATA_DISCONNECTED:
System.out.println(
"DATA_DISCONNECTED"
);
break
;
}
telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());
Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod(
"getITelephony"
);
getITelephonyMethod.setAccessible(
true
);
ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);
ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());
if
(on){
System.out.println(
"on is true"
);
dataConnSwitchMethod = ITelephonyClass.getDeclaredMethod(
"enableDataConnectivity"
);
}
else
{
System.out.println(
"on is false"
);
dataConnSwitchMethod = ITelephonyClass.getDeclaredMethod(
"disableDataConnectivity"
);
}
dataConnSwitchMethod.setAccessible(
true
);
dataConnSwitchMethod.invoke(ITelephonyStub);
}
catch
(Exception e) {
// TODO: handle exception
Log.e(
"Error"
, e.toString());
}
}
|
使用时直接调用上面的函数,参数列表true/false分别代表开/关。不过2.3版本以下此功能有一个限制,就是必须在手动将数据交换图标点亮后,才能去控制mobile data的on/off,而且,就是在off之后,数据交换图标还是亮着的状态,不过这个时候上不了网罢了,但是如果你不亮开数据交换图标,再怎么调用也还是没有用的。
在2.3版本及以上的Android系统中,可以使用 IConnectivityManager.setMobileDataEnabled() 这是个隐藏的方法,就是直接控制手机 'Settings -> Wireless & network -> Mobile network settings -> Data Enabled' 这个操作路径下的方法,也就是我想控制的mobile data
1
2
3
4
5
6
7
8
9
10
11
|
public
static
void
setMobileDataEnabled(Context context,
boolean
enabled){
final
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
Class cmClass = Class.forName(cm.getClass().getName());
final
Field iConnectivityManagerField = cmClass.getDeclaredField(
"mService"
);
iConnectivityManagerField.setAccessible(
true
);
final
Object iConnectivityManager = iConnectivityManagerField.get(cm);
final
Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
final
Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod(
"setMobileDataEnabled"
, Boolean.TYPE );
setMobileDataEnabledMethod.setAccessible(
true
);
setMobileDataEnabledMethod.invoke(iConnectivityManager, enabled);
}
|
使用时也是直接调用就可以,context传入的是当前activity的对象,enabled传入true/false,控制开关。
以上两个方法就是针对 mobile data on/off的实现,大家不要忘记需要在AndroidManifest.xml中加入
1
2
|
<
uses-permission
android:name
=
"android.permission.MODIFY_PHONE_STATE"
>
</
uses-permission
>
|
此权限。
说到这就顺便把如何查看当前设备的网络连接跟大伙说一下,因为通常这些都是配套使用的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
//检查当前的网络状态
public
static
void
checkNetworkState(Menu menu, Context context){
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiinfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mobileinfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if
(wifiinfo !=
null
&& wifiinfo.isAvailable())
{
//如果wifi已经打开
if
(wifiinfo.isConnected())
{
//wifi已经连接上
}
else
{
//wifi可用,但是没有进行连接
}
}
else
{
//如果wifi为关闭状态
}
if
(mobileinfo !=
null
&& mobileinfo.isAvailable())
{
//移动数据连接 可用
if
(mobileinfo.isConnected())
{
//移动数据已经连接
}
else
{
//移动数据未连接
}
}
else
{
//说明该设备并没有移动数据连接功能
}
}
|
上面的方法是判断wifi连接还是正常的移动数据连接
还有一种方法就是比较全的,可以把所有的与当前设备连接或可以使用的网络显示出来
1
2
3
4
5
6
7
8
9
10
|
public
void
showNetworkAvailable(){
ConnectivityManager cm = (ConnectivityManager)MainActivity.
this
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] nwInfos = cm.getAllNetworkInfo();
for
(NetworkInfo nwInfo : nwInfos){
System.out.println(
"network type name="
+nwInfo.getTypeName());
System.out.println(
"network available="
+nwInfo.isAvailable());
System.out.println(
"network c_or-c="
+nwInfo.isConnectedOrConnecting());
System.out.println(
"network connected="
+nwInfo.isConnected());
}
}
|
以上资料大部分是从国外的StackOverflow上了解到的,而且我也均真正测试过,是好用的。