问题描述
- android 如何实现移动数据上网的开关?
-
android 如何实现移动数据上网的开关?之前百度了一下,找到几篇,但都说不行,今天再搜索,想试一试,竟都不见了!特来此求肋。谢谢
解决方案
感谢名位的回答,虽然没有用到,但也是学到了些东西的。本人已经找到了解决办法,也在此分享吧:
解决办法中使用到了ConnectivityManager类,但是在SDK中的ConnectivityManager类并没有提供setMobileDataEnable()、getMobileDataEnable()等方法。也看了ConnectivityManager类的源码,里面都是有这些方法的。弄了大半天,最终狠下心来,自己写个ConnectivityManager类,其中的方法和源ConnectivityManager类的方法一样,但都是空实现,编译成ConnectivityManager.class文件,然后替换android.jar包中的android.net.ConnectivityManager.class文件。然后在项目中,使用ConnectivityManager的setMobileDataEnable()方法来打开和关闭数据上网,使用getMobileDataEnable()方法获得当前连接状态,当然这需要android.permission.CHANGE_NETWORK_STATE和android.permission.ACCESS_NETWORK_STATE权限。
ConnectivityManager类如下:
package android.net;
import java.net.InetAddress;
public class ConnectivityManager
{
public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
public static final String CONNECTIVITY_ACTION_IMMEDIATE = "android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE";
public static final String EXTRA_NETWORK_INFO = "networkInfo";
public static final String EXTRA_IS_FAILOVER = "isFailover";
public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity";
public static final String EXTRA_REASON = "reason";
public static final String EXTRA_EXTRA_INFO = "extraInfo";
public static final String EXTRA_INET_CONDITION = "inetCondition";
public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
public static final String INET_CONDITION_ACTION = "android.net.conn.INET_CONDITION_ACTION";
public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
public static final String EXTRA_ACTIVE_TETHER = "activeArray";
public static final String EXTRA_ERRORED_TETHER = "erroredArray";
public static final int TYPE_NONE = -1;
public static final int TYPE_MOBILE = 0;
public static final int TYPE_WIFI = 1;
public static final int TYPE_MOBILE_MMS = 2;
public static final int TYPE_MOBILE_SUPL = 3;
public static final int TYPE_MOBILE_DUN = 4;
public static final int TYPE_MOBILE_HIPRI = 5;
public static final int TYPE_WIMAX = 6;
public static final int TYPE_BLUETOOTH = 7;
public static final int TYPE_DUMMY = 8;
public static final int TYPE_ETHERNET = 9;
public static final int TYPE_MOBILE_FOTA = 10;
public static final int TYPE_MOBILE_IMS = 11;
public static final int TYPE_MOBILE_CBS = 12;
public static final int TYPE_WIFI_P2P = 13;
public static final int MAX_RADIO_TYPE = TYPE_WIFI_P2P;
public static final int MAX_NETWORK_TYPE = TYPE_WIFI_P2P;
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
public static boolean isNetworkTypeValid(int networkType)
{
return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
}
/** {@hide} */
public static String getNetworkTypeName(int type)
{
return Integer.toString(type);
}
/** {@hide} */
public static boolean isNetworkTypeMobile(int networkType)
{
return false;
}
public void setNetworkPreference(int preference)
{
}
public int getNetworkPreference()
{
return 0;
}
class NetworkInfo
{
}
public NetworkInfo getActiveNetworkInfo()
{
return null;
}
/** {@hide} */
public NetworkInfo getActiveNetworkInfoForUid(int uid)
{
return null;
}
public NetworkInfo getNetworkInfo(int networkType)
{
return null;
}
public NetworkInfo[] getAllNetworkInfo()
{
return null;
}
/** {@hide} */
public LinkProperties getActiveLinkProperties()
{
return null;
}
/** {@hide} */
public LinkProperties getLinkProperties(int networkType)
{
return null;
}
/** {@hide} */
public boolean setRadios(boolean turnOn)
{
return turnOn;
}
/** {@hide} */
public boolean setRadio(int networkType, boolean turnOn)
{
return turnOn;
}
public int startUsingNetworkFeature(int networkType, String feature)
{
return networkType;
}
public int stopUsingNetworkFeature(int networkType, String feature)
{
return networkType;
}
public boolean requestRouteToHost(int networkType, int hostAddress)
{
return false;
}
public boolean requestRouteToHostAddress(int networkType,
InetAddress hostAddress)
{
return false;
}
@Deprecated
public boolean getBackgroundDataSetting()
{
return true;
}
@Deprecated
public void setBackgroundDataSetting(boolean allowBackgroundData)
{
}
public NetworkQuotaInfo getActiveNetworkQuotaInfo()
{
return null;
}
public boolean getMobileDataEnabled()
{
return false;
}
public void setMobileDataEnabled(boolean enabled)
{
}
class Context
{
}
public static ConnectivityManager from(Context context)
{
return new ConnectivityManager();
}
public String[] getTetherableIfaces()
{
return null;
}
public String[] getTetheredIfaces()
{
return null;
}
public String[] getTetheringErroredIfaces()
{
return null;
}
public int tether(String iface)
{
return 0;
}
public int untether(String iface)
{
return 0;
}
public boolean isTetheringSupported()
{
return false;
}
public String[] getTetherableUsbRegexs()
{
return null;
}
public String[] getTetherableWifiRegexs()
{
return null;
}
public String[] getTetherableBluetoothRegexs()
{
return null;
}
public int setUsbTethering(boolean enable)
{
return 0;
}
/** {@hide} */
public static final int TETHER_ERROR_NO_ERROR = 0;
/** {@hide} */
public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
/** {@hide} */
public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
/** {@hide} */
public static final int TETHER_ERROR_UNSUPPORTED = 3;
/** {@hide} */
public static final int TETHER_ERROR_UNAVAIL_IFACE = 4;
/** {@hide} */
public static final int TETHER_ERROR_MASTER_ERROR = 5;
/** {@hide} */
public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
/** {@hide} */
public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
/** {@hide} */
public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8;
/** {@hide} */
public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9;
/** {@hide} */
public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
public int getLastTetherError(String iface)
{
return 0;
}
public boolean requestNetworkTransitionWakelock(String forWhom)
{
return false;
}
public void reportInetCondition(int networkType, int percentage)
{
}
class PointerProperties
{
}
public void setGlobalProxy(PointerProperties p)
{
}
public PointerProperties getGlobalProxy()
{
return null;
}
public PointerProperties getProxy()
{
return null;
}
public void setDataDependency(int networkType, boolean met)
{
}
public boolean isNetworkSupported(int networkType)
{
return false;
}
public boolean isActiveNetworkMetered()
{
return false;
}
}
解决方案二:
1、调用隐藏的方法可以在源代码中进行编译
2、利用反射
希望下面文章对你有帮助
http://blog.csdn.net/tibib/article/details/8469871
解决方案三:
用我这个方法绝对好使,适用于任何手机。不需要放到系统里编译,也不需要导入jar包。
public void setMobileDataStatus(Context context, boolean enabled)
{
ConnectivityManager conMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
// ConnectivityManager类
Class<?> conMgrClass = null;
// ConnectivityManager类中的字段
Field iConMgrField = null;
// IConnectivityManager类的引用
Object iConMgr = null;
// IConnectivityManager类
Class<?> iConMgrClass = null;
// setMobileDataEnabled方法
Method setMobileDataEnabledMethod = null;
try {
// 取得ConnectivityManager类
conMgrClass = Class.forName(conMgr.getClass().getName());
// 取得ConnectivityManager类中的对象Mservice
iConMgrField = conMgrClass.getDeclaredField("mService");
// 设置mService可访问
iConMgrField.setAccessible(true);
// 取得mService的实例化类IConnectivityManager
iConMgr = iConMgrField.get(conMgr);
// 取得IConnectivityManager类
iConMgrClass = Class.forName(iConMgr.getClass().getName());
// 取得IConnectivityManager类中的setMobileDataEnabled(boolean)方法
setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod(
"setMobileDataEnabled", Boolean.TYPE);
// 设置setMobileDataEnabled方法是否可访问
setMobileDataEnabledMethod.setAccessible(true);
// 调用setMobileDataEnabled方法
setMobileDataEnabledMethod.invoke(iConMgr, enabled);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
解决方案四:
设置-》流量使用情况
我的是在这里能够开关
不过我不知道各个手机的情况一样不,我的系统是android4.1.1
不知道楼主是想用代码实现还是手机功能?我是按照手机功能回答的
解决方案五:
这个是一种方法,但是对有些手机可能无法实现,我的可以,你可以试一下
Java code
@SuppressWarnings("unchecked")
public void openDataConnect() throws ClassNotFoundException,
SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Method dataConnSwitchmethod;
Class telephonyManagerClass;
Object ITelephonyStub;
Class ITelephonyClass;
boolean isEnabled = false;
TelephonyManager telephonyManager = (TelephonyManager) context.get()
.getSystemService(Context.TELEPHONY_SERVICE);
//获取当前的状态
if(telephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED){
isEnabled = true;
}else{
isEnabled = false;
}
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 (isEnabled) {
dataConnSwitchmethod = ITelephonyClass
.getDeclaredMethod("disableDataConnectivity");
} else {
dataConnSwitchmethod = ITelephonyClass
.getDeclaredMethod("enableDataConnectivity");
}
dataConnSwitchmethod.setAccessible(true);
dataConnSwitchmethod.invoke(ITelephonyStub);
}
解决方案六:
android APN的打开与关闭
由于Android对于APN的网络API没有公开,不过我们可以阅读源代码,然后进行数
据库操作,系统会自动监听数据库的变化,从而实现开启或者关闭APN。
大家可以研究一下frameworks/base/core/java/android/provider
/Telephony.java这个类,
比较重要的就是 URI 和数据库字段: content://telephony/carriers
字段可以在Telephony.java中找到。
其实原理很简单 :
1 、 当开启APN的时候,设置一个正确的移动或者联通的APN
2、 关闭的时候设置一个错误APN就会自动关闭网络
看代码:Activity:
Java代码
package cc.mdev.apn;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class Main extends Activity {
Uri uri = Uri.parse("content://telephony/carriers");
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button open= (Button) findViewById(R.id.open);
Button close= (Button) findViewById(R.id.close);
open.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openAPN();
}
});
close.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
closeAPN();
}
});
}
public void openAPN(){
List<APN> list = getAPNList();
for (APN apn : list) {
ContentValues cv = new ContentValues();
cv.put("apn", APNMatchTools.matchAPN(apn.apn));
cv.put("type", APNMatchTools.matchAPN(apn.type));
getContentResolver().update(uri, cv, "_id=?", new String[]{apn.id});
}
}
public void closeAPN(){
List<APN> list = getAPNList();
for (APN apn : list) {
ContentValues cv = new ContentValues();
cv.put("apn", APNMatchTools.matchAPN(apn.apn)+"mdev");
cv.put("type", APNMatchTools.matchAPN(apn.type)+"mdev");
getContentResolver().update(uri, cv, "_id=?", new String[]{apn.id});
}
}
private List<APN> getAPNList(){
String tag = "Main.getAPNList()";
//current不为空表示可以使用的APN
String projection[] = {"_id,apn,type,current"};
Cursor cr = this.getContentResolver().query(uri, projection, null, null, null);
List<APN> list = new ArrayList<APN>();
while(cr!=null && cr.moveToNext()){
Log.d(tag, cr.getString(cr.getColumnIndex("_id")) + " " + cr.getString(cr.getColumnIndex("apn")) + " " + cr.getString(cr.getColumnIndex("type"))+ " " + cr.getString(cr.getColumnIndex("current")));
APN a = new APN();
a.id = cr.getString(cr.getColumnIndex("_id"));
a.apn = cr.getString(cr.getColumnIndex("apn"));
a.type = cr.getString(cr.getColumnIndex("type"));
list.add(a);
}
if(cr!=null)
cr.close();
return list;
}
public static class APN{
String id;
String apn;
String type;
}
}
APNMatchTools.java
Java代码
package cc.mdev.apn;
public final class APNMatchTools {
public static class APNNet{
public static String CMWAP = "cmwap";
public static String CMNET = "cmnet";
//中国联通3GWAP设置 中国联通3G因特网设置 中国联通WAP设置 中国联通因特网设置
//3gwap 3gnet uniwap uninet
public static String GWAP_3 = "3gwap";
public static String GNET_3="3gnet";
public static String UNIWAP="uniwap";
public static String UNINET="uninet";
}
public static String matchAPN(String currentName) {
if("".equals(currentName) || null==currentName){
return "";
}
currentName = currentName.toLowerCase();
if(currentName.startsWith(APNNet.CMNET))
return APNNet.CMNET;
else if(currentName.startsWith(APNNet.CMWAP))
return APNNet.CMWAP;
else if(currentName.startsWith(APNNet.GNET_3))
return APNNet.GNET_3;
else if(currentName.startsWith(APNNet.GWAP_3))
return APNNet.GWAP_3;
else if(currentName.startsWith(APNNet.UNINET))
return APNNet.UNINET;
else if(currentName.startsWith(APNNet.UNIWAP))
return APNNet.UNIWAP;
else if(currentName.startsWith("default"))
return "default";
else return "";
// return currentName.substring(0, currentName.length() - SUFFIX.length());
}
}
最后不要忘记加上修改APN的权限:
Xml代码
1. <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS"></uses-permission>
经过测试在G1 上联通和移动卡均是成功的。
解决方案七:
在frameworksbasepackagesSystemUIsrccomandroidsystemuistatusbartabletSettingsView.java
路径下
public class SettingsView extends LinearLayout implements View.OnClickListener{
//增加数据广播实例声明
DataEnabledController mDataEnabled;
...
//在该方法下增加~
protected void onFinishInflate() {
...
mDataEnabled = new DataEnabledController(context,
(CompoundButton)findViewById(R.id.dataEnable_checkbox));
}
}
再在SystemUIres下相应的xml布局文件内加入
<LinearLayout
android:id="@+id/dataEnable"
style="@style/StatusBarPanelSettingsRow"
>
<ImageView
android:id="@+id/dataEnable_icon"
style="@style/StatusBarPanelSettingsIcon"
android:src="@drawable/ic_sysbar_data_switcher"
/>
<TextView
android:id="@+id/dataEnable_label"
style="@style/StatusBarPanelSettingsContents"
android:text="@string/status_bar_settings_data_enabled"
/>
<Switch
android:id="@+id/dataEnable_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="5dp"
/>
</LinearLayout>
<View style="@style/StatusBarPanelSettingsPanelSeparator" />
最后在SystemUIres下加入相应资源图片和字符串即可~ 希望对你有所帮助~
解决方案八:
4.0 以后的 Android 不在提供普通应用程序对 APN(Access Point Name) 修改的权限,如果强制修改的话,会报安全异常直接挂掉的。除非有当前设备系统应用的签名,然后打包进你修改 APN 的应用里面。
2.x 的系统可以尝试一下以下代码,
public static boolean setNETMode()
{
ContentResolver resolver = context.getContentResolver();
Cursor cursor =
resolver.query(Uri.parse("content://telephony/carriers"),
new String[] { "_id" }, "apn like '%net' and current=1", null,
null);
if ((cursor != null) && (cursor.moveToNext()))
{
ContentValues values = new ContentValues();
values.put("apn_id", cursor.getString(0));
resolver.update(
Uri.parse("content://telephony/carriers/preferapn"), values,
null, null);
return true;
}
return false;
}
解决方案九:
一般的移动网络开关都是通过篡改APN实现的(真正的开关没有直接对外的api):
如接入点名称类型一般是default,当关闭的时候修改为其他的值,打开时候修改为default.
解决方案十:
是哇,可以用反射来实现吧?