Android VPN编程
来源:互联网 发布:乐陵淘宝客服打包 编辑:程序博客网 时间:2024/04/30 09:46
前段时间开发App碰上一个特殊的需求,就是要用代码连接或者断开VPN。后来百度谷歌了一番都没有找到能够实现的方案。最后只能自己查看系统源码,将相关的API调用找出来,采用反射调用实现了代码连接或断开VPN。
首先声明,以下调用本人仅在4.4.2和4.4.3系统上测试可用,并且调用这些方法的App需要系统级权限。本人获取系统级权限的做法是下载第三方ROM,将ROM重新签名为自己的签名,然后使用这个签名为自己的App签名,这样App就能获取到系统权限了。第二点就是此调用只是连接某个已设置好的VPN链接(通过传入该VPN链接在VPN列表界面的位置),不具备配置VPN链接的功能。所以调用者需要先在手机上配置好VPN,保证服务器、账号及密码的正确性。
下面附上具体的代码,具体功能就不解释了,距离写这段调用时间已经过去挺久了,大都忘了。如果大家想知道可以查阅系统源码。
public class Helper { public static void resetVpn(final Context context) { disconnect(context);//调用连接前先断开已连接的VPN,保证顺利连接我们要连接的VPN //断开当前VPN连接到再次连接VPN之间需要时间间隔,否则会连接失败。 new Handler().postDelayed(new Runnable() { @Override public void run() { Object profile = getVpnProfile(); connect(context, profile); } }, 500); } public static Object getVpnProfile() { try { Class clsKeyStore = Class.forName("android.security.KeyStore"); Method methodGetInstance = clsKeyStore.getDeclaredMethod( "getInstance", null); methodGetInstance.setAccessible(true); Object objKeyStore = methodGetInstance.invoke(null, null); Method methodSaw = clsKeyStore.getDeclaredMethod("saw", String.class); methodSaw.setAccessible(true); String[] keys = (String[]) methodSaw.invoke(objKeyStore, "VPN_"); Class clsVpnProfile = Class .forName("com.android.internal.net.VpnProfile"); Method methodDecode = clsVpnProfile.getDeclaredMethod("decode", String.class, byte[].class); methodDecode.setAccessible(true); Method methodGet = clsKeyStore.getDeclaredMethod("get", String.class); methodGet.setAccessible(true); Object byteArrayValue = methodGet.invoke(objKeyStore, "VPN_" + keys[0]);//此处0表示连接VPN列表中的第一个VPN Object objVpnProfile = methodDecode.invoke(null, keys[0], byteArrayValue); return objVpnProfile; } catch (Exception e) { e.printStackTrace(); } return null; } public static Class getVpnProfileClass() { try { return Class.forName("com.android.internal.net.VpnProfile"); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } public static void connect(Context context, Object profile) { ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); Field fieldIConManager = null; try { fieldIConManager = cm.getClass().getDeclaredField("mService"); fieldIConManager.setAccessible(true); Object objIConManager = fieldIConManager.get(cm); Class clsIConManager = Class.forName(objIConManager.getClass() .getName()); Class clsVpnProfile = Class .forName("com.android.internal.net.VpnProfile"); Method metStartLegacyVpn = clsIConManager.getDeclaredMethod( "startLegacyVpn", clsVpnProfile); metStartLegacyVpn.setAccessible(true); metStartLegacyVpn.invoke(objIConManager, profile); } catch (Exception e) { e.printStackTrace(); } } private static void disconnect(Context context) { ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); Field fieldIConManager = null; try { fieldIConManager = cm.getClass().getDeclaredField("mService"); fieldIConManager.setAccessible(true); Object objIConManager = fieldIConManager.get(cm); Class clsIConManager = Class.forName(objIConManager.getClass() .getName()); Method metPrepare = clsIConManager.getDeclaredMethod("prepareVpn", String.class, String.class); metPrepare.invoke(objIConManager, "[Legacy VPN]", "[Legacy VPN]"); } catch (Exception e) { e.printStackTrace(); } }}
1 0
- Android VPN 编程
- android VPN编程
- Android VPN 编程
- Android VPN 编程
- Android VPN 编程
- Android VPN 编程
- Android VPN编程
- Android VPN 编程
- Android VPN编程
- android VPN
- android vpn pptp 自动切换VPN
- Android VPN设置
- Android VPN code
- Android Vpn 整理
- Android VPN source code
- android vpn 分析
- Android Vpn 的配置
- Android VPN source code
- PopupWindow的使用
- IOS 保存图片至相册
- MYeclipse使用theme
- Java内部类详解
- Eclipse的Java Working set使用方法
- Android VPN编程
- 关于中文命名静态资源导致乱码或者不读取的解决办法
- 网络爬虫基本原理(文章转自博客园:wawlian博客,文章很不错,转了一起学习)
- const的用法
- 用9种办法解决 JS 闭包经典面试题之 for 循环取 i
- Vector:不定长数组基础用法
- ios 限制只能输入字母和数字
- C/C++学习资料集
- Dex Loader] Unable to execute dex: Multiple dex files define Lcom/mob/commons/MobProduct;