開啟和關閉android行動網路
第一種方式:
通過APN的方式開啟和關閉很威猛啊,為什麼這麼說呢,廢話不多說,先看程式碼:
1. 匹配類:
- //建立一個匹配類,用於匹配移動、電信、聯通的APN
-
publicfinalclass APNMatchTools
- {
- // 中國移動cmwap
- publicstatic String CMWAP = "cmwap";
- // 中國移動cmnet
- publicstatic String CMNET = "cmnet";
- // 中國聯通3gwap APN
- publicstatic String GWAP_3 = "3gwap";
- // 中國聯通3gnet APN
- publicstatic String GNET_3 = "3gnet";
- // 中國聯通uni wap APN
-
publicstatic String UNIWAP =
- // 中國聯通uni net APN
- publicstatic String UNINET = "uninet";
- // 中國電信 ct wap APN
- publicstatic String CTWAP = "ctwap";
- // 中國電信ct net APN
- publicstatic String CTNET = "ctnet";
- publicstatic String matchAPN(String currentName)
- {
-
if ("".equals(currentName) ||
- {
- return"";
- }
- // 引數轉為小寫
- currentName = currentName.toLowerCase();
- // 檢查引數是否與各APN匹配,返回匹配值
- if (currentName.startsWith(CMNET))
- return CMNET;
- elseif (currentName.startsWith(CMWAP))
- return CMWAP;
- elseif (currentName.startsWith(GNET_3))
- return GNET_3;
- elseif (currentName.startsWith(GWAP_3))
- return GWAP_3;
- elseif (currentName.startsWith(UNINET))
- return UNINET;
- elseif (currentName.startsWith(UNIWAP))
- return UNIWAP;
- elseif (currentName.startsWith(CTWAP))
- return CTWAP;
- elseif (currentName.startsWith(CTNET))
- return CTNET;
- elseif (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;
- publicclass ApnSwitchTest extends Activity
- {
- Uri uri = Uri.parse("content://telephony/carriers/preferapn");
- // 開啟APN
- publicvoid 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
- publicvoid 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
- });
- }
- }
- publicstaticclass 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有關反射的知識的,或者是忘了的,可以去學習和溫習一下)。
- /**
- * 設定手機的移動資料
- */
- publicstaticvoid