6

android.net.VpnService は基本的にカスタム vpn ソリューションを構築するための基本クラスであることは知っていますが、必要なのは PPTP または L2TP VPN 接続 (組み込み VPN マネージャーの新しいプロファイル) を作成して使用することだけです。これを行う最も簡単な方法は、com.android.settings.vpn.VpnSettings に Java リフレクションを使用することだと思います。他の投稿からのコード スニペットは次のとおりです (システム VPN 設定ページに独自の VPN 設定を追加する方法は? )

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);
    }
}

このコードを実行すると、次のようになります。java.lang.classnotfoundexception: com.android.settings.vpn2.vpnsettings

私が間違っていることを知っているだけです。API 14、15 .. 18 で試しましたデバイスがルート化されていません。

組み込みの VPN マネージャーに新しいプロファイルを追加する方法について別の提案がある場合は、お知らせください。

4

2 に答える 2

4

基本的に、VpnSettingsアプリ内でクラスを使用できないため、試みていることは機能しません。これは Android フレームワークのプライベートな部分ではありません。これは設定アプリの一部であり、あなたのアプリとは完全に別のアプリです。org.mozilla.firefox.AppFirefox アプリからクラスにアクセスしようとするようなものです。あなたはそれをすることはできません。できたとしてもVpnSettings、アプリがアクセス許可を持っていない場所に設定を保存するため、まだ機能しないことがわかります。

デバイスルート化されていて、アプリがルート アクセス権を持っていた場合、その場所に自分で書き込むことができる可能性があります。そうでなければ、これを行うチャンスはありません。

于 2013-11-28T18:35:29.443 に答える