解决方案 »

  1.   


    /*
     * Copyright (C) 2011 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */package com.android.settings.vpn2;import com.android.settings.R;import android.content.Context;
    import android.content.DialogInterface;
    import android.net.IConnectivityManager;
    import android.net.LinkProperties;
    import android.net.RouteInfo;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.os.ServiceManager;
    import android.preference.Preference;
    import android.preference.PreferenceGroup;
    import android.security.Credentials;
    import android.security.KeyStore;
    import android.util.Log;
    import android.view.ContextMenu;
    import android.view.ContextMenu.ContextMenuInfo;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.AdapterView.AdapterContextMenuInfo;
    import android.widget.Toast;import com.android.internal.net.LegacyVpnInfo;
    import com.android.internal.net.VpnConfig;
    import com.android.settings.SettingsPreferenceFragment;import java.net.Inet4Address;
    import java.nio.charset.Charsets;
    import java.util.Arrays;
    import java.util.HashMap;public class VpnSettings extends SettingsPreferenceFragment implements
            Handler.Callback, Preference.OnPreferenceClickListener,
            DialogInterface.OnClickListener, DialogInterface.OnDismissListener {    private static final String TAG = "VpnSettings";    private final IConnectivityManager mService = IConnectivityManager.Stub
                .asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
        private final KeyStore mKeyStore = KeyStore.getInstance();
        private boolean mUnlocking = false;    private HashMap<String, VpnPreference> mPreferences;
        private VpnDialog mDialog;    private Handler mUpdater;
        private LegacyVpnInfo mInfo;    // The key of the profile for the current ContextMenu.
        private String mSelectedKey;    @Override
        public void onCreate(Bundle savedState) {
            super.onCreate(savedState);
            addPreferencesFromResource(R.xml.vpn_settings2);
            getPreferenceScreen().setOrderingAsAdded(false);        if (savedState != null) {
                VpnProfile profile = VpnProfile.decode(savedState.getString("VpnKey"),
                        savedState.getByteArray("VpnProfile"));
                if (profile != null) {
                    mDialog = new VpnDialog(getActivity(), this, profile,
                            savedState.getBoolean("VpnEditing"));
                }
            }
        }    @Override
        public void onSaveInstanceState(Bundle savedState) {
            // We do not save view hierarchy, as they are just profiles.
            if (mDialog != null) {
                VpnProfile profile = mDialog.getProfile();
                savedState.putString("VpnKey", profile.key);
                savedState.putByteArray("VpnProfile", profile.encode());
                savedState.putBoolean("VpnEditing", mDialog.isEditing());
            }
            // else?
        }    @Override
        public void onResume() {
            super.onResume();        // Check KeyStore here, so others do not need to deal with it.
            if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
                if (!mUnlocking) {
                    // Let us unlock KeyStore. See you later!
                    Credentials.getInstance().unlock(getActivity());
                } else {
                    // We already tried, but it is still not working!
                    finishFragment();
                }
                mUnlocking = !mUnlocking;
                return;
            }        // Now KeyStore is always unlocked. Reset the flag.
            mUnlocking = false;        // Currently we are the only user of profiles in KeyStore.
            // Assuming KeyStore and KeyGuard do the right thing, we can
            // safely cache profiles in the memory.
            if (mPreferences == null) {
                mPreferences = new HashMap<String, VpnPreference>();
                PreferenceGroup group = getPreferenceScreen();            String[] keys = mKeyStore.saw(Credentials.VPN);
                if (keys != null && keys.length > 0) {
                    Context context = getActivity();                for (String key : keys) {
                        VpnProfile profile = VpnProfile.decode(key,
                                mKeyStore.get(Credentials.VPN + key));
                        if (profile == null) {
                            Log.w(TAG, "bad profile: key = " + key);
                            mKeyStore.delete(Credentials.VPN + key);
                        } else {
                            VpnPreference preference = new VpnPreference(context, profile);
                            mPreferences.put(key, preference);
                            group.addPreference(preference);
                        }
                    }
                }
                group.findPreference("add_network").setOnPreferenceClickListener(this);
            }        // Show the dialog if there is one.
            if (mDialog != null) {
                mDialog.setOnDismissListener(this);
                mDialog.show();
            }        // Start monitoring.
            if (mUpdater == null) {
                mUpdater = new Handler(this);
            }
            mUpdater.sendEmptyMessage(0);        // Register for context menu. Hmmm, getListView() is hidden?
            registerForContextMenu(getListView());
        }    @Override
        public void onPause() {
            super.onPause();        // Hide the dialog if there is one.
            if (mDialog != null) {
                mDialog.setOnDismissListener(null);
                mDialog.dismiss();
            }        // Unregister for context menu.
            if (getView() != null) {
                unregisterForContextMenu(getListView());
            }
        }    @Override
        public void onDismiss(DialogInterface dialog) {
            // Here is the exit of a dialog.
            mDialog = null;
        }    @Override
        public void onClick(DialogInterface dialog, int button) {
            if (button == DialogInterface.BUTTON_POSITIVE) {
                // Always save the profile.
                VpnProfile profile = mDialog.getProfile();
                mKeyStore.put(Credentials.VPN + profile.key, profile.encode());            // Update the preference.
                VpnPreference preference = mPreferences.get(profile.key);
                if (preference != null) {
                    disconnect(profile.key);
                    preference.update(profile);
                } else {
                    preference = new VpnPreference(getActivity(), profile);
                    mPreferences.put(profile.key, preference);
                    getPreferenceScreen().addPreference(preference);
                }            // If we are not editing, connect!
                if (!mDialog.isEditing()) {
                    try {
                        connect(profile);
                    } catch (Exception e) {
                        Log.e(TAG, "connect", e);
                    }
                }
            }
        }    @Override
        public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
            if (mDialog != null) {
                Log.v(TAG, "onCreateContextMenu() is called when mDialog != null");
                return;
            }        if (info instanceof AdapterContextMenuInfo) {
                Preference preference = (Preference) getListView().getItemAtPosition(
                        ((AdapterContextMenuInfo) info).position);
                if (preference instanceof VpnPreference) {
                    VpnProfile profile = ((VpnPreference) preference).getProfile();
                    mSelectedKey = profile.key;
                    menu.setHeaderTitle(profile.name);
                    menu.add(Menu.NONE, R.string.vpn_menu_edit, 0, R.string.vpn_menu_edit);
                    menu.add(Menu.NONE, R.string.vpn_menu_delete, 0, R.string.vpn_menu_delete);
                }
            }
        }    @Override
        public boolean onContextItemSelected(MenuItem item) {
            if (mDialog != null) {
                Log.v(TAG, "onContextItemSelected() is called when mDialog != null");
                return false;
            }        VpnPreference preference = mPreferences.get(mSelectedKey);
            if (preference == null) {
                Log.v(TAG, "onContextItemSelected() is called but no preference is found");
                return false;
            }        switch (item.getItemId()) {
                case R.string.vpn_menu_edit:
                    mDialog = new VpnDialog(getActivity(), this, preference.getProfile(), true);
                    mDialog.setOnDismissListener(this);
                    mDialog.show();
                    return true;
                case R.string.vpn_menu_delete:
                    disconnect(mSelectedKey);
                    getPreferenceScreen().removePreference(preference);
                    mPreferences.remove(mSelectedKey);
                    mKeyStore.delete(Credentials.VPN + mSelectedKey);
                    return true;
            }
            return false;
        }
      

  2.   

        @Override
        public boolean onPreferenceClick(Preference preference) {
            if (mDialog != null) {
                Log.v(TAG, "onPreferenceClick() is called when mDialog != null");
                return true;
            }        if (preference instanceof VpnPreference) {
                VpnProfile profile = ((VpnPreference) preference).getProfile();
                if (mInfo != null && profile.key.equals(mInfo.key) &&
                        mInfo.state == LegacyVpnInfo.STATE_CONNECTED) {
                    try {
                        mInfo.intent.send();
                        return true;
                    } catch (Exception e) {
                        // ignore
                    }
                }
                mDialog = new VpnDialog(getActivity(), this, profile, false);
            } else {
                // Generate a new key. Here we just use the current time.
                long millis = System.currentTimeMillis();
                while (mPreferences.containsKey(Long.toHexString(millis))) {
                    ++millis;
                }
                mDialog = new VpnDialog(getActivity(), this,
                        new VpnProfile(Long.toHexString(millis)), true);
            }
            mDialog.setOnDismissListener(this);
            mDialog.show();
            return true;
        }    @Override
        public boolean handleMessage(Message message) {
            mUpdater.removeMessages(0);        if (isResumed()) {
                try {
                    LegacyVpnInfo info = mService.getLegacyVpnInfo();
                    if (mInfo != null) {
                        VpnPreference preference = mPreferences.get(mInfo.key);
                        if (preference != null) {
                            preference.update(-1);
                        }
                        mInfo = null;
                    }
                    if (info != null) {
                        VpnPreference preference = mPreferences.get(info.key);
                        if (preference != null) {
                            preference.update(info.state);
                            mInfo = info;
                        }
                    }
                } catch (Exception e) {
                    // ignore
                }
                mUpdater.sendEmptyMessageDelayed(0, 1000);
            }
            return true;
        }    private String[] getDefaultNetwork() throws Exception {
            LinkProperties network = mService.getActiveLinkProperties();
            if (network == null) {
                Toast.makeText(getActivity(), R.string.vpn_no_network, Toast.LENGTH_LONG).show();
                throw new IllegalStateException("Network is not available");
            }
            String interfaze = network.getInterfaceName();
            if (interfaze == null) {
                Toast.makeText(getActivity(), R.string.vpn_no_network, Toast.LENGTH_LONG).show();
                throw new IllegalStateException("Cannot get the default interface");
            }
            String gateway = null;
            for (RouteInfo route : network.getRoutes()) {
                // Currently legacy VPN only works on IPv4.
                if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
                    gateway = route.getGateway().getHostAddress();
                    break;
                }
            }
            if (gateway == null) {
                Toast.makeText(getActivity(), R.string.vpn_no_network, Toast.LENGTH_LONG).show();
                throw new IllegalStateException("Cannot get the default gateway");
            }
            return new String[] {interfaze, gateway};
        }  
      

  3.   

      private void connect(VpnProfile profile) throws Exception {
            // Get the default interface and the default gateway.
            String[] network = getDefaultNetwork();
            String interfaze = network[0];
            String gateway = network[1];        // Load certificates.
            String privateKey = "";
            String userCert = "";
            String caCert = "";
            String serverCert = "";
            if (!profile.ipsecUserCert.isEmpty()) {
                /*
                 * VPN has a special exception in keystore to allow it to use system
                 * UID certs.
                 */
                privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
                byte[] value = mKeyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert);
                userCert = (value == null) ? null : new String(value, Charsets.UTF_8);
            }
            if (!profile.ipsecCaCert.isEmpty()) {
                byte[] value = mKeyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
                caCert = (value == null) ? null : new String(value, Charsets.UTF_8);
            }
            if (!profile.ipsecServerCert.isEmpty()) {
                byte[] value = mKeyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
                serverCert = (value == null) ? null : new String(value, Charsets.UTF_8);
            }
            if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
                Toast.makeText(getActivity(), R.string.vpn_missing_cert, Toast.LENGTH_LONG).show();
                throw new IllegalStateException("Cannot load credentials");
            }        // Prepare arguments for racoon.
            String[] racoon = null;
            switch (profile.type) {
                case VpnProfile.TYPE_L2TP_IPSEC_PSK:
                    racoon = new String[] {
                        interfaze, profile.server, "udppsk", profile.ipsecIdentifier,
                        profile.ipsecSecret, "1701",
                    };
                    break;
                case VpnProfile.TYPE_L2TP_IPSEC_RSA:
                    racoon = new String[] {
                        interfaze, profile.server, "udprsa", privateKey, userCert,
                        caCert, serverCert, "1701",
                    };
                    break;
                case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
                    racoon = new String[] {
                        interfaze, profile.server, "xauthpsk", profile.ipsecIdentifier,
                        profile.ipsecSecret, profile.username, profile.password, "", gateway,
                    };
                    break;
                case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
                    racoon = new String[] {
                        interfaze, profile.server, "xauthrsa", privateKey, userCert,
                        caCert, serverCert, profile.username, profile.password, "", gateway,
                    };
                    break;
                case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
                    racoon = new String[] {
                        interfaze, profile.server, "hybridrsa",
                        caCert, serverCert, profile.username, profile.password, "", gateway,
                    };
                    break;
            }        // Prepare arguments for mtpd.
            String[] mtpd = null;
            switch (profile.type) {
                case VpnProfile.TYPE_PPTP:
                    mtpd = new String[] {
                        interfaze, "pptp", profile.server, "1723",
                        "name", profile.username, "password", profile.password,
                        "linkname", "vpn", "refuse-eap", "nodefaultroute",
                        "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
                        (profile.mppe ? "+mppe" : "nomppe"),
                    };
                    break;
                case VpnProfile.TYPE_L2TP_IPSEC_PSK:
                case VpnProfile.TYPE_L2TP_IPSEC_RSA:
                    mtpd = new String[] {
                        interfaze, "l2tp", profile.server, "1701", profile.l2tpSecret,
                        "name", profile.username, "password", profile.password,
                        "linkname", "vpn", "refuse-eap", "nodefaultroute",
                        "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
                    };
                    break;
            }        VpnConfig config = new VpnConfig();
            config.user = profile.key;
            config.interfaze = interfaze;
            config.session = profile.name;
            config.routes = profile.routes;
            if (!profile.dnsServers.isEmpty()) {
                config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
            }
            if (!profile.searchDomains.isEmpty()) {
                config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
            }        mService.startLegacyVpn(config, racoon, mtpd);
        }    private void disconnect(String key) {
            if (mInfo != null && key.equals(mInfo.key)) {
                try {
                    mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
                } catch (Exception e) {
                    // ignore
                }
            }
        }    @Override
        protected int getHelpResource() {
            return R.string.help_url_vpn;
        }    private class VpnPreference extends Preference {
            private VpnProfile mProfile;
            private int mState = -1;        VpnPreference(Context context, VpnProfile profile) {
                super(context);
                setPersistent(false);
                setOrder(0);
                setOnPreferenceClickListener(VpnSettings.this);            mProfile = profile;
                update();
            }        VpnProfile getProfile() {
                return mProfile;
            }        void update(VpnProfile profile) {
                mProfile = profile;
                update();
            }        void update(int state) {
                mState = state;
                update();
            }        void update() {
                if (mState < 0) {
                    String[] types = getContext().getResources()
                            .getStringArray(R.array.vpn_types_long);
                    setSummary(types[mProfile.type]);
                } else {
                    String[] states = getContext().getResources()
                            .getStringArray(R.array.vpn_states);
                    setSummary(states[mState]);
                }
                setTitle(mProfile.name);
                notifyHierarchyChanged();
            }        @Override
            public int compareTo(Preference preference) {
                int result = -1;
                if (preference instanceof VpnPreference) {
                    VpnPreference another = (VpnPreference) preference;
                    if ((result = another.mState - mState) == 0 &&
                            (result = mProfile.name.compareTo(another.mProfile.name)) == 0 &&
                            (result = mProfile.type - another.mProfile.type) == 0) {
                        result = mProfile.key.compareTo(another.mProfile.key);
                    }
                }
                return result;
            }
        } 
      

  4.   

    这个要把代码抽出来!在android sdk 环境下编译 在eclipse 很多隐藏报错的 要想在Eclipse 下把相关class 文件拷贝到android.jar中 如果是隐藏的方法 你可以改源码 !然后make j8 重新编译  IConnectivityManager.startLegacyVpn(config, racoon, mtpd);这个我没找到源码  只有在SDK下编译了
      

  5.   

    有没有弄出来的,麻烦给个demo啊,非常感谢。 [email protected]
      

  6.   

    有没有弄出来的,麻烦给个demo啊,非常感谢。 [email protected]