開啟和關閉移動數據網絡有兩種方法:一種是通過操作系統的數據庫改變APN(網絡接入點),從而實現開啟和關閉移動數據網絡,另一種是通過反射調用系統(ConnectivityManager)的setMoblieDataEnabled方法,通過操作該方法開啟和關閉系統移動數據,同時也可以通過反射調用getMoblieDataEnabled方法獲取當前的開啟和關閉狀態。
第一種方式:
通過APN的方式開啟和關閉很威猛啊,為什么這么說呢,廢話不多說,先看代碼:
1. 匹配類:
- //創建一個匹配類,用於匹配移動、電信、聯通的APN
- public final class APNMatchTools
- {
- // 中國移動cmwap
- public static String CMWAP = "cmwap";
- // 中國移動cmnet
- public static String CMNET = "cmnet";
- // 中國聯通3gwap APN
- public static String GWAP_3 = "3gwap";
- // 中國聯通3gnet APN
- public static String GNET_3 = "3gnet";
- // 中國聯通uni wap APN
- public static String UNIWAP = "uniwap";
- // 中國聯通uni net APN
- public static String UNINET = "uninet";
- // 中國電信 ct wap APN
- public static String CTWAP = "ctwap";
- // 中國電信ct net APN
- public static String CTNET = "ctnet";
- public static String matchAPN(String currentName)
- {
- if ("".equals(currentName) || null == currentName)
- {
- return "";
- }
- // 參數轉為小寫
- currentName = currentName.toLowerCase();
- // 檢查參數是否與各APN匹配,返回匹配值
- if (currentName.startsWith(CMNET))
- return CMNET;
- else if (currentName.startsWith(CMWAP))
- return CMWAP;
- else if (currentName.startsWith(GNET_3))
- return GNET_3;
- else if (currentName.startsWith(GWAP_3))
- return GWAP_3;
- else if (currentName.startsWith(UNINET))
- return UNINET;
- else if (currentName.startsWith(UNIWAP))
- return UNIWAP;
- else if (currentName.startsWith(CTWAP))
- return CTWAP;
- else if (currentName.startsWith(CTNET))
- return CTNET;
- else if (currentName.startsWith("default"))
- return "default";
- else
- return "";
- }
- }
2. 開啟和關閉APN的方法在ApnSwitchTest類中實現,如下:
- 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.util.Log;
- public class ApnSwitchTest extends Activity
- {
- Uri uri = Uri.parse("content://telephony/carriers/preferapn");
- // 開啟APN
- public void openAPN()
- {
- List<APN> list = getAPNList();
- for (APN apn : list)
- {
- ContentValues cv = new ContentValues();
- // 獲取及保存移動或聯通手機卡的APN網絡匹配
- cv.put("apn", APNMatchTools.matchAPN(apn.apn));
- cv.put("type", APNMatchTools.matchAPN(apn.type));
- // 更新系統數據庫,改變移動網絡狀態
- getContentResolver().update(uri, cv, "_id=?", new String[]
- {
- apn.id
- });
- }
- }
- // 關閉APN
- public void closeAPN()
- {
- List<APN> list = getAPNList();
- for (APN apn : list)
- {
- // 創建ContentValues保存數據
- ContentValues cv = new ContentValues();
- // 添加"close"匹配一個錯誤的APN,關閉網絡
- cv.put("apn", APNMatchTools.matchAPN(apn.apn) + "close");
- cv.put("type", APNMatchTools.matchAPN(apn.type) + "close");
- // 更新系統數據庫,改變移動網絡狀態
- getContentResolver().update(uri, cv, "_id=?", new String[]
- {
- apn.id
- });
- }
- }
- public static class APN
- {
- String id;
- String apn;
- String type;
- }
- private List<APN> getAPNList()
- {
- // current不為空表示可以使用的APN
- String projection[] =
- {
- "_id, apn, type, current"
- };
- // 查詢獲取系統數據庫的內容
- Cursor cr = getContentResolver().query(uri, projection, null, null, null);
- // 創建一個List集合
- List<APN> list = new ArrayList<APN>();
- while (cr != null && cr.moveToNext())
- {
- Log.d("ApnSwitch", "id" + cr.getString(cr.getColumnIndex("_id")) + " \n" + "apn"
- + cr.getString(cr.getColumnIndex("apn")) + "\n" + "type"
- + cr.getString(cr.getColumnIndex("type")) + "\n" + "current"
- + 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;
- }
- }<span style="font-family: 'Comic Sans MS'; "> </span>
最后,別忘了在AndroidManifext.xml文件中添加訪問權限<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
親們,從上面的代碼中看出什么來了么,沒錯,通過APN的方式就是修改數據庫,關閉APN其實就是給它隨便匹配一個錯誤的APN。為什么說這種方法很生猛呢,當你通過這個方式關閉APN后,你在通過手機上的快捷開關開啟移動數據網絡時,是沒效果的,也就是說開啟不了,除非你再用同樣的方法開啟APN。
第二種方式:
這就奇怪了,關閉APN后,為什么再通過手機上的快捷開關(AppWidget)開啟不了呢,這個問題就值得思考了,說明快捷開關其實並不是通過這個方式來開啟和關閉移動網絡的。道理很簡單,想想那些快捷開關是怎么樣根據開啟和關閉移動網絡,然后更換亮和暗的圖標的呢(更新UI)。這里肯定會涉及到一個獲取系統當前開啟和關閉移動數據狀態的問題。那到底是怎樣獲取的,是通過什么樣的形式的?其實道理很簡單,就是通過調用系統的getMobileDataState和setMobileData(我是這么知道它是調用到這個方法的呢?親們,如果你有android手機,把它插到電腦上,然后開啟已經搭建好的android開發環境的eclpise,打開logcat面板,相應地在你手機的快捷開關上開啟和關閉移動網絡,然后看看在logcat面板上出現什么了)。
既然知道是調用上面這兩個方法了,我們是不是就可以直接調用這個兩個方法實現了?NO,沒這么簡單,這個兩個方法不能直接調用,必須通過反射機制調用(呵呵,沒接觸過java有關反射的知識的,或者是忘了的,可以去學習和溫習一下)。
- /**
- * 設置手機的移動數據
- */
- public static void setMobileData(Context pContext, boolean pBoolean) {
- try {
- ConnectivityManager mConnectivityManager = (ConnectivityManager) pContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- Class ownerClass = mConnectivityManager.getClass();
- Class[] argsClass = new Class[1];
- argsClass[0] = boolean.class;
- Method method = ownerClass.getMethod("setMobileDataEnabled", argsClass);
- method.invoke(mConnectivityManager, pBoolean);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- System.out.println("移動數據設置錯誤: " + e.toString());
- }
- }
- /**
- * 返回手機移動數據的狀態
- *
- * @param pContext
- * @param arg
- * 默認填null
- * @return true 連接 false 未連接
- */
- public static boolean getMobileDataState(Context pContext, Object[] arg) {
- try {
- ConnectivityManager mConnectivityManager = (ConnectivityManager) pContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- Class ownerClass = mConnectivityManager.getClass();
- Class[] argsClass = null;
- if (arg != null) {
- argsClass = new Class[1];
- argsClass[0] = arg.getClass();
- }
- Method method = ownerClass.getMethod("getMobileDataEnabled", argsClass);
- Boolean isOpen = (Boolean) method.invoke(mConnectivityManager, arg);
- return isOpen;
- } catch (Exception e) {
- // TODO: handle exception
- System.out.println("得到移動數據狀態出錯");
- return false;
- }
- }</span>
最后,別忘了在AndroidMannifest.xml文件里添加訪問權限 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />,
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
通過上面的代碼可以知道,當開啟移動網絡時調用:
setMobileData(context,true),關閉調用setMobileData(context,false),通過getMobileDataStatus(context)方法返回的布爾值判斷當移動數據網絡前狀態的開啟和關閉。
轉自:http://blog.csdn.net/fangzhibin4712/article/details/26563285