diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 5a734ffae..6209687bc 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -88,6 +88,7 @@ + diff --git a/res/values/strings.xml b/res/values/strings.xml index a0f30fdc0..fc549ffa6 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -222,4 +222,8 @@ None SRTP ZRTP + +pref_nb_accounts_extra +pref_default_account +SIP Accounts diff --git a/res/xml/account_preferences.xml b/res/xml/account_preferences.xml new file mode 100644 index 000000000..7bf2aa65d --- /dev/null +++ b/res/xml/account_preferences.xml @@ -0,0 +1,4 @@ + + + + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 9f9ec184f..476ed1b69 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -2,8 +2,8 @@ - - + + - + @@ -91,45 +92,45 @@ android:title="@string/pref_codec_pcma"/> - + - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 2d7f60f0c..416dd3c29 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -47,14 +47,21 @@ import java.util.Timer; import java.util.TimerTask; import org.linphone.LinphoneSimpleListener.LinphoneOnAudioChangedListener; -import org.linphone.LinphoneSimpleListener.LinphoneServiceListener; import org.linphone.LinphoneSimpleListener.LinphoneOnAudioChangedListener.AudioState; +import org.linphone.LinphoneSimpleListener.LinphoneServiceListener; import org.linphone.core.CallDirection; import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneAuthInfo; import org.linphone.core.LinphoneCall; +import org.linphone.core.LinphoneCall.State; import org.linphone.core.LinphoneChatRoom; import org.linphone.core.LinphoneCore; +import org.linphone.core.LinphoneCore.EcCalibratorStatus; +import org.linphone.core.LinphoneCore.FirewallPolicy; +import org.linphone.core.LinphoneCore.GlobalState; +import org.linphone.core.LinphoneCore.MediaEncryption; +import org.linphone.core.LinphoneCore.RegistrationState; +import org.linphone.core.LinphoneCore.Transports; import org.linphone.core.LinphoneCoreException; import org.linphone.core.LinphoneCoreFactory; import org.linphone.core.LinphoneCoreListener; @@ -62,18 +69,11 @@ import org.linphone.core.LinphoneFriend; import org.linphone.core.LinphoneProxyConfig; import org.linphone.core.Log; import org.linphone.core.PayloadType; -import org.linphone.core.LinphoneCall.State; -import org.linphone.core.LinphoneCore.EcCalibratorStatus; -import org.linphone.core.LinphoneCore.FirewallPolicy; -import org.linphone.core.LinphoneCore.GlobalState; -import org.linphone.core.LinphoneCore.MediaEncryption; -import org.linphone.core.LinphoneCore.RegistrationState; -import org.linphone.core.LinphoneCore.Transports; import org.linphone.mediastream.Version; import org.linphone.mediastream.video.capture.AndroidVideoApi5JniWrapper; import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration; -import org.linphone.mediastream.video.capture.hwconf.Hacks; import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.AndroidCamera; +import org.linphone.mediastream.video.capture.hwconf.Hacks; import android.app.Activity; import android.content.BroadcastReceiver; @@ -93,8 +93,8 @@ import android.media.MediaPlayer; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.PowerManager; -import android.os.Vibrator; import android.os.PowerManager.WakeLock; +import android.os.Vibrator; import android.preference.PreferenceManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -184,7 +184,6 @@ public final class LinphoneManager implements LinphoneCoreListener { private BroadcastReceiver mKeepAliveReceiver = new KeepAliveReceiver(); private native void hackSpeakerState(boolean speakerOn); - @SuppressWarnings("unused") private static void sRouteAudioToSpeakerHelperHelper(boolean speakerOn) { getInstance().routeAudioToSpeakerHelperHelper(speakerOn); } @@ -623,7 +622,6 @@ public final class LinphoneManager implements LinphoneCoreListener { mLc.addAuthInfo(lAuthInfo); } - //proxy mLc.clearProxyConfigs(); String lProxy = getPrefString(R.string.pref_proxy_key,null); @@ -640,7 +638,16 @@ public final class LinphoneManager implements LinphoneCoreListener { if (lDefaultProxyConfig == null) { lDefaultProxyConfig = LinphoneCoreFactory.instance().createProxyConfig(lIdentity, lProxy, null,true); mLc.addProxyConfig(lDefaultProxyConfig); - mLc.setDefaultProxyConfig(lDefaultProxyConfig); + int defaultAccount = getPrefInt(R.string.pref_default_account, 0); + if (defaultAccount == 0 || defaultAccount >= getPrefInt(R.string.pref_extra_accounts, 0)) { + //outbound proxy + if (getPrefBoolean(R.string.pref_enable_outbound_proxy_key, false)) { + lDefaultProxyConfig.setRoute(lProxy); + } else { + lDefaultProxyConfig.setRoute(null); + } + mLc.setDefaultProxyConfig(lDefaultProxyConfig); + } } else { lDefaultProxyConfig.edit(); @@ -649,8 +656,43 @@ public final class LinphoneManager implements LinphoneCoreListener { lDefaultProxyConfig.enableRegister(true); lDefaultProxyConfig.done(); } + + // Extra accounts + for (int i = 1; i < getPrefExtraAccountsNumber(); i++) { + lUserName = getPrefString(getString(R.string.pref_username_key) + i, null); + lPasswd = getPrefString(getString(R.string.pref_passwd_key) + i, null); + if (lUserName != null && lUserName.length() > 0) { + LinphoneAuthInfo lAuthInfo = LinphoneCoreFactory.instance().createAuthInfo(lUserName, lPasswd, null); + mLc.addAuthInfo(lAuthInfo); + + lDomain = getPrefString(getString(R.string.pref_domain_key) + i, null); + if (lDomain != null && lDomain.length() > 0) { + lIdentity = "sip:"+lUserName+"@"+lDomain; + lProxy = getPrefString(getString(R.string.pref_proxy_key) + i, null); + if (lProxy == null || lProxy.length() == 0) { + lProxy = "sip:" + lDomain; + } + if (!lProxy.startsWith("sip:")) { + lProxy = "sip:" + lProxy; + } + lDefaultProxyConfig = LinphoneCoreFactory.instance().createProxyConfig(lIdentity, lProxy, null, true); + mLc.addProxyConfig(lDefaultProxyConfig); + + //outbound proxy + if (getPrefBoolean(getString(R.string.pref_enable_outbound_proxy_key) + i, false)) { + lDefaultProxyConfig.setRoute(lProxy); + } else { + lDefaultProxyConfig.setRoute(null); + } + + if (i == getPrefInt(R.string.pref_default_account, 0)) { + mLc.setDefaultProxyConfig(lDefaultProxyConfig); + } + } + } + } + lDefaultProxyConfig = mLc.getDefaultProxyConfig(); - if (lDefaultProxyConfig !=null) { //prefix String lPrefix = getPrefString(R.string.pref_prefix_key, null); @@ -659,14 +701,8 @@ public final class LinphoneManager implements LinphoneCoreListener { } //escape + lDefaultProxyConfig.setDialEscapePlus(getPrefBoolean(R.string.pref_escape_plus_key,false)); - //outbound proxy - if (getPrefBoolean(R.string.pref_enable_outbound_proxy_key, false)) { - lDefaultProxyConfig.setRoute(lProxy); - } else { - lDefaultProxyConfig.setRoute(null); - } - } + //init network state NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo(); mLc.setNetworkReachable(networkInfo !=null? networkInfo.getState() == NetworkInfo.State.CONNECTED:false); @@ -766,13 +802,24 @@ public final class LinphoneManager implements LinphoneCoreListener { private boolean getPrefBoolean(int key, boolean value) { return mPref.getBoolean(mR.getString(key), value); } + private boolean getPrefBoolean(String key, boolean value) { + return mPref.getBoolean(key, value); + } private String getPrefString(int key, String value) { return mPref.getString(mR.getString(key), value); } + private int getPrefInt(int key, int value) { + return mPref.getInt(mR.getString(key), value); + } private String getPrefString(int key, int value) { return mPref.getString(mR.getString(key), mR.getString(value)); } - + private String getPrefString(String key, String value) { + return mPref.getString(key, value); + } + private int getPrefExtraAccountsNumber() { + return mPref.getInt(getString(R.string.pref_extra_accounts), 0); + } /* Simple implementation as Android way seems very complicate: diff --git a/src/org/linphone/LinphonePreferencesActivity.java b/src/org/linphone/LinphonePreferencesActivity.java index 5c9f58555..46c1b2ac4 100644 --- a/src/org/linphone/LinphonePreferencesActivity.java +++ b/src/org/linphone/LinphonePreferencesActivity.java @@ -37,24 +37,26 @@ import java.util.List; import org.linphone.LinphoneManager.EcCalibrationListener; import org.linphone.LinphoneManager.LinphoneConfigException; import org.linphone.core.LinphoneCore; -import org.linphone.core.LinphoneCoreException; -import org.linphone.core.Log; import org.linphone.core.LinphoneCore.EcCalibratorStatus; import org.linphone.core.LinphoneCore.MediaEncryption; +import org.linphone.core.LinphoneCoreException; +import org.linphone.core.Log; import org.linphone.mediastream.Version; import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration; import org.linphone.mediastream.video.capture.hwconf.Hacks; +import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.preference.CheckBoxPreference; import android.preference.ListPreference; import android.preference.Preference; -import android.preference.PreferenceActivity; -import android.preference.PreferenceCategory; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; public class LinphonePreferencesActivity extends PreferenceActivity implements EcCalibrationListener { private Handler mHandler = new Handler(); @@ -62,6 +64,8 @@ public class LinphonePreferencesActivity extends PreferenceActivity implements E private CheckBoxPreference elPref; private CheckBoxPreference ecPref; private ListPreference mencPref; + private int nbAccounts = 1; + private static final int ADD_SIP_ACCOUNT = 0x666; private SharedPreferences prefs() { return getPreferenceManager().getSharedPreferences(); @@ -84,6 +88,78 @@ public class LinphonePreferencesActivity extends PreferenceActivity implements E findPreference(id).setEnabled(LinphoneManager.getInstance().detectVideoCodec(mime)); } + private void createDynamicAccountsPreferences() { + PreferenceScreen root = getPreferenceScreen(); + + // Get the good preference screen + final PreferenceCategory accounts = (PreferenceCategory) root.getPreference(0); + accounts.removeAll(); + Preference addAccount = (Preference) root.getPreference(1); + addAccount.setOnPreferenceClickListener(new OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + addExtraAccountPreferencesButton(accounts, nbAccounts, true); + Intent i = new Intent(); + i.putExtra("Account",nbAccounts); + nbAccounts++; + i.setClass(LinphonePreferencesActivity.this, LinphonePreferencesSIPAccountActivity.class); + startActivityForResult(i, ADD_SIP_ACCOUNT); + return true; + } + }); + + // Get already configured extra accounts + SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + nbAccounts = prefs.getInt(getString(R.string.pref_extra_accounts), 1); + for (int i = 0; i < nbAccounts; i++) { + // For each, add menus to configure it + addExtraAccountPreferencesButton(accounts, i, false); + } + } + + public int getNbAccountsExtra() { + return nbAccounts; + } + + private void addExtraAccountPreferencesButton(PreferenceCategory parent, final int n, boolean isNewAccount) { + SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + if (isNewAccount) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(getString(R.string.pref_extra_accounts), n+1); + editor.commit(); + } + + Preference me = new Preference(LinphonePreferencesActivity.this); + String keyUsername = getString(R.string.pref_username_key); + String keyDomain = getString(R.string.pref_domain_key); + if (n > 0) { + keyUsername += n + ""; + keyDomain += n + ""; + } + if (prefs.getString(keyUsername, null) == null) { + me.setTitle(getString(R.string.pref_sipaccount)); + } else { + me.setTitle(prefs.getString(keyUsername, "") + "@" + prefs.getString(keyDomain, "")); + } + + me.setOnPreferenceClickListener(new OnPreferenceClickListener() + { + public boolean onPreferenceClick(Preference preference) { + Intent i = new Intent(); + i.putExtra("Account", n); + i.setClass(LinphonePreferencesActivity.this, LinphonePreferencesSIPAccountActivity.class); + startActivityForResult(i, ADD_SIP_ACCOUNT); + return false; + } + }); + parent.addPreference(me); + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == ADD_SIP_ACCOUNT) { + createDynamicAccountsPreferences(); + } + } @Override protected void onCreate(Bundle savedInstanceState) { @@ -91,6 +167,7 @@ public class LinphonePreferencesActivity extends PreferenceActivity implements E // Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); + createDynamicAccountsPreferences(); addTransportChecboxesListener(); ecCalibratePref = (CheckBoxPreference) findPreference(pref_echo_canceller_calibration_key); diff --git a/src/org/linphone/LinphonePreferencesSIPAccountActivity.java b/src/org/linphone/LinphonePreferencesSIPAccountActivity.java new file mode 100644 index 000000000..47bcfad77 --- /dev/null +++ b/src/org/linphone/LinphonePreferencesSIPAccountActivity.java @@ -0,0 +1,133 @@ +package org.linphone; + +import org.linphone.core.Log; + +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.EditTextPreference; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.text.InputType; + +public class LinphonePreferencesSIPAccountActivity extends PreferenceActivity { + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.account_preferences); + + PreferenceScreen screen = getPreferenceScreen(); + int n = getIntent().getExtras().getInt("Account", 1); + addExtraAccountPreferencesFields(screen, n); + } + + private void addExtraAccountPreferencesFields(PreferenceScreen parent, final int n) { + final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + + PreferenceCategory category = new PreferenceCategory(this); + category.setTitle(getString(R.string.pref_sipaccount)); + + EditTextPreference username = new EditTextPreference(this); + username.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + username.setTitle(getString(R.string.pref_username)); + username.setPersistent(true); + username.setKey(getString(R.string.pref_username_key) + getAccountNumber(n)); + + EditTextPreference password = new EditTextPreference(this); + password.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + password.setTitle(getString(R.string.pref_passwd)); + password.setPersistent(true); + password.setKey(getString(R.string.pref_passwd_key) + getAccountNumber(n)); + + EditTextPreference domain = new EditTextPreference(this); + domain.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + domain.setTitle(getString(R.string.pref_domain)); + domain.setPersistent(true); + domain.setKey(getString(R.string.pref_domain_key) + getAccountNumber(n)); + + EditTextPreference proxy = new EditTextPreference(this); + proxy.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + proxy.setTitle(getString(R.string.pref_proxy)); + proxy.setPersistent(true); + proxy.setKey(getString(R.string.pref_proxy_key) + getAccountNumber(n)); + + CheckBoxPreference outboundProxy = new CheckBoxPreference(this); + outboundProxy.setTitle(getString(R.string.pref_enable_outbound_proxy)); + outboundProxy.setPersistent(true); + outboundProxy.setKey(getString(R.string.pref_enable_outbound_proxy_key) + getAccountNumber(n)); + + final Preference delete = new Preference(this); + delete.setTitle("Delete this account"); + delete.setOnPreferenceClickListener(new OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + int nbAccounts = prefs.getInt(getString(R.string.pref_extra_accounts), 1); + SharedPreferences.Editor editor = prefs.edit(); + + for (int i = n; i < nbAccounts - 1; i++) { + editor.putString(getString(R.string.pref_username_key) + i, prefs.getString(getString(R.string.pref_username_key) + (i+1), null)); + editor.putString(getString(R.string.pref_passwd_key) + i, prefs.getString(getString(R.string.pref_passwd_key) + (i+1), null)); + editor.putString(getString(R.string.pref_domain_key) + i, prefs.getString(getString(R.string.pref_domain_key) + (i+1), null)); + editor.putString(getString(R.string.pref_proxy_key) + i, prefs.getString(getString(R.string.pref_proxy_key) + (i+1), null)); + editor.putBoolean(getString(R.string.pref_enable_outbound_proxy_key) + i, prefs.getBoolean(getString(R.string.pref_enable_outbound_proxy_key) + (i+1), false)); + } + + int lastAccount = nbAccounts - 1; + editor.putString(getString(R.string.pref_username_key) + lastAccount, null); + editor.putString(getString(R.string.pref_passwd_key) + lastAccount, null); + editor.putString(getString(R.string.pref_domain_key) + lastAccount, null); + editor.putString(getString(R.string.pref_proxy_key) + lastAccount, null); + editor.putBoolean(getString(R.string.pref_enable_outbound_proxy_key) + lastAccount, false); + + int defaultAccount = prefs.getInt(getString(R.string.pref_default_account), 0); + if (defaultAccount > n) { + Log.e("Default Account : ", defaultAccount + " => " + (defaultAccount - 1)); + editor.putInt(getString(R.string.pref_default_account), defaultAccount - 1); + } + + editor.putInt(getString(R.string.pref_extra_accounts), nbAccounts - 1); + editor.commit(); + LinphonePreferencesSIPAccountActivity.this.finish(); + return true; + } + }); + + CheckBoxPreference mainAccount = new CheckBoxPreference(this); + mainAccount.setTitle("Use as default"); + mainAccount.setOnPreferenceClickListener(new OnPreferenceClickListener() + { + public boolean onPreferenceClick(Preference preference) { + + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(getString(R.string.pref_default_account), n); + editor.commit(); + delete.setEnabled(false); + preference.setEnabled(false); + return true; + } + }); + + mainAccount.setChecked(prefs.getInt(getString(R.string.pref_default_account), 0) == n); + mainAccount.setEnabled(!mainAccount.isChecked()); + delete.setEnabled(prefs.getInt(getString(R.string.pref_default_account), 0) != n); + + parent.addPreference(category); + category.addPreference(username); + category.addPreference(password); + category.addPreference(domain); + category.addPreference(proxy); + category.addPreference(outboundProxy); + category.addPreference(mainAccount); + category.addPreference(delete); + } + + private String getAccountNumber(int n) { + if (n > 0) + return n + ""; + else + return ""; + } +} \ No newline at end of file