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
原创粉丝点击