SipEditor.java revision bb5fb3fa71c9b9ab678f5cf5f2a9cc69ceea3445
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone.sip;
18
19import com.android.phone.R;
20
21import android.app.AlertDialog;
22import android.content.DialogInterface;
23import android.content.Intent;
24import android.net.sip.SipProfile;
25import android.os.Bundle;
26import android.os.Parcel;
27import android.os.Parcelable;
28import android.preference.CheckBoxPreference;
29import android.preference.EditTextPreference;
30import android.preference.ListPreference;
31import android.preference.Preference;
32import android.preference.PreferenceActivity;
33import android.preference.PreferenceGroup;
34import android.text.TextUtils;
35import android.util.Log;
36import android.view.KeyEvent;
37import android.view.Menu;
38import android.view.MenuItem;
39import android.view.View;
40import android.widget.Button;
41
42import java.lang.reflect.Constructor;
43import java.lang.reflect.InvocationTargetException;
44import java.lang.reflect.Method;
45
46/**
47 * The activity class for editing a new or existing SIP profile.
48 */
49public class SipEditor extends PreferenceActivity
50        implements Preference.OnPreferenceChangeListener {
51    private static final int MENU_SAVE = Menu.FIRST;
52    private static final int MENU_DISCARD = Menu.FIRST + 1;
53
54    private static final String TAG = SipEditor.class.getSimpleName();
55    private static final String KEY_PROFILE = "profile";
56    private static final String SCRAMBLED = "****";
57    private static final String EMPTY = "";
58    private static final String DEFAULT_SIP_PORT = "5060";
59    private static final String DEFAULT_PROTOCOL = "UDP";
60    private static final String GET_METHOD_PREFIX = "get";
61
62    private boolean mAddingProfile;
63
64    enum PreferenceKey {
65        ProfileName(R.string.profile_name, 0, EMPTY),
66        DomainAddress(R.string.domain_address, 1, EMPTY),
67        Username(R.string.username, 2, EMPTY),
68        Password(R.string.password, 3, EMPTY),
69        DisplayName(R.string.display_name, 4, EMPTY),
70        ProxyAddress(R.string.proxy_address, 5, EMPTY),
71        Port(R.string.port, 6, DEFAULT_SIP_PORT),
72        Transport(R.string.transport, 7, DEFAULT_PROTOCOL),
73        SendKeepAlive(R.string.send_keepalive, 8, EMPTY),
74        AutoRegistration(R.string.auto_registration, 9, EMPTY);
75
76        /**
77         * @param key The key name of the preference.
78         * @param index The index of the preference in the view.
79         * @param defaultValue The default value of the preference.
80         */
81        PreferenceKey(int text, int index, String defaultValue) {
82            this.text = text;
83            this.index = index;
84            this.defaultValue = defaultValue;
85        }
86
87        public final int text;
88        public final int index;
89        public final String defaultValue;
90    }
91
92    private Preference[] mPreferences =
93            new Preference[PreferenceKey.values().length];
94
95    @Override
96    public void onCreate(Bundle savedInstanceState) {
97        Log.v(TAG, "start profile editor");
98        super.onCreate(savedInstanceState);
99
100        setContentView(R.layout.sip_settings_ui);
101        addPreferencesFromResource(R.xml.sip_edit);
102        final SipProfile p = (SipProfile) ((savedInstanceState == null)
103                ? getIntent().getParcelableExtra(SipSettings.KEY_SIP_PROFILE)
104                : savedInstanceState.getParcelable(KEY_PROFILE));
105
106        for (PreferenceKey key : PreferenceKey.values()) {
107            mPreferences[key.index] = setupPreference(getString(key.text));
108        }
109        if (p == null) {
110            findViewById(R.id.add_remove_account_bar)
111                    .setVisibility(View.GONE);
112        } else {
113            Button removeButton =
114                    (Button)findViewById(R.id.add_remove_account_button);
115            removeButton.setText(getString(R.string.remove_sip_account));
116            removeButton.setOnClickListener(
117                    new android.view.View.OnClickListener() {
118                        public void onClick(View v) {
119                            setRemovedProfileAndFinish(p);
120                        }
121                    });
122        }
123        loadPreferencesFromProfile(p);
124    }
125
126    @Override
127    public boolean onCreateOptionsMenu(Menu menu) {
128        super.onCreateOptionsMenu(menu);
129        menu.add(0, MENU_SAVE, 0, R.string.sip_menu_save)
130                .setIcon(android.R.drawable.ic_menu_save);
131        menu.add(0, MENU_DISCARD, 0, R.string.sip_menu_discard)
132                .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
133        return true;
134    }
135
136    @Override
137    public boolean onOptionsItemSelected(MenuItem item) {
138        switch (item.getItemId()) {
139            case MENU_SAVE:
140                if (validateAndSetResult()) {
141                    finish();
142                }
143                return true;
144
145            case MENU_DISCARD:
146                finish();
147                return true;
148        }
149        return super.onOptionsItemSelected(item);
150    }
151
152    @Override
153    public boolean onKeyDown(int keyCode, KeyEvent event) {
154        switch (keyCode) {
155            case KeyEvent.KEYCODE_BACK:
156                if (validateAndSetResult()) finish();
157                return true;
158        }
159        return super.onKeyDown(keyCode, event);
160    }
161
162    private void setRemovedProfileAndFinish(SipProfile p) {
163        try {
164            Intent intent = new Intent(this, SipSettings.class);
165            intent.putExtra(SipSettings.KEY_SIP_PROFILE, (Parcelable) p);
166            setResult(RESULT_FIRST_USER, intent);
167            finish();
168        } catch (Exception e) {
169            showAlert(e.getMessage());
170        }
171    }
172
173    private void showAlert(String message) {
174        new AlertDialog.Builder(this)
175                .setTitle(android.R.string.dialog_alert_title)
176                .setIcon(android.R.drawable.ic_dialog_alert)
177                .setMessage(message)
178                .setPositiveButton(R.string.alert_dialog_ok,
179                        new DialogInterface.OnClickListener() {
180                            public void onClick(DialogInterface dialog, int w) {
181                            }
182                        })
183                .show();
184    }
185
186    private boolean validateAndSetResult() {
187        for(Preference pref : mPreferences)  {
188            String value = EMPTY;
189            if (pref instanceof ListPreference) {
190                value = ((ListPreference)pref).getValue();
191            } else if (pref instanceof EditTextPreference) {
192                value = ((EditTextPreference)pref).getText();
193            } else if (pref instanceof CheckBoxPreference) {
194                continue;
195            }
196            if (TextUtils.isEmpty(value) &&
197                    (pref != mPreferences[PreferenceKey.ProxyAddress.index])) {
198                showAlert(pref.getTitle() + " "
199                        + getString(R.string.empty_alert));
200                return false;
201            }
202        }
203        try {
204            Intent intent = new Intent(this, SipSettings.class);
205            intent.putExtra(SipSettings.KEY_SIP_PROFILE,
206                    (Parcelable) createSipProfile());
207            setResult(RESULT_OK, intent);
208            return true;
209        } catch (Exception e) {
210            Log.e(TAG, "Can not create new SipProfile : " + e.getMessage());
211            showAlert(e.getMessage());
212            return false;
213        }
214    }
215
216    private SipProfile createSipProfile() throws Exception {
217            return new SipProfile.Builder(
218                    getValue(PreferenceKey.Username),
219                    getValue(PreferenceKey.DomainAddress))
220                    .setProfileName(getValue(PreferenceKey.ProfileName))
221                    .setPassword(getValue(PreferenceKey.Password))
222                    .setOutboundProxy(getValue(PreferenceKey.ProxyAddress))
223                    .setProtocol(getValue(PreferenceKey.Transport))
224                    .setDisplayName(getValue(PreferenceKey.DisplayName))
225                    .setPort(Integer.parseInt(getValue(PreferenceKey.Port)))
226                    .setSendKeepAlive(isChecked(PreferenceKey.SendKeepAlive))
227                    .setAutoRegistration(
228                            isChecked(PreferenceKey.AutoRegistration))
229                    .build();
230    }
231
232    public boolean onPreferenceChange(Preference pref, Object newValue) {
233        if (pref instanceof CheckBoxPreference) return true;
234        String value = (String) newValue;
235        if (value == null) value = EMPTY;
236        if (pref != mPreferences[PreferenceKey.Password.index]) {
237            pref.setSummary(value);
238        } else {
239            pref.setSummary(SCRAMBLED);
240        }
241        return true;
242    }
243
244    private void loadPreferencesFromProfile(SipProfile p) {
245        if (p != null) {
246            Log.v(TAG, "Edit the existing profile : " + p.getProfileName());
247            try {
248                Class profileClass = SipProfile.class;
249                for (PreferenceKey key : PreferenceKey.values()) {
250                    Method meth = profileClass.getMethod(GET_METHOD_PREFIX +
251                            getString(key.text), (Class[])null);
252                    if (key == PreferenceKey.Port) {
253                        setValue(key,
254                                String.valueOf(meth.invoke(p, (Object[])null)));
255                    } else if (key == PreferenceKey.SendKeepAlive
256                            || key == PreferenceKey.AutoRegistration) {
257                        setCheckBox(key, ((Boolean)
258                                meth.invoke(p, (Object[])null)).booleanValue());
259                    } else {
260                        setValue(key, (String) meth.invoke(p, (Object[])null));
261                    }
262                }
263            } catch (Exception e) {
264                Log.e(TAG, "Can not load pref from profile:" + e.getMessage());
265            }
266        } else {
267            Log.v(TAG, "Edit a new profile");
268            for (PreferenceKey key : PreferenceKey.values()) {
269                Preference pref = mPreferences[key.index];
270                pref.setOnPreferenceChangeListener(this);
271                if (pref instanceof EditTextPreference) {
272                    ((EditTextPreference)pref).setText(key.defaultValue);
273                } else if (pref instanceof ListPreference) {
274                    ((ListPreference)pref).setValue(key.defaultValue);
275                } else {
276                    continue;
277                }
278                pref.setSummary(EMPTY.equals(key.defaultValue)
279                        ? getString(R.string.initial_preference_summary) : key.defaultValue);
280            }
281        }
282    }
283
284    private boolean isChecked(PreferenceKey key) {
285        CheckBoxPreference pref = (CheckBoxPreference)mPreferences[key.index];
286        return pref.isChecked();
287    }
288
289    private String getValue(PreferenceKey key) {
290        Preference pref = mPreferences[key.index];
291        if (pref instanceof EditTextPreference) {
292            return ((EditTextPreference)pref).getText();
293        } else if (pref instanceof ListPreference) {
294            return ((ListPreference)pref).getValue();
295        }
296        throw new RuntimeException("getValue() for the preference " + key.text);
297    }
298
299    private void setCheckBox(PreferenceKey key, boolean checked) {
300        CheckBoxPreference pref = (CheckBoxPreference) mPreferences[key.index];
301        pref.setChecked(checked);
302    }
303
304    private void setValue(PreferenceKey key, String value) {
305        Preference pref = mPreferences[key.index];
306        if (pref instanceof EditTextPreference) {
307            ((EditTextPreference)pref).setText(value);
308        } else if (pref instanceof ListPreference) {
309            ((ListPreference)pref).setValue(value);
310        }
311
312        if (TextUtils.isEmpty(value)) {
313            value = getString(R.string.initial_preference_summary);
314        } else {
315            if (key == PreferenceKey.Password) value = SCRAMBLED;
316        }
317        pref.setSummary(value);
318    }
319
320    private Preference setupPreference(String key) {
321        Preference pref = getPreferenceScreen().findPreference(key);
322        pref.setOnPreferenceChangeListener(this);
323        return pref;
324    }
325}
326