diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 47d1a9fb5..b605c730a 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -93,6 +93,7 @@
Show alerts for forum posts
Vibrate
Sound
- Default ringtone
- No sound
+ Default ringtone
+ None
+ Choose ringtone
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
index 8167de5a4..708c74b58 100644
--- a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
+++ b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
@@ -2,6 +2,7 @@ package org.briarproject.android;
import static android.app.Notification.DEFAULT_LIGHTS;
import static android.app.Notification.DEFAULT_SOUND;
+import static android.app.Notification.DEFAULT_VIBRATE;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
@@ -30,12 +31,13 @@ import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.SettingsUpdatedEvent;
import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.messaging.GroupId;
+import org.briarproject.util.StringUtils;
import android.app.Application;
-import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
@@ -126,6 +128,10 @@ Service, EventListener {
b.setContentText(appContext.getResources().getQuantityString(
R.plurals.private_message_notification_text, privateTotal,
privateTotal));
+ boolean sound = settings.getBoolean("notifySound", true);
+ String ringtoneUri = settings.get("notifyRingtoneUri");
+ if(sound && !StringUtils.isNullOrEmpty(ringtoneUri))
+ b.setSound(Uri.parse(ringtoneUri));
b.setDefaults(getDefaults());
b.setOnlyAlertOnce(true);
b.setAutoCancel(true);
@@ -161,10 +167,12 @@ Service, EventListener {
private int getDefaults() {
int defaults = DEFAULT_LIGHTS;
- if(settings.getBoolean("notifySound", true))
+ boolean sound = settings.getBoolean("notifySound", true);
+ String ringtoneUri = settings.get("notifyRingtoneUri");
+ if(sound && StringUtils.isNullOrEmpty(ringtoneUri))
defaults |= DEFAULT_SOUND;
if(settings.getBoolean("notifyVibration", true))
- defaults |= Notification.DEFAULT_VIBRATE;
+ defaults |= DEFAULT_VIBRATE;
return defaults;
}
@@ -197,6 +205,9 @@ Service, EventListener {
b.setContentText(appContext.getResources().getQuantityString(
R.plurals.group_post_notification_text, groupTotal,
groupTotal));
+ String ringtoneUri = settings.get("notifyRingtoneUri");
+ if(!StringUtils.isNullOrEmpty(ringtoneUri))
+ b.setSound(Uri.parse(ringtoneUri));
b.setDefaults(getDefaults());
b.setOnlyAlertOnce(true);
b.setAutoCancel(true);
diff --git a/briar-android/src/org/briarproject/android/SettingsActivity.java b/briar-android/src/org/briarproject/android/SettingsActivity.java
index 02aca849d..f5f4e8236 100644
--- a/briar-android/src/org/briarproject/android/SettingsActivity.java
+++ b/briar-android/src/org/briarproject/android/SettingsActivity.java
@@ -1,6 +1,15 @@
package org.briarproject.android;
import static android.graphics.Typeface.DEFAULT_BOLD;
+import static android.media.RingtoneManager.ACTION_RINGTONE_PICKER;
+import static android.media.RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI;
+import static android.media.RingtoneManager.EXTRA_RINGTONE_EXISTING_URI;
+import static android.media.RingtoneManager.EXTRA_RINGTONE_PICKED_URI;
+import static android.media.RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT;
+import static android.media.RingtoneManager.EXTRA_RINGTONE_TITLE;
+import static android.media.RingtoneManager.EXTRA_RINGTONE_TYPE;
+import static android.media.RingtoneManager.TYPE_NOTIFICATION;
+import static android.provider.Settings.System.DEFAULT_NOTIFICATION_URI;
import static android.view.Gravity.CENTER;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
@@ -28,10 +37,14 @@ import org.briarproject.api.db.DbException;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.SettingsUpdatedEvent;
+import org.briarproject.util.StringUtils;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.res.Resources;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
@@ -44,6 +57,8 @@ import android.widget.TextView;
public class SettingsActivity extends BriarActivity implements EventListener,
OnClickListener {
+ public static final int REQUEST_RINGTONE = 2;
+
private static final Logger LOG =
Logger.getLogger(SettingsActivity.class.getName());
@@ -54,10 +69,11 @@ OnClickListener {
private TextView notifySound = null, notifySoundHint = null;
private ListLoadingProgressBar progress = null;
private ImageButton testingButton = null;
- private boolean bluetoothSetting = true, soundSetting = true;
// Fields that are accessed from background threads must be volatile
@Inject private volatile DatabaseComponent db;
+ private volatile Settings settings;
+ private volatile boolean bluetoothSetting = true;
@Override
public void onCreate(Bundle state) {
@@ -96,7 +112,6 @@ OnClickListener {
enableBluetoothHint = new TextView(this);
enableBluetoothHint.setPadding(pad, 0, pad, pad);
- enableBluetoothHint.setText(R.string.bluetooth_setting_enabled);
enableBluetoothHint.setOnClickListener(this);
settings.addView(enableBluetoothHint);
@@ -116,7 +131,6 @@ OnClickListener {
notifyPrivateMessages = new CheckBox(this);
notifyPrivateMessages.setTextSize(18);
notifyPrivateMessages.setText(R.string.notify_private_messages_setting);
- notifyPrivateMessages.setChecked(true);
notifyPrivateMessages.setOnClickListener(this);
settings.addView(notifyPrivateMessages);
@@ -127,7 +141,6 @@ OnClickListener {
notifyGroupPosts = new CheckBox(this);
notifyGroupPosts.setTextSize(18);
notifyGroupPosts.setText(R.string.notify_group_posts_setting);
- notifyGroupPosts.setChecked(true);
notifyGroupPosts.setOnClickListener(this);
settings.addView(notifyGroupPosts);
@@ -153,7 +166,6 @@ OnClickListener {
notifySoundHint = new TextView(this);
notifySoundHint.setPadding(pad, 0, pad, pad);
- notifySoundHint.setText(R.string.notify_sound_setting_enabled);
notifySoundHint.setOnClickListener(this);
settings.addView(notifySoundHint);
@@ -173,7 +185,8 @@ OnClickListener {
LinearLayout footer = new LinearLayout(this);
footer.setLayoutParams(MATCH_WRAP);
footer.setGravity(CENTER);
- footer.setBackgroundColor(res.getColor(R.color.button_bar_background));
+ int background = res.getColor(R.color.button_bar_background);
+ footer.setBackgroundColor(background);
testingButton = new ImageButton(this);
testingButton.setBackgroundResource(0);
testingButton.setImageResource(R.drawable.action_about);
@@ -198,12 +211,12 @@ OnClickListener {
try {
long now = System.currentTimeMillis();
TransportConfig c = db.getConfig(new TransportId("bt"));
- Settings settings = db.getSettings();
+ settings = db.getSettings();
long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO))
LOG.info("Loading settings took " + duration + " ms");
- boolean btSetting = c.getBoolean("enable", true);
- displaySettings(btSetting, settings);
+ bluetoothSetting = c.getBoolean("enable", true);
+ displaySettings();
} catch(DbException e) {
if(LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
@@ -212,14 +225,12 @@ OnClickListener {
});
}
- private void displaySettings(final boolean btSetting,
- final Settings settings) {
+ private void displaySettings() {
runOnUiThread(new Runnable() {
public void run() {
scroll.setVisibility(VISIBLE);
progress.setVisibility(GONE);
- bluetoothSetting = btSetting;
int resId;
if(bluetoothSetting) resId = R.string.bluetooth_setting_enabled;
else resId = R.string.bluetooth_setting_disabled;
@@ -234,10 +245,16 @@ OnClickListener {
notifyVibration.setChecked(settings.getBoolean(
"notifyVibration", true));
- soundSetting = settings.getBoolean("notifySound", true);
- if(soundSetting) resId = R.string.notify_sound_setting_enabled;
- else resId = R.string.notify_sound_setting_disabled;
- notifySoundHint.setText(resId);
+ String text;
+ if(settings.getBoolean("notifySound", true)) {
+ String ringtoneName = settings.get("notifyRingtoneName");
+ if(StringUtils.isNullOrEmpty(ringtoneName))
+ text = getString(R.string.notify_sound_setting_default);
+ else text = ringtoneName;
+ } else {
+ text = getString(R.string.notify_sound_setting_disabled);
+ }
+ notifySoundHint.setText(text);
}
});
}
@@ -252,42 +269,58 @@ OnClickListener {
if(progress == null) return; // Not created yet
if(view == testingButton) {
startActivity(new Intent(this, TestingActivity.class));
- return;
- }
- if(view == enableBluetooth || view == enableBluetoothHint) {
+ } else if(view == enableBluetooth || view == enableBluetoothHint) {
bluetoothSetting = !bluetoothSetting;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if(adapter != null) {
if(bluetoothSetting) adapter.enable();
else adapter.disable();
}
+ storeBluetoothSetting();
+ return;
+ } else if(view == notifyPrivateMessages) {
+ Settings s = new Settings();
+ s.putBoolean("notifyPrivateMessages",
+ notifyPrivateMessages.isChecked());
+ storeSettings(s);
+ } else if(view == notifyGroupPosts) {
+ Settings s = new Settings();
+ s.putBoolean("notifyGroupPosts", notifyGroupPosts.isChecked());
+ storeSettings(s);
+ } else if(view == notifyVibration) {
+ Settings s = new Settings();
+ s.putBoolean("notifyVibration", notifyVibration.isChecked());
+ storeSettings(s);
} else if(view == notifySound || view == notifySoundHint) {
- soundSetting = !soundSetting;
+ String title = getString(R.string.choose_ringtone_title);
+ Intent i = new Intent(ACTION_RINGTONE_PICKER);
+ i.putExtra(EXTRA_RINGTONE_TYPE, TYPE_NOTIFICATION);
+ i.putExtra(EXTRA_RINGTONE_TITLE, title);
+ i.putExtra(EXTRA_RINGTONE_DEFAULT_URI, DEFAULT_NOTIFICATION_URI);
+ i.putExtra(EXTRA_RINGTONE_SHOW_SILENT, true);
+ if(settings.getBoolean("notifySound", true)) {
+ Uri uri;
+ String ringtoneUri = settings.get("notifyRingtoneUri");
+ if(StringUtils.isNullOrEmpty(ringtoneUri))
+ uri = DEFAULT_NOTIFICATION_URI;
+ else uri = Uri.parse(ringtoneUri);
+ i.putExtra(EXTRA_RINGTONE_EXISTING_URI, uri);
+ }
+ this.startActivityForResult(i, REQUEST_RINGTONE);
}
- Settings settings = new Settings();
- settings.putBoolean("notifyPrivateMessages",
- notifyPrivateMessages.isChecked());
- settings.putBoolean("notifyGroupPosts",
- notifyGroupPosts.isChecked());
- settings.putBoolean("notifyVibration",
- notifyVibration.isChecked());
- settings.putBoolean("notifySound", soundSetting);
- storeSettings(bluetoothSetting, settings);
}
- private void storeSettings(final boolean btSetting,
- final Settings settings) {
+ private void storeBluetoothSetting() {
runOnDbThread(new Runnable() {
public void run() {
try {
TransportConfig c = new TransportConfig();
- c.putBoolean("enable", btSetting);
+ c.putBoolean("enable", bluetoothSetting);
long now = System.currentTimeMillis();
db.mergeConfig(new TransportId("bt"), c);
- db.mergeSettings(settings);
long duration = System.currentTimeMillis() - now;
if(LOG.isLoggable(INFO))
- LOG.info("Storing settings took " + duration + " ms");
+ LOG.info("Merging config took " + duration + " ms");
} catch(DbException e) {
if(LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
@@ -296,6 +329,54 @@ OnClickListener {
});
}
+ private void storeSettings(final Settings settings) {
+ runOnDbThread(new Runnable() {
+ public void run() {
+ try {
+ long now = System.currentTimeMillis();
+ db.mergeSettings(settings);
+ long duration = System.currentTimeMillis() - now;
+ if(LOG.isLoggable(INFO))
+ LOG.info("Merging settings took " + duration + " ms");
+ } catch(DbException e) {
+ if(LOG.isLoggable(WARNING))
+ LOG.log(WARNING, e.toString(), e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onActivityResult(int request, int result, Intent data) {
+ super.onActivityResult(request, result, data);
+ if(request == REQUEST_RINGTONE && result == RESULT_OK) {
+ Settings s = new Settings();
+ Uri uri = data.getParcelableExtra(EXTRA_RINGTONE_PICKED_URI);
+ if(uri == null) {
+ // The user chose silence
+ notifySoundHint.setText(R.string.notify_sound_setting_disabled);
+ s.putBoolean("notifySound", false);
+ s.put("notifyRingtoneName", "");
+ s.put("notifyRingtoneUri", "");
+ } else if(RingtoneManager.isDefault(uri)) {
+ // The user chose the default
+ notifySoundHint.setText(R.string.notify_sound_setting_default);
+ s.putBoolean("notifySound", true);
+ s.put("notifyRingtoneName", "");
+ s.put("notifyRingtoneUri", "");
+ } else {
+ // The user chose a ringtone other than the default
+ Ringtone r = RingtoneManager.getRingtone(this, uri);
+ String name = r.getTitle(this);
+ notifySoundHint.setText(name);
+ s.putBoolean("notifySound", true);
+ s.put("notifyRingtoneName", name);
+ s.put("notifyRingtoneUri", uri.toString());
+ }
+ storeSettings(s);
+ }
+ }
+
public void eventOccurred(Event e) {
if(e instanceof SettingsUpdatedEvent) {
LOG.info("Settings updated");