實現開啓和關閉android移動網絡

http://blog.csdn.net/fangzhibin4712/article/details/26563285

開啓和關閉移動數據網絡有兩種方法:一種是通過操作系統的數據庫改變APN(網絡接入點),從而實現開啓和關閉移動數據網絡,另一種是通過反射調用系統(ConnectivityManager)的setMoblieDataEnabled方法,通過操作該方法開啓和關閉系統移動數據,同時也可以通過反射調用getMoblieDataEnabled方法獲取當前的開啓和關閉狀態。

 

第一種方式:

   通過APN的方式開啓和關閉很威猛啊,爲什麼這麼說呢,廢話不多說,先看代碼:

   1. 匹配類:

 

[java] view plaincopy
  1. //創建一個匹配類,用於匹配移動、電信、聯通的APN  
  2. public final class APNMatchTools  
  3. {  
  4.   
  5.     // 中國移動cmwap  
  6.     public static String CMWAP = "cmwap";  
  7.   
  8.     // 中國移動cmnet  
  9.     public static String CMNET = "cmnet";  
  10.   
  11.     // 中國聯通3gwap APN  
  12.   
  13.     public static String GWAP_3 = "3gwap";  
  14.   
  15.     // 中國聯通3gnet APN  
  16.     public static String GNET_3 = "3gnet";  
  17.   
  18.     // 中國聯通uni wap APN  
  19.     public static String UNIWAP = "uniwap";  
  20.   
  21.     // 中國聯通uni net APN  
  22.     public static String UNINET = "uninet";  
  23.   
  24.     // 中國電信 ct wap APN  
  25.     public static String CTWAP = "ctwap";  
  26.   
  27.     // 中國電信ct net APN  
  28.     public static String CTNET = "ctnet";  
  29.   
  30.     public static String matchAPN(String currentName)  
  31.     {  
  32.   
  33.         if ("".equals(currentName) || null == currentName)  
  34.         {  
  35.   
  36.             return "";  
  37.         }  
  38.   
  39.         // 參數轉爲小寫  
  40.         currentName = currentName.toLowerCase();  
  41.         // 檢查參數是否與各APN匹配,返回匹配值  
  42.         if (currentName.startsWith(CMNET))  
  43.             return CMNET;  
  44.         else if (currentName.startsWith(CMWAP))  
  45.             return CMWAP;  
  46.         else if (currentName.startsWith(GNET_3))  
  47.             return GNET_3;  
  48.   
  49.         else if (currentName.startsWith(GWAP_3))  
  50.             return GWAP_3;  
  51.         else if (currentName.startsWith(UNINET))  
  52.             return UNINET;  
  53.   
  54.         else if (currentName.startsWith(UNIWAP))  
  55.             return UNIWAP;  
  56.         else if (currentName.startsWith(CTWAP))  
  57.             return CTWAP;  
  58.         else if (currentName.startsWith(CTNET))  
  59.             return CTNET;  
  60.         else if (currentName.startsWith("default"))  
  61.             return "default";  
  62.         else  
  63.             return "";  
  64.     }  
  65.   
  66. }  

2. 開啓和關閉APN的方法在ApnSwitchTest類中實現,如下:

[java] view plaincopy
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3.   
  4. import android.app.Activity;  
  5. import android.content.ContentValues;  
  6. import android.database.Cursor;  
  7. import android.net.Uri;  
  8. import android.util.Log;  
  9.   
  10. public class ApnSwitchTest extends Activity  
  11. {  
  12.   
  13.     Uri uri = Uri.parse("content://telephony/carriers/preferapn");  
  14.     
  15.     // 開啓APN  
  16.     public void openAPN()  
  17.     {  
  18.         List<APN> list = getAPNList();  
  19.         for (APN apn : list)  
  20.         {  
  21.             ContentValues cv = new ContentValues();  
  22.   
  23.             // 獲取及保存移動或聯通手機卡的APN網絡匹配  
  24.             cv.put("apn", APNMatchTools.matchAPN(apn.apn));  
  25.             cv.put("type", APNMatchTools.matchAPN(apn.type));  
  26.   
  27.             // 更新系統數據庫,改變移動網絡狀態  
  28.             getContentResolver().update(uri, cv, "_id=?"new String[]  
  29.             {  
  30.                 apn.id  
  31.             });  
  32.         }  
  33.   
  34.     }  
  35.   
  36.     // 關閉APN  
  37.     public void closeAPN()  
  38.     {  
  39.         List<APN> list = getAPNList();  
  40.         for (APN apn : list)  
  41.         {  
  42.             // 創建ContentValues保存數據  
  43.             ContentValues cv = new ContentValues();  
  44.             // 添加"close"匹配一個錯誤的APN,關閉網絡  
  45.             cv.put("apn", APNMatchTools.matchAPN(apn.apn) + "close");  
  46.             cv.put("type", APNMatchTools.matchAPN(apn.type) + "close");  
  47.   
  48.             // 更新系統數據庫,改變移動網絡狀態  
  49.             getContentResolver().update(uri, cv, "_id=?"new String[]  
  50.             {  
  51.                 apn.id  
  52.             });  
  53.         }  
  54.     }  
  55.       
  56.     public static class APN  
  57.     {  
  58.         String id;  
  59.   
  60.         String apn;  
  61.   
  62.         String type;  
  63.     }  
  64.   
  65.     private List<APN> getAPNList()  
  66.     {  
  67.         // current不爲空表示可以使用的APN  
  68.         String projection[] =  
  69.         {  
  70.             "_id, apn, type, current"  
  71.         };  
  72.         // 查詢獲取系統數據庫的內容  
  73.         Cursor cr = getContentResolver().query(uri, projection, nullnullnull);  
  74.   
  75.         // 創建一個List集合  
  76.         List<APN> list = new ArrayList<APN>();  
  77.   
  78.         while (cr != null && cr.moveToNext())  
  79.         {  
  80.   
  81.             Log.d("ApnSwitch""id" + cr.getString(cr.getColumnIndex("_id")) + " \n" + "apn"  
  82.                     + cr.getString(cr.getColumnIndex("apn")) + "\n" + "type"  
  83.                     + cr.getString(cr.getColumnIndex("type")) + "\n" + "current"  
  84.                     + cr.getString(cr.getColumnIndex("current")));  
  85.   
  86.             APN a = new APN();  
  87.   
  88.             a.id = cr.getString(cr.getColumnIndex("_id"));  
  89.             a.apn = cr.getString(cr.getColumnIndex("apn"));  
  90.             a.type = cr.getString(cr.getColumnIndex("type"));  
  91.             list.add(a);  
  92.         }  
  93.   
  94.         if (cr != null)  
  95.             cr.close();  
  96.   
  97.         return list;  
  98.     }  
  99.   
  100. }<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有關反射的知識的,或者是忘了的,可以去學習和溫習一下)。


[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.  * 設置手機的移動數據 
  3.  */  
  4. public static void setMobileData(Context pContext, boolean pBoolean) {  
  5.   
  6.     try {  
  7.   
  8.         ConnectivityManager mConnectivityManager = (ConnectivityManager) pContext.getSystemService(Context.CONNECTIVITY_SERVICE);  
  9.   
  10.         Class ownerClass = mConnectivityManager.getClass();  
  11.   
  12.         Class[] argsClass = new Class[1];  
  13.         argsClass[0] = boolean.class;  
  14.   
  15.         Method method = ownerClass.getMethod("setMobileDataEnabled", argsClass);  
  16.   
  17.         method.invoke(mConnectivityManager, pBoolean);  
  18.   
  19.     } catch (Exception e) {  
  20.         // TODO Auto-generated catch block  
  21.         e.printStackTrace();  
  22.         System.out.println("移動數據設置錯誤: " + e.toString());  
  23.     }  
  24. }  
  25.   
  26. /** 
  27.  * 返回手機移動數據的狀態 
  28.  * 
  29.  * @param pContext 
  30.  * @param arg 
  31.  *            默認填null 
  32.  * @return true 連接 false 未連接 
  33.  */  
  34. public static boolean getMobileDataState(Context pContext, Object[] arg) {  
  35.   
  36.     try {  
  37.   
  38.         ConnectivityManager mConnectivityManager = (ConnectivityManager) pContext.getSystemService(Context.CONNECTIVITY_SERVICE);  
  39.   
  40.         Class ownerClass = mConnectivityManager.getClass();  
  41.   
  42.         Class[] argsClass = null;  
  43.         if (arg != null) {  
  44.             argsClass = new Class[1];  
  45.             argsClass[0] = arg.getClass();  
  46.         }  
  47.   
  48.         Method method = ownerClass.getMethod("getMobileDataEnabled", argsClass);  
  49.   
  50.         Boolean isOpen = (Boolean) method.invoke(mConnectivityManager, arg);  
  51.   
  52.         return isOpen;  
  53.   
  54.     } catch (Exception e) {  
  55.         // TODO: handle exception  
  56.   
  57.         System.out.println("得到移動數據狀態出錯");  
  58.         return false;  
  59.     }  
  60.   
  61. }</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)方法返回的布爾值判斷當移動數據網絡前狀態的開啓和關閉。
發佈了15 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章