From adf9adf1afc990351cbe60e5155db713af9d8a59 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Fri, 2 May 2014 14:08:46 +0100
Subject: [PATCH] More ringtones! Your wish is our command.

---
 briar-android/res/values/strings.xml          |   5 +-
 .../AndroidNotificationManagerImpl.java       |  17 +-
 .../android/SettingsActivity.java             | 147 ++++++++++++++----
 3 files changed, 131 insertions(+), 38 deletions(-)

diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 47d1a9fb58..b605c730a5 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -93,6 +93,7 @@
     <string name="notify_group_posts_setting">Show alerts for forum posts</string>
     <string name="notify_vibration_setting">Vibrate</string>
     <string name="notify_sound_setting">Sound</string>
-    <string name="notify_sound_setting_enabled">Default ringtone</string>
-    <string name="notify_sound_setting_disabled">No sound</string>
+    <string name="notify_sound_setting_default">Default ringtone</string>
+    <string name="notify_sound_setting_disabled">None</string>
+    <string name="choose_ringtone_title">Choose ringtone</string>
 </resources>
\ 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 8167de5a4f..708c74b58c 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 02aca849d3..f5f4e8236a 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,75 @@ 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);
+					long duration = System.currentTimeMillis() - now;
+					if(LOG.isLoggable(INFO))
+						LOG.info("Merging config took " + duration + " ms");
+				} catch(DbException e) {
+					if(LOG.isLoggable(WARNING))
+						LOG.log(WARNING, e.toString(), e);
+				}
+			}
+		});
+	}
+
+	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("Storing settings took " + duration + " ms");
+						LOG.info("Merging settings took " + duration + " ms");
 				} catch(DbException e) {
 					if(LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
@@ -296,6 +346,37 @@ OnClickListener {
 		});
 	}
 
+	@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");
-- 
GitLab