How to add custom VPN settings using Java Reflecion (Android SDK 14+)

I know that android.net.VpnService is basically the base class for creating custom vpn solutions, but all I want to do is create and use a PPTP or L2TP VPN connection (just a new profile for the built-in VPN manager). I think the easiest way to do this is to use Java reflection for com.android.settings.vpn.VpnSettings. Here's a code snippet for this from another post ( How do I add my own VPN settings to the VPN system 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 that to know what I'm doing wrong. I tried with API 14, 15 .. 18 Devices are not deployed.

If you have another suggestion on how to add a new profile to the built-in VPN manager, please let me know.

+6
source share
2 answers

Basically, what you're trying will not work, because the VpnSettings class VpnSettings not available in your application. This is not a private part of the Android platform; This is part of the Settings app, which is a completely separate application. This is similar to trying to access the org.mozilla.firefox.App class from a Firefox application. You cannot do this. And if you could, you would find that it still won’t work, because VpnSettings saves its settings in a place that your application does not have access to access.

If your device has been deployed and your application has access to the root directory, you can potentially write it to this location. Otherwise, you have no chance of it.

+3
source

It seems like changing my Android Project Build Target object to the Google target API instead of the Android target goal fixed the problem (or at least I no longer get a ClassNotFoundException).

Try to install this yourself: right-click on your project. Build Path β†’ Configure Build Path ... Go to Android Settings in the left pane. Check the appropriate Google target API for your project.

EDIT: This fixed the VpnProfile problem that I had, but not the VpnSettings that you have (now I have this problem).

EDIT 2: The VpnSettings class is in the Settings app. You can download the source for the Settings app if you want: https://android.googlesource.com/platform/packages/apps/Settings.git

+1
source

Source: https://habr.com/ru/post/954390/


All Articles