I know that android.net.VpnService is basically a base class to build custom vpn solutions, but all I want is to create and use PPTP or L2TP VPN connection (just a new profile for built-in VPN manager). I think that the easiest way to do that is to use Java reflection for com.android.settings.vpn.VpnSettings. Here's the code snippet for that from the other post (How to add own VPN settings to system VPN settings page?)
package com.nikola.despotoski.whatever;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class VpnSetter {
private static Map<String , Class<?>> getMappedFields(){
Map<String , Class<?>> fieldsAndTypes = new HashMap<String, Class<?>>();
fieldsAndTypes.put("name", String.class); // 0
fieldsAndTypes.put("type" , int.class); // 1
fieldsAndTypes.put("server", String.class); // 2
fieldsAndTypes.put("username", String.class);
fieldsAndTypes.put("password", String.class);
fieldsAndTypes.put("dnsServers", String.class);
fieldsAndTypes.put("searchDomains", String.class);
fieldsAndTypes.put("routes", String.class);
fieldsAndTypes.put("mppe", boolean.class);
fieldsAndTypes.put("l2tpSecret", String.class);
fieldsAndTypes.put("ipsecIdentifier", String.class);
fieldsAndTypes.put("ipsecSecret", String.class);
fieldsAndTypes.put("ipsecUserCert", String.class);
fieldsAndTypes.put("ipsecCaCert", String.class);
fieldsAndTypes.put("saveLogin", boolean.class);
return fieldsAndTypes;
}
public static final Set<String> VPN_PROFILE_KEYS = getMappedFields().keySet(); // contains keys for quicker generation of key-value map for each
public static void addVpnProfile(String vpnProfileKey, Map<String, Object> values) throws ClassNotFoundException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException{
Class<?> vpnSettings = Class.forName("com.android.settings.vpn2.VpnSettings");
Class<?>[] privateVpnSettingsClasses = vpnSettings.getDeclaredClasses();
Class<?> vpnPreference = null;
Class<?> vpnProfileClass = Class.forName("com.android.settings.vpn2.VpnProfile");
for(Class<?> priv :privateVpnSettingsClasses ){
if(priv.getName().equals("VpnPreference")){
vpnPreference = priv;
break;
}
}
Field vpnProfileFromVpnPreferenceField = vpnPreference.getDeclaredField("mProfile");
vpnProfileFromVpnPreferenceField.setAccessible(true);
Object vpnProfile = vpnProfileFromVpnPreferenceField.get(vpnProfileClass);
Constructor<?> constructor = vpnProfileFromVpnPreferenceField.getClass().getConstructors()[0];
constructor.setAccessible(true);
vpnProfile = constructor.newInstance(vpnProfileKey);//creating new instance of VpnProfile class
Map<String, Class<?>> vpnProfileMap = getMappedFields();
Iterator<String> profileKeysIterator = vpnProfileMap.keySet().iterator();
while(profileKeysIterator.hasNext()){
String key = profileKeysIterator.next();
Field field = vpnProfile.getClass().getField(key);
field.setAccessible(true);
if(vpnProfileMap.get(key).equals(String.class) && values.get(key)!=null){
String s = new String();
field.set(s, "value");//change this
}else if(vpnProfileMap.get(key).equals(boolean.class) && values.get(key)!=null){
int i = 0;
field.setInt(i, 1111111);// change this
}else if(values.get(key)!=null){
boolean b = false;
field.setBoolean(b, true);// change this
}
}
vpnSettings = Class.forName("com.android.settings.vpn.VpnSettings"); //time to add it to settings
Method addProfileMethod = vpnSettings.getDeclaredMethod("addProfile", vpnProfile.getClass());
addProfileMethod.setAccessible(true);
addProfileMethod.invoke(vpnSettings, vpnProfile);
}
}
When I run this code I get: java.lang.classnotfoundexception: com.android.settings.vpn2.vpnsettings
Just what to know what I'm doing wrong. I tried with API 14, 15 .. 18 Device is not rooted.
If you have another suggestion how to add a new profile to built-in VPN manager please let me know.