diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c358708658..9e3f11d970 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -101,7 +101,7 @@
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 82a63eafda..e84a532aa3 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -202,4 +202,15 @@
- 5
- 10
+
+
+ - default
+ - custom
+
+
+
+ - @string/arrays__use_default
+ - @string/arrays__use_custom
+
+
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 703f2eeccb..eb980a52bc 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -101,4 +101,9 @@
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d81a30892a..964017fbac 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -153,6 +153,11 @@
Key exchange message...
+
+ Using custom: %s
+ Using default: %s
+ None
+
Now
@@ -691,6 +696,8 @@
Import / export
My identity key
+ Use default
+ Use custom
@@ -775,11 +782,11 @@
Manual MMS settings
Use manual MMS settings
Override system MMS settings with the information below.
- MMSC URL (Required)
- MMS Proxy Host (Optional)
- MMS Proxy Port (Optional)
- MMSC Username (Optional)
- MMSC Password (Optional)
+ MMSC URL
+ MMS Proxy Host
+ MMS Proxy Port
+ MMSC Username
+ MMSC Password
SMS delivery reports
Request a delivery report for each SMS message you send
Automatically delete older messages once a conversation thread exceeds a specified length
diff --git a/res/xml/preferences_manual_mms.xml b/res/xml/preferences_manual_mms.xml
index 65a70a8ba7..abfde94989 100644
--- a/res/xml/preferences_manual_mms.xml
+++ b/res/xml/preferences_manual_mms.xml
@@ -1,33 +1,36 @@
-
-
+
-
+
-
+
-
+
-
+
+
+
-
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java
index 5d3fc29553..42aa764548 100644
--- a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java
+++ b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java
@@ -39,6 +39,7 @@ import org.thoughtcrime.securesms.jobs.PushDecryptJob;
import org.thoughtcrime.securesms.jobs.SmsDecryptJob;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.util.ParcelUtil;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.VersionTracker;
import org.whispersystems.jobqueue.EncryptionKeys;
diff --git a/src/org/thoughtcrime/securesms/MmsPreferencesFragment.java b/src/org/thoughtcrime/securesms/MmsPreferencesFragment.java
deleted file mode 100644
index 918e42b6dd..0000000000
--- a/src/org/thoughtcrime/securesms/MmsPreferencesFragment.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.preference.EditTextPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.support.v4.preference.PreferenceFragment;
-import android.text.TextUtils;
-import android.widget.Toast;
-
-import org.thoughtcrime.securesms.mms.OutgoingMmsConnection;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-
-public class MmsPreferencesFragment extends PreferenceFragment {
-
- @Override
- public void onCreate(Bundle paramBundle) {
- super.onCreate(paramBundle);
- initializePreferences();
- initializeEditTextSummaries();
- ((PassphraseRequiredActionBarActivity) getActivity()).getSupportActionBar()
- .setTitle(R.string.preferences__advanced_mms_access_point_names);
- }
-
- private void initializePreferences() {
- if (!OutgoingMmsConnection.isConnectionPossible(getActivity())) {
- TextSecurePreferences.setUseLocalApnsEnabled(getActivity(), true);
- addPreferencesFromResource(R.xml.preferences_manual_mms);
- this.findPreference(TextSecurePreferences.ENABLE_MANUAL_MMS_PREF)
- .setOnPreferenceChangeListener(new OverrideMmsChangeListener());
- } else {
- addPreferencesFromResource(R.xml.preferences_manual_mms);
- }
- this.findPreference(TextSecurePreferences.MMSC_HOST_PREF).setOnPreferenceChangeListener(new ValidUriVerificationListener());
- this.findPreference(TextSecurePreferences.MMSC_PROXY_HOST_PREF).setOnPreferenceChangeListener(new ValidHostnameVerificationListener());
- this.findPreference(TextSecurePreferences.MMSC_PROXY_PORT_PREF).setOnPreferenceChangeListener(new EditTextVerificationListener());
- this.findPreference(TextSecurePreferences.MMSC_USERNAME_PREF).setOnPreferenceChangeListener(new EditTextVerificationListener());
- this.findPreference(TextSecurePreferences.MMSC_PASSWORD_PREF).setOnPreferenceChangeListener(new EditTextVerificationListener());
- }
-
- private void initializeEditTextSummary(final EditTextPreference preference) {
- preference.setSummary(TextUtils.isEmpty(preference.getText()) ? getString(R.string.MmsPreferencesFragment__not_set) : preference.getText());
- }
-
- private void initializeEditTextSummaries() {
- initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_HOST_PREF));
- initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_PROXY_HOST_PREF));
- initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_PROXY_PORT_PREF));
- initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_USERNAME_PREF));
- initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_PASSWORD_PREF));
- }
-
- private class OverrideMmsChangeListener implements Preference.OnPreferenceChangeListener {
- @Override
- public boolean onPreferenceChange(Preference preference, Object o) {
- TextSecurePreferences.setUseLocalApnsEnabled(getActivity(), true);
- Toast.makeText(getActivity(), R.string.MmsPreferencesFragment__manual_mms_settings_are_required,
- Toast.LENGTH_SHORT).show();
- return false;
- }
- }
-
- public static CharSequence getSummary(Context context) {
- final int enabledResId = R.string.MmsPreferencesFragment__enabled;
- final int disabledResId = R.string.MmsPreferencesFragment__disabled;
-
- return context.getString(TextSecurePreferences.isUseLocalApnsEnabled(context) ? enabledResId : disabledResId);
- }
-
- private class EditTextVerificationListener implements OnPreferenceChangeListener {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- String newString = (String)newValue;
- if (isValid(newString)) {
- preference.setSummary(TextUtils.isEmpty(newString) ? getString(R.string.MmsPreferencesFragment__not_set) : newString);
- return true;
- } else {
- Toast.makeText(getActivity(), getErrorMessage(), Toast.LENGTH_LONG).show();
- return false;
- }
- }
-
- protected boolean isValid(String newString) { return true; }
- protected int getErrorMessage() { return 0; }
- }
-
- private class ValidUriVerificationListener extends EditTextVerificationListener {
- @Override
- protected boolean isValid(String newString) {
- if (TextUtils.isEmpty(newString)) return true;
- try {
- new URI(newString);
- return true;
- } catch (URISyntaxException mue) {
- return false;
- }
- }
-
- @Override
- protected int getErrorMessage() {
- return R.string.MmsPreferencesFragment__invalid_uri;
- }
- }
-
- private class ValidHostnameVerificationListener extends EditTextVerificationListener {
- @Override
- protected boolean isValid(String newString) {
- if (TextUtils.isEmpty(newString)) return true;
- try {
- URI uri = new URI(null, newString, null, null);
- return true;
- } catch (URISyntaxException mue) {
- return false;
- }
- }
-
- @Override
- protected int getErrorMessage() {
- return R.string.MmsPreferencesFragment__invalid_host;
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/PromptMmsActivity.java b/src/org/thoughtcrime/securesms/PromptMmsActivity.java
index 0e4abc51ab..2e495b9a74 100644
--- a/src/org/thoughtcrime/securesms/PromptMmsActivity.java
+++ b/src/org/thoughtcrime/securesms/PromptMmsActivity.java
@@ -5,6 +5,8 @@ import android.os.Bundle;
import android.view.View;
import android.widget.Button;
+import org.thoughtcrime.securesms.preferences.MmsPreferencesActivity;
+
public class PromptMmsActivity extends PassphraseRequiredActionBarActivity {
private Button okButton;
diff --git a/src/org/thoughtcrime/securesms/components/CustomDefaultPreference.java b/src/org/thoughtcrime/securesms/components/CustomDefaultPreference.java
new file mode 100644
index 0000000000..874d0470b7
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/components/CustomDefaultPreference.java
@@ -0,0 +1,227 @@
+package org.thoughtcrime.securesms.components;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.preference.DialogPreference;
+import android.support.annotation.NonNull;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+
+public class CustomDefaultPreference extends DialogPreference {
+
+ private static final String TAG = CustomDefaultPreference.class.getSimpleName();
+
+ private final int inputType;
+ private final String customPreference;
+ private final String customToggle;
+
+ private CustomPreferenceValidator validator;
+ private String defaultValue;
+
+ private Spinner spinner;
+ private EditText customText;
+ private TextView defaultLabel;
+ private Button positiveButton;
+
+ public CustomDefaultPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ int[] attributeNames = new int[]{android.R.attr.inputType, R.attr.custom_pref_toggle};
+ TypedArray attributes = context.obtainStyledAttributes(attrs, attributeNames);
+
+ this.inputType = attributes.getInt(0, 0);
+ this.customPreference = getKey();
+ this.customToggle = attributes.getString(1);
+ this.validator = new NullValidator();
+
+ attributes.recycle();
+
+ setPersistent(false);
+ setDialogLayoutResource(R.layout.custom_default_preference_dialog);
+ }
+
+ public CustomDefaultPreference setValidator(CustomPreferenceValidator validator) {
+ this.validator = validator;
+ return this;
+ }
+
+ public CustomDefaultPreference setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ this.setSummary(getSummary());
+ return this;
+ }
+
+ @Override
+ public String getSummary() {
+ if (isCustom()) {
+ return getContext().getString(R.string.CustomDefaultPreference_using_custom,
+ getPrettyPrintValue(getCustomValue()));
+ } else {
+ return getContext().getString(R.string.CustomDefaultPreference_using_default,
+ getPrettyPrintValue(getDefaultValue()));
+ }
+ }
+
+ @Override
+ protected void onBindDialogView(@NonNull View view) {
+ super.onBindDialogView(view);
+
+ this.spinner = (Spinner) view.findViewById(R.id.default_or_custom);
+ this.defaultLabel = (TextView) view.findViewById(R.id.default_label);
+ this.customText = (EditText) view.findViewById(R.id.custom_edit);
+
+ this.customText.setInputType(inputType);
+ this.customText.addTextChangedListener(new TextValidator());
+ this.customText.setText(getCustomValue());
+ this.spinner.setOnItemSelectedListener(new SelectionLister());
+ this.defaultLabel.setText(getPrettyPrintValue(defaultValue));
+ }
+
+ @Override
+ protected void showDialog(Bundle instanceState) {
+ super.showDialog(instanceState);
+ positiveButton = ((AlertDialog)getDialog()).getButton(AlertDialog.BUTTON_POSITIVE);
+
+ if (isCustom()) spinner.setSelection(1, true);
+ else spinner.setSelection(0, true);
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ if (positiveResult) {
+ if (spinner != null) setCustom(spinner.getSelectedItemPosition() == 1);
+ if (customText != null) setCustomValue(customText.getText().toString());
+
+ setSummary(getSummary());
+ }
+ }
+
+ private String getPrettyPrintValue(String value) {
+ if (TextUtils.isEmpty(value)) return getContext().getString(R.string.CustomDefaultPreference_none);
+ else return value;
+ }
+
+ private boolean isCustom() {
+ return TextSecurePreferences.getBooleanPreference(getContext(), customToggle, false);
+ }
+
+ private void setCustom(boolean custom) {
+ TextSecurePreferences.setBooleanPreference(getContext(), customToggle, custom);
+ }
+
+ private String getCustomValue() {
+ return TextSecurePreferences.getStringPreference(getContext(), customPreference, "");
+ }
+
+ private void setCustomValue(String value) {
+ TextSecurePreferences.setStringPreference(getContext(), customPreference, value);
+ }
+
+ private String getDefaultValue() {
+ return defaultValue;
+ }
+
+ private class SelectionLister implements AdapterView.OnItemSelectedListener {
+
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ defaultLabel.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
+ customText.setVisibility(position == 0 ? View.GONE : View.VISIBLE);
+ positiveButton.setEnabled(position == 0 || validator.isValid(customText.getText().toString()));
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ defaultLabel.setVisibility(View.VISIBLE);
+ customText.setVisibility(View.GONE);
+ }
+ }
+
+ private class TextValidator implements TextWatcher {
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (spinner.getSelectedItemPosition() == 1) {
+ positiveButton.setEnabled(validator.isValid(s.toString()));
+ }
+ }
+ }
+
+ protected interface CustomPreferenceValidator {
+ public boolean isValid(String value);
+ }
+
+ private static class NullValidator implements CustomPreferenceValidator {
+ @Override
+ public boolean isValid(String value) {
+ return true;
+ }
+ }
+
+ public static class UriValidator implements CustomPreferenceValidator {
+ @Override
+ public boolean isValid(String value) {
+ if (TextUtils.isEmpty(value)) return true;
+
+ try {
+ new URI(value);
+ return true;
+ } catch (URISyntaxException mue) {
+ return false;
+ }
+ }
+ }
+
+ public static class HostnameValidator implements CustomPreferenceValidator {
+ @Override
+ public boolean isValid(String value) {
+ if (TextUtils.isEmpty(value)) return true;
+
+ try {
+ URI uri = new URI(null, value, null, null);
+ return true;
+ } catch (URISyntaxException mue) {
+ return false;
+ }
+ }
+ }
+
+ public static class PortValidator implements CustomPreferenceValidator {
+ @Override
+ public boolean isValid(String value) {
+ try {
+ Integer.parseInt(value);
+ return true;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ }
+
+
+
+}
diff --git a/src/org/thoughtcrime/securesms/database/ApnDatabase.java b/src/org/thoughtcrime/securesms/database/ApnDatabase.java
index a136ceac4f..a6694d9b75 100644
--- a/src/org/thoughtcrime/securesms/database/ApnDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/ApnDatabase.java
@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.mms.ApnUnavailableException;
import org.thoughtcrime.securesms.mms.MmsConnection.Apn;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
+import org.whispersystems.libaxolotl.util.guava.Optional;
import java.io.File;
import java.io.FileOutputStream;
@@ -93,13 +94,11 @@ public class ApnDatabase {
null,
SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
}
- protected Apn getLocallyConfiguredMmsConnectionParameters() throws ApnUnavailableException {
- if (TextSecurePreferences.isUseLocalApnsEnabled(context)) {
- String mmsc = TextSecurePreferences.getMmscUrl(context).trim();
- if (TextUtils.isEmpty(mmsc))
- throw new ApnUnavailableException("Malformed locally configured MMSC.");
- if (!mmsc.startsWith("http"))
+ private Apn getCustomApnParameters() {
+ String mmsc = TextSecurePreferences.getMmscUrl(context).trim();
+
+ if (!TextUtils.isEmpty(mmsc) && !mmsc.startsWith("http"))
mmsc = "http://" + mmsc;
String proxy = TextSecurePreferences.getMmscProxy(context);
@@ -108,26 +107,12 @@ public class ApnDatabase {
String pass = TextSecurePreferences.getMmscPassword(context);
return new Apn(mmsc, proxy, port, user, pass);
- }
-
- throw new ApnUnavailableException("No locally configured parameters available");
-
}
- public Apn getMmsConnectionParameters(final String mccmnc, final String apn) {
-
- if (TextSecurePreferences.isUseLocalApnsEnabled(context)) {
- Log.w(TAG, "Choosing locally-overridden MMS settings");
- try {
- return getLocallyConfiguredMmsConnectionParameters();
- } catch (ApnUnavailableException aue) {
- Log.w(TAG, "preference to use local apn set, but no parameters avaiable. falling back.");
- }
- }
-
+ public Apn getDefaultApnParameters(String mccmnc, String apn) {
if (mccmnc == null) {
Log.w(TAG, "mccmnc was null, returning null");
- return null;
+ return Apn.EMPTY;
}
Cursor cursor = null;
@@ -161,9 +146,25 @@ public class ApnDatabase {
}
Log.w(TAG, "No matching APNs found, returning null");
- return null;
+
+ return Apn.EMPTY;
} finally {
if (cursor != null) cursor.close();
}
+
+ }
+
+ public Optional getMmsConnectionParameters(String mccmnc, String apn) {
+ Apn customApn = getCustomApnParameters();
+ Apn defaultApn = getDefaultApnParameters(mccmnc, apn);
+ Apn result = new Apn(customApn, defaultApn,
+ TextSecurePreferences.getUseCustomMmsc(context),
+ TextSecurePreferences.getUseCustomMmscProxy(context),
+ TextSecurePreferences.getUseCustomMmscProxyPort(context),
+ TextSecurePreferences.getUseCustomMmscUsername(context),
+ TextSecurePreferences.getUseCustomMmscPassword(context));
+
+ if (TextUtils.isEmpty(result.getMmsc())) return Optional.absent();
+ else return Optional.of(result);
}
}
diff --git a/src/org/thoughtcrime/securesms/mms/MmsConnection.java b/src/org/thoughtcrime/securesms/mms/MmsConnection.java
index db13f061b7..de91f9234d 100644
--- a/src/org/thoughtcrime/securesms/mms/MmsConnection.java
+++ b/src/org/thoughtcrime/securesms/mms/MmsConnection.java
@@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.database.ApnDatabase;
import org.thoughtcrime.securesms.util.TelephonyUtil;
import org.thoughtcrime.securesms.util.Conversions;
import org.thoughtcrime.securesms.util.Util;
+import org.whispersystems.libaxolotl.util.guava.Optional;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
@@ -56,27 +57,24 @@ public abstract class MmsConnection {
this.apn = apn;
}
- protected static Apn getLocalApn(Context context) throws ApnUnavailableException {
- try {
- Apn params = ApnDatabase.getInstance(context)
- .getMmsConnectionParameters(TelephonyUtil.getMccMnc(context),
- TelephonyUtil.getApn(context));
+ public static Apn getApn(Context context, String apnName) throws ApnUnavailableException {
+ Log.w(TAG, "Getting MMSC params for apn " + apnName);
- if (params == null) {
+ try {
+ Optional params = ApnDatabase.getInstance(context)
+ .getMmsConnectionParameters(TelephonyUtil.getMccMnc(context),
+ TelephonyUtil.getApn(context));
+
+ if (!params.isPresent()) {
throw new ApnUnavailableException("No parameters available from ApnDefaults.");
}
- return params;
+ return params.get();
} catch (IOException ioe) {
throw new ApnUnavailableException("ApnDatabase threw an IOException", ioe);
}
}
- public static Apn getApn(Context context, String apnName) throws ApnUnavailableException {
- Log.w(TAG, "Getting MMSC params for apn " + apnName);
- return getLocalApn(context);
- }
-
protected static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio)
throws IOException
{
@@ -171,6 +169,9 @@ public abstract class MmsConnection {
protected abstract HttpUriRequest constructRequest(boolean useProxy) throws IOException;
public static class Apn {
+
+ public static Apn EMPTY = new Apn("", "", "", "", "");
+
private final String mmsc;
private final String proxy;
private final String port;
@@ -185,6 +186,20 @@ public abstract class MmsConnection {
this.password = password;
}
+ public Apn(Apn customApn, Apn defaultApn,
+ boolean useCustomMmsc,
+ boolean useCustomProxy,
+ boolean useCustomProxyPort,
+ boolean useCustomUsername,
+ boolean useCustomPassword)
+ {
+ this.mmsc = useCustomMmsc ? customApn.mmsc : defaultApn.mmsc;
+ this.proxy = useCustomProxy ? customApn.proxy : defaultApn.proxy;
+ this.port = useCustomProxyPort ? customApn.port : defaultApn.port;
+ this.username = useCustomUsername ? customApn.username : defaultApn.username;
+ this.password = useCustomPassword ? customApn.password : defaultApn.password;
+ }
+
public boolean hasProxy() {
return !TextUtils.isEmpty(proxy);
}
diff --git a/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java
similarity index 95%
rename from src/org/thoughtcrime/securesms/MmsPreferencesActivity.java
rename to src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java
index d3f7682728..b51aa25baa 100644
--- a/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java
+++ b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.thoughtcrime.securesms;
+package org.thoughtcrime.securesms.preferences;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -22,6 +22,7 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.MenuItem;
+import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
diff --git a/src/org/thoughtcrime/securesms/preferences/MmsPreferencesFragment.java b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesFragment.java
new file mode 100644
index 0000000000..48f6409138
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesFragment.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.thoughtcrime.securesms.preferences;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.preference.PreferenceFragment;
+import android.util.Log;
+
+import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.components.CustomDefaultPreference;
+import org.thoughtcrime.securesms.database.ApnDatabase;
+import org.thoughtcrime.securesms.mms.MmsConnection;
+import org.thoughtcrime.securesms.util.TelephonyUtil;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
+
+import java.io.IOException;
+
+
+public class MmsPreferencesFragment extends PreferenceFragment {
+
+ private static final String TAG = MmsPreferencesFragment.class.getSimpleName();
+
+ @Override
+ public void onCreate(Bundle paramBundle) {
+ super.onCreate(paramBundle);
+ addPreferencesFromResource(R.xml.preferences_manual_mms);
+
+ ((PassphraseRequiredActionBarActivity) getActivity()).getSupportActionBar()
+ .setTitle(R.string.preferences__advanced_mms_access_point_names);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ new LoadApnDefaultsTask().execute();
+ }
+
+ private class LoadApnDefaultsTask extends AsyncTask {
+
+ @Override
+ protected MmsConnection.Apn doInBackground(Void... params) {
+ try {
+ Context context = getActivity();
+
+ if (context != null) {
+ return ApnDatabase.getInstance(context)
+ .getDefaultApnParameters(TelephonyUtil.getMccMnc(context),
+ TelephonyUtil.getApn(context));
+ }
+ } catch (IOException e) {
+ Log.w(TAG, e);
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(MmsConnection.Apn apnDefaults) {
+ ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_HOST_PREF))
+ .setValidator(new CustomDefaultPreference.UriValidator())
+ .setDefaultValue(apnDefaults.getMmsc());
+
+ ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_PROXY_HOST_PREF))
+ .setValidator(new CustomDefaultPreference.HostnameValidator())
+ .setDefaultValue(apnDefaults.getProxy());
+
+ ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_PROXY_PORT_PREF))
+ .setValidator(new CustomDefaultPreference.PortValidator())
+ .setDefaultValue(apnDefaults.getPort());
+
+ ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_USERNAME_PREF))
+ .setDefaultValue(apnDefaults.getPort());
+
+ ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_PASSWORD_PREF))
+ .setDefaultValue(apnDefaults.getPassword());
+ }
+ }
+
+}
diff --git a/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java
index 81f0c0d85e..191343097f 100644
--- a/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java
+++ b/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java
@@ -15,7 +15,6 @@ import android.support.v4.preference.PreferenceFragment;
import android.text.TextUtils;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
-import org.thoughtcrime.securesms.MmsPreferencesFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.OutgoingSmsPreference;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -46,8 +45,6 @@ public class SmsMmsPreferenceFragment extends PreferenceFragment {
public void onResume() {
super.onResume();
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__sms_mms);
- this.findPreference(MMS_PREF)
- .setSummary(MmsPreferencesFragment.getSummary(getActivity()));
initializePlatformSpecificOptions();
}
diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
index 6082af1d5a..5dbb6d145c 100644
--- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
+++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
@@ -15,10 +15,15 @@ public class TextSecurePreferences {
public static final String DISABLE_PASSPHRASE_PREF = "pref_disable_passphrase";
public static final String THEME_PREF = "pref_theme";
public static final String LANGUAGE_PREF = "pref_language";
+ private static final String MMSC_CUSTOM_HOST_PREF = "pref_apn_mmsc_custom_host";
public static final String MMSC_HOST_PREF = "pref_apn_mmsc_host";
+ private static final String MMSC_CUSTOM_PROXY_PREF = "pref_apn_mms_custom_proxy";
public static final String MMSC_PROXY_HOST_PREF = "pref_apn_mms_proxy";
+ private static final String MMSC_CUSTOM_PROXY_PORT_PREF = "pref_apn_mms_custom_proxy_port";
public static final String MMSC_PROXY_PORT_PREF = "pref_apn_mms_proxy_port";
+ private static final String MMSC_CUSTOM_USERNAME_PREF = "pref_apn_mmsc_custom_username";
public static final String MMSC_USERNAME_PREF = "pref_apn_mmsc_username";
+ private static final String MMSC_CUSTOM_PASSWORD_PREF = "pref_apn_mmsc_custom_password";
public static final String MMSC_PASSWORD_PREF = "pref_apn_mmsc_password";
public static final String THREAD_TRIM_LENGTH = "pref_trim_length";
public static final String THREAD_TRIM_NOW = "pref_trim_now";
@@ -206,26 +211,91 @@ public class TextSecurePreferences {
setBooleanPreference(context, DISABLE_PASSPHRASE_PREF, disabled);
}
+ public static boolean getUseCustomMmsc(Context context) {
+ boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context);
+ return getBooleanPreference(context, MMSC_CUSTOM_HOST_PREF, legacy);
+ }
+
+ public static void setUseCustomMmsc(Context context, boolean value) {
+ setBooleanPreference(context, MMSC_CUSTOM_HOST_PREF, value);
+ }
+
public static String getMmscUrl(Context context) {
return getStringPreference(context, MMSC_HOST_PREF, "");
}
+ public static void setMmscUrl(Context context, String mmsc) {
+ setStringPreference(context, MMSC_HOST_PREF, mmsc);
+ }
+
+ public static boolean getUseCustomMmscProxy(Context context) {
+ boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context);
+ return getBooleanPreference(context, MMSC_CUSTOM_PROXY_PREF, legacy);
+ }
+
+ public static void setUseCustomMmscProxy(Context context, boolean value) {
+ setBooleanPreference(context, MMSC_CUSTOM_PROXY_PREF, value);
+ }
+
public static String getMmscProxy(Context context) {
return getStringPreference(context, MMSC_PROXY_HOST_PREF, "");
}
+ public static void setMmscProxy(Context context, String value) {
+ setStringPreference(context, MMSC_PROXY_HOST_PREF, value);
+ }
+
+ public static boolean getUseCustomMmscProxyPort(Context context) {
+ boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context);
+ return getBooleanPreference(context, MMSC_CUSTOM_PROXY_PORT_PREF, legacy);
+ }
+
+ public static void setUseCustomMmscProxyPort(Context context, boolean value) {
+ setBooleanPreference(context, MMSC_CUSTOM_PROXY_PORT_PREF, value);
+ }
+
public static String getMmscProxyPort(Context context) {
return getStringPreference(context, MMSC_PROXY_PORT_PREF, "");
}
+ public static void setMmscProxyPort(Context context, String value) {
+ setStringPreference(context, MMSC_PROXY_PORT_PREF, value);
+ }
+
+ public static boolean getUseCustomMmscUsername(Context context) {
+ boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context);
+ return getBooleanPreference(context, MMSC_CUSTOM_USERNAME_PREF, legacy);
+ }
+
+ public static void setUseCustomMmscUsername(Context context, boolean value) {
+ setBooleanPreference(context, MMSC_CUSTOM_USERNAME_PREF, value);
+ }
+
public static String getMmscUsername(Context context) {
return getStringPreference(context, MMSC_USERNAME_PREF, "");
}
+ public static void setMmscUsername(Context context, String value) {
+ setStringPreference(context, MMSC_USERNAME_PREF, value);
+ }
+
+ public static boolean getUseCustomMmscPassword(Context context) {
+ boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context);
+ return getBooleanPreference(context, MMSC_CUSTOM_PASSWORD_PREF, legacy);
+ }
+
+ public static void setUseCustomMmscPassword(Context context, boolean value) {
+ setBooleanPreference(context, MMSC_CUSTOM_PASSWORD_PREF, value);
+ }
+
public static String getMmscPassword(Context context) {
return getStringPreference(context, MMSC_PASSWORD_PREF, "");
}
+ public static void setMmscPassword(Context context, String value) {
+ setStringPreference(context, MMSC_PASSWORD_PREF, value);
+ }
+
public static String getIdentityContactUri(Context context) {
return getStringPreference(context, IDENTITY_PREF, null);
}
@@ -242,14 +312,10 @@ public class TextSecurePreferences {
return getBooleanPreference(context, SCREEN_SECURITY_PREF, true);
}
- public static boolean isUseLocalApnsEnabled(Context context) {
+ public static boolean isLegacyUseLocalApnsEnabled(Context context) {
return getBooleanPreference(context, ENABLE_MANUAL_MMS_PREF, false);
}
- public static void setUseLocalApnsEnabled(Context context, boolean useLocal) {
- setBooleanPreference(context, ENABLE_MANUAL_MMS_PREF, useLocal);
- }
-
public static int getLastVersionCode(Context context) {
return getIntegerPreference(context, LAST_VERSION_CODE_PREF, 0);
}
@@ -373,11 +439,11 @@ public class TextSecurePreferences {
setLongPreference(context, PUSH_REGISTRATION_REMINDER_PREF, time);
}
- private static void setBooleanPreference(Context context, String key, boolean value) {
+ public static void setBooleanPreference(Context context, String key, boolean value) {
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply();
}
- private static boolean getBooleanPreference(Context context, String key, boolean defaultValue) {
+ public static boolean getBooleanPreference(Context context, String key, boolean defaultValue) {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(key, defaultValue);
}
@@ -385,7 +451,7 @@ public class TextSecurePreferences {
PreferenceManager.getDefaultSharedPreferences(context).edit().putString(key, value).apply();
}
- private static String getStringPreference(Context context, String key, String defaultValue) {
+ public static String getStringPreference(Context context, String key, String defaultValue) {
return PreferenceManager.getDefaultSharedPreferences(context).getString(key, defaultValue);
}