Android AppWidget控制手机上网APN接入点

来源:互联网 发布:光纤网络测速 编辑:程序博客网 时间:2024/06/06 07:52

首先很有必要讲一下需求,由于搞IT的加班比较多,每天回家基本上都是8点之后,电信网络又贵,无奈我屌丝一个用网时间又少,索性在淘宝上花重金购置了一张1元5小时的上网卡,貌似是广东电信的绝版卡,在广东省内上网5小时一分钱,但是接入点要是CTWAP,否则上网就是1小时3块钱了。用久了发现了一个弊端:网络不好的时候手机会自动切换APN接入点,刚开始的时候我是下载一个了HIAPN的软件,这个软件提供一个桌面插件,很方便看到当前APN接入点是什么。可惜好景不长,随着系统升级,这个软件停止了更新,只能在固件2.3的系统上使用。于是我就琢磨这自己来开发一个插件,而且最好在手机切换APN的时候能够有报警机制(震动)。

扯完了需求,马上就上干货了。

1.切换WIFI开关

如果开着WIFI就关掉,如果关掉就打开。这个是最简单的了,普通应用就OK

/** * 切换wifi开关 * @param context */public static void changeWifi(Context context) {WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);if (wifiManager.isWifiEnabled()) {wifiManager.setWifiEnabled(false);} else {wifiManager.setWifiEnabled(true);}}
对应权限

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

2.切换手机数据流量

2.1 获取手机流量数据开关

public static boolean getMobileDataState(Context cxt) {TelephonyManager telephonyService = (TelephonyManager) cxt.getSystemService(Context.TELEPHONY_SERVICE);try {Method getMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("getDataEnabled");if (null != getMobileDataEnabledMethod) {boolean mobileDataEnabled = (Boolean) getMobileDataEnabledMethod.invoke(telephonyService);return mobileDataEnabled;}} catch (Exception e) {Log.v(TAG,"Error getting"+ ((InvocationTargetException) e).getTargetException() + telephonyService);}return false;}

2.2 设置手机流量数据(android5.0以下)

 /**     * 当开启移动网络时调用setMobileDataStatus(context,true),     * 关闭调用setMobileDataStatus(context,false)     * 移动数据开启和关闭     * @param context     * @param enabled     */    public static 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(Exception e)      {    e.printStackTrace();      }    }

对应的权限

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>

2.3 设置手机流量数据开关(android5.0及以上)

public static void setMobileDataState(Context cxt, boolean mobileDataEnabled) {TelephonyManager telephonyService = (TelephonyManager) cxt.getSystemService(Context.TELEPHONY_SERVICE);try {Method setMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("setDataEnabled", boolean.class);if (null != setMobileDataEnabledMethod) {setMobileDataEnabledMethod.invoke(telephonyService,mobileDataEnabled);}} catch (Exception e) {Log.v(TAG,"Error setting"+ ((InvocationTargetException) e).getTargetException() + telephonyService);}}

对应的权限

<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>

注意:android5.0的这个隐藏接口的调用,把apk移动到system/priva-app 这个目录下面才能调用成功(我没有试验过,网上有网友说可行),或者你要是有手机的plaform签名,因为上面的权限只能赋予给系统应用,最好直接用系统权限打包后签名。这个接口的改动所以会导致我们用WIFI万能钥匙的时候如果你的手机是android5.0以上,能够直接打开WIFI但不能直接开启手机数据流量,而是提示你手动开启数据流量。


3.切换APN接入点


3.1获取当前APN接入点

       public static final Uri PRE_APN_URI = Uri.parse("content://telephony/carriers/preferapn");                                          // 获取当前APNpublic static String getCurApnName(Context context) {ContentResolver resoler = context.getContentResolver();// String[] projection = new String[] { "_id" };Cursor cur = resoler.query(PRE_APN_URI, projection, null, null, null);String apnName = "";// cur为空则表示默认情况下一个都没有选中if (cur != null && cur.moveToFirst()) {// apnId = cur.getString(cur.getColumnIndex("_id"));apnName = cur.getString(cur.getColumnIndex("apn"));}Log.i("xml", "getCurApnId:" + apnName);return apnName;}

3.2更新APN接入点

 // 所有的APN配配置信息位置  public static final Uri APN_LIST_URI = Uri.parse("content://telephony/carriers");                                                public static boolean updateCurrentAPN(ContentResolver resolver, String newAPN) {     boolean changeResult = false;        Cursor cursor = null;         try {             //get new apn id from list             cursor = resolver.query(APN_LIST_URI, null, " apn = ? and current = 1", new String[]{newAPN.toLowerCase()}, null);             String apnId = null;             if (cursor != null && cursor.moveToFirst()) {                 apnId = cursor.getString(cursor.getColumnIndex("_id"));             }             cursor.close();                         //set new apn id as chosen one             if (apnId != null) {                 ContentValues values = new ContentValues();                 values.put("apn_id", apnId);                 resolver.update(PRE_APN_URI, values, null, null);                 changeResult = true;            } else {                 //apn id not found, return 0.             }         } catch (Exception e) {         e.printStackTrace();        } finally {             if (cursor != null) {                 cursor.close();             }         }                 return changeResult; } }

需要的权限

 <!-- Permission is only granted to system apps -->    <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"/>

这个也是系统权限啊,由此可以看出实现的难度      切换WIFI<切换手机流量<切换APN   

本Demo代码已经上传GitHub,点击下载,注意切换手机流量和APN都要有系统权限,如果没有对应手机的platform签名,会无法安装。


0 0
原创粉丝点击