VPN有系统设置。我将根据VpnService类添加额外的VPN服务。我看到有一个方法setConfigureIntent
看起来类似于我需要的东西,但我没有看到任何使用示例。
public VpnService.Builder setConfigureIntent (PendingIntent intent)
在API级别14中添加 将
PendingIntent
设置为用户配置VPN连接的活动。如果未设置,则配置按钮将不会显示在系统管理的对话框中。
VPN设置页面在这里:
,。
实际上我只需要在系统VPN设置中添加一个按钮,点击显示具有VPN特定设置的自定义对话框。
答案 0 :(得分:3)
以下是@shoe rat提出的使用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);
}
}
我没时间测试它,但肯定会给你一个起点。我不确定访问此隐藏API需要root访问权限。请记住,这可能会抛出一些SecurityExceptions或IllegalAccessException。
答案 1 :(得分:0)
如果你找不到上课,你可以尝试一下。
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());