问题
There are system setting for VPN. I am going to add additional VPN service probably based on the VpnService class. As I see there is a method setConfigureIntent
which looks similar to something I need but I do not see any examples of usage.
public VpnService.Builder setConfigureIntent (PendingIntent intent)
Added in API level 14 Set the
PendingIntent
to an activity for users to configure the VPN connection. If it is not set, the button to configure will not be shown in system-managed dialogs.
VPN settings pages are here:


Actually I just need to add a button to the system VPN settings clicking on which custom dialog with VPN specific settings is shown.
回答1:
Here is starting point to what @shoe rat proposed, using Java Reflection:
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);
}
}
I didn't have time to test it, but surely it will give you a starting point. I'm not sure root access is needed for accessing this hidden API. Please bare in mind that this might throw some SecurityExceptions or IllegalAccessException.
回答2:
If you can not find class,you may try this.
Context vpnset =createPackageContext("com.android.settings",Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
Class<?> vpnSettings = Class.forName("com.android.settings.vpn2.VpnSettings",true,vpnset.getClassLoader());
来源:https://stackoverflow.com/questions/18446661/how-to-add-own-vpn-settings-to-system-vpn-settings-page