mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 14:19:53 +01:00
Notification settings. Dev task #76.
This commit is contained in:
@@ -11,4 +11,6 @@
|
|||||||
<color name="horizontal_border">#CCCCCC</color>
|
<color name="horizontal_border">#CCCCCC</color>
|
||||||
<color name="groups_available_background">#FCCF1C</color>
|
<color name="groups_available_background">#FCCF1C</color>
|
||||||
<color name="no_posts">#AAAAAA</color>
|
<color name="no_posts">#AAAAAA</color>
|
||||||
|
<color name="settings_title_text">#2D3E50</color>
|
||||||
|
<color name="settings_title_underline">#2D3E50</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -85,6 +85,15 @@
|
|||||||
<item quantity="other">%d new forum posts.</item>
|
<item quantity="other">%d new forum posts.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="settings_title">Settings</string>
|
<string name="settings_title">Settings</string>
|
||||||
<string name="activate_bluetooth_option">Activate Bluetooth while signed in</string>
|
<string name="bluetooth_setting_title">BLUETOOTH</string>
|
||||||
<string name="activate_bluetooth_explanation">Briar uses Bluetooth to communicate with nearby contacts</string>
|
<string name="bluetooth_setting">Turn on Bluetooth</string>
|
||||||
|
<string name="bluetooth_setting_enabled">While signed in</string>
|
||||||
|
<string name="bluetooth_setting_disabled">Only when adding contacts</string>
|
||||||
|
<string name="notification_settings_title">NOTIFICATIONS</string>
|
||||||
|
<string name="notify_private_messages_setting">Show alerts for private messages</string>
|
||||||
|
<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>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -60,8 +60,6 @@ public class AndroidModule extends AbstractModule {
|
|||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(AndroidExecutor.class).to(AndroidExecutorImpl.class).in(
|
bind(AndroidExecutor.class).to(AndroidExecutorImpl.class).in(
|
||||||
Singleton.class);
|
Singleton.class);
|
||||||
bind(AndroidNotificationManager.class).to(
|
|
||||||
AndroidNotificationManagerImpl.class).in(Singleton.class);
|
|
||||||
bind(ReferenceManager.class).to(ReferenceManagerImpl.class).in(
|
bind(ReferenceManager.class).to(ReferenceManagerImpl.class).in(
|
||||||
Singleton.class);
|
Singleton.class);
|
||||||
bind(UiCallback.class).toInstance(uiCallback);
|
bind(UiCallback.class).toInstance(uiCallback);
|
||||||
@@ -101,4 +99,12 @@ public class AndroidModule extends AbstractModule {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides @Singleton
|
||||||
|
AndroidNotificationManager getAndroidNotificationManager(
|
||||||
|
LifecycleManager lifecycleManager,
|
||||||
|
AndroidNotificationManagerImpl notificationManager) {
|
||||||
|
lifecycleManager.register(notificationManager);
|
||||||
|
return notificationManager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
package org.briarproject.android;
|
package org.briarproject.android;
|
||||||
|
|
||||||
import static android.app.Notification.DEFAULT_ALL;
|
import static android.app.Notification.DEFAULT_LIGHTS;
|
||||||
|
import static android.app.Notification.DEFAULT_SOUND;
|
||||||
|
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
|
||||||
import static android.content.Context.NOTIFICATION_SERVICE;
|
import static android.content.Context.NOTIFICATION_SERVICE;
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -16,21 +21,36 @@ import org.briarproject.android.contact.ConversationActivity;
|
|||||||
import org.briarproject.android.groups.GroupActivity;
|
import org.briarproject.android.groups.GroupActivity;
|
||||||
import org.briarproject.android.groups.GroupListActivity;
|
import org.briarproject.android.groups.GroupListActivity;
|
||||||
import org.briarproject.api.ContactId;
|
import org.briarproject.api.ContactId;
|
||||||
|
import org.briarproject.api.Settings;
|
||||||
import org.briarproject.api.android.AndroidNotificationManager;
|
import org.briarproject.api.android.AndroidNotificationManager;
|
||||||
|
import org.briarproject.api.android.DatabaseUiExecutor;
|
||||||
|
import org.briarproject.api.db.DatabaseComponent;
|
||||||
|
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.api.lifecycle.Service;
|
||||||
import org.briarproject.api.messaging.GroupId;
|
import org.briarproject.api.messaging.GroupId;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
|
|
||||||
class AndroidNotificationManagerImpl implements AndroidNotificationManager {
|
class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||||
|
Service, EventListener {
|
||||||
|
|
||||||
private static final int PRIVATE_MESSAGE_NOTIFICATION_ID = 3;
|
private static final int PRIVATE_MESSAGE_NOTIFICATION_ID = 3;
|
||||||
private static final int GROUP_POST_NOTIFICATION_ID = 4;
|
private static final int GROUP_POST_NOTIFICATION_ID = 4;
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(AndroidNotificationManagerImpl.class.getName());
|
||||||
|
|
||||||
|
private final DatabaseComponent db;
|
||||||
|
private final Executor dbUiExecutor;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
private final Map<ContactId, Integer> contactCounts =
|
private final Map<ContactId, Integer> contactCounts =
|
||||||
new HashMap<ContactId, Integer>(); // Locking: this
|
new HashMap<ContactId, Integer>(); // Locking: this
|
||||||
@@ -39,9 +59,42 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager {
|
|||||||
|
|
||||||
private int privateTotal = 0, groupTotal = 0; // Locking: this
|
private int privateTotal = 0, groupTotal = 0; // Locking: this
|
||||||
|
|
||||||
|
private volatile Settings settings = new Settings();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AndroidNotificationManagerImpl(Application app) {
|
public AndroidNotificationManagerImpl(DatabaseComponent db,
|
||||||
this.appContext = app.getApplicationContext();
|
@DatabaseUiExecutor Executor dbExecutor, Application app) {
|
||||||
|
this.db = db;
|
||||||
|
this.dbUiExecutor = dbExecutor;
|
||||||
|
appContext = app.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean start() {
|
||||||
|
db.addListener(this);
|
||||||
|
loadSettings();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSettings() {
|
||||||
|
dbUiExecutor.execute(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
settings = db.getSettings();
|
||||||
|
} catch(DbException e) {
|
||||||
|
if(LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean stop() {
|
||||||
|
db.removeListener(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if(e instanceof SettingsUpdatedEvent) loadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void showPrivateMessageNotification(ContactId c) {
|
public synchronized void showPrivateMessageNotification(ContactId c) {
|
||||||
@@ -63,6 +116,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager {
|
|||||||
private void updatePrivateMessageNotification() {
|
private void updatePrivateMessageNotification() {
|
||||||
if(privateTotal == 0) {
|
if(privateTotal == 0) {
|
||||||
clearPrivateMessageNotification();
|
clearPrivateMessageNotification();
|
||||||
|
} else if(!settings.getBoolean("notifyPrivateMessages", true)) {
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
NotificationCompat.Builder b =
|
NotificationCompat.Builder b =
|
||||||
new NotificationCompat.Builder(appContext);
|
new NotificationCompat.Builder(appContext);
|
||||||
@@ -71,24 +126,24 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager {
|
|||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.private_message_notification_text, privateTotal,
|
R.plurals.private_message_notification_text, privateTotal,
|
||||||
privateTotal));
|
privateTotal));
|
||||||
b.setDefaults(DEFAULT_ALL);
|
b.setDefaults(getDefaults());
|
||||||
b.setOnlyAlertOnce(true);
|
b.setOnlyAlertOnce(true);
|
||||||
if(contactCounts.size() == 1) {
|
if(contactCounts.size() == 1) {
|
||||||
Intent i = new Intent(appContext, ConversationActivity.class);
|
Intent i = new Intent(appContext, ConversationActivity.class);
|
||||||
ContactId c = contactCounts.keySet().iterator().next();
|
ContactId c = contactCounts.keySet().iterator().next();
|
||||||
i.putExtra("briar.CONTACT_ID", c.getInt());
|
i.putExtra("briar.CONTACT_ID", c.getInt());
|
||||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
TaskStackBuilder tsb = TaskStackBuilder.create(appContext);
|
TaskStackBuilder t = TaskStackBuilder.create(appContext);
|
||||||
tsb.addParentStack(ConversationActivity.class);
|
t.addParentStack(ConversationActivity.class);
|
||||||
tsb.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(tsb.getPendingIntent(0, 0));
|
b.setContentIntent(t.getPendingIntent(0, FLAG_UPDATE_CURRENT));
|
||||||
} else {
|
} else {
|
||||||
Intent i = new Intent(appContext, ContactListActivity.class);
|
Intent i = new Intent(appContext, ContactListActivity.class);
|
||||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
TaskStackBuilder tsb = TaskStackBuilder.create(appContext);
|
TaskStackBuilder t = TaskStackBuilder.create(appContext);
|
||||||
tsb.addParentStack(ContactListActivity.class);
|
t.addParentStack(ContactListActivity.class);
|
||||||
tsb.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(tsb.getPendingIntent(0, 0));
|
b.setContentIntent(t.getPendingIntent(0, FLAG_UPDATE_CURRENT));
|
||||||
}
|
}
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
@@ -103,6 +158,15 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager {
|
|||||||
nm.cancel(PRIVATE_MESSAGE_NOTIFICATION_ID);
|
nm.cancel(PRIVATE_MESSAGE_NOTIFICATION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getDefaults() {
|
||||||
|
int defaults = DEFAULT_LIGHTS;
|
||||||
|
if(settings.getBoolean("notifySound", true))
|
||||||
|
defaults |= DEFAULT_SOUND;
|
||||||
|
if(settings.getBoolean("notifyVibration", true))
|
||||||
|
defaults |= Notification.DEFAULT_VIBRATE;
|
||||||
|
return defaults;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void showGroupPostNotification(GroupId g) {
|
public synchronized void showGroupPostNotification(GroupId g) {
|
||||||
Integer count = groupCounts.get(g);
|
Integer count = groupCounts.get(g);
|
||||||
if(count == null) groupCounts.put(g, 1);
|
if(count == null) groupCounts.put(g, 1);
|
||||||
@@ -122,6 +186,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager {
|
|||||||
private void updateGroupPostNotification() {
|
private void updateGroupPostNotification() {
|
||||||
if(groupTotal == 0) {
|
if(groupTotal == 0) {
|
||||||
clearGroupPostNotification();
|
clearGroupPostNotification();
|
||||||
|
} else if(!settings.getBoolean("notifyGroupPosts", true)) {
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
NotificationCompat.Builder b =
|
NotificationCompat.Builder b =
|
||||||
new NotificationCompat.Builder(appContext);
|
new NotificationCompat.Builder(appContext);
|
||||||
@@ -130,24 +196,24 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager {
|
|||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.group_post_notification_text, groupTotal,
|
R.plurals.group_post_notification_text, groupTotal,
|
||||||
groupTotal));
|
groupTotal));
|
||||||
b.setDefaults(DEFAULT_ALL);
|
b.setDefaults(getDefaults());
|
||||||
b.setOnlyAlertOnce(true);
|
b.setOnlyAlertOnce(true);
|
||||||
if(groupCounts.size() == 1) {
|
if(groupCounts.size() == 1) {
|
||||||
Intent i = new Intent(appContext, GroupActivity.class);
|
Intent i = new Intent(appContext, GroupActivity.class);
|
||||||
GroupId g = groupCounts.keySet().iterator().next();
|
GroupId g = groupCounts.keySet().iterator().next();
|
||||||
i.putExtra("briar.GROUP_ID", g.getBytes());
|
i.putExtra("briar.GROUP_ID", g.getBytes());
|
||||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
TaskStackBuilder tsb = TaskStackBuilder.create(appContext);
|
TaskStackBuilder t = TaskStackBuilder.create(appContext);
|
||||||
tsb.addParentStack(GroupActivity.class);
|
t.addParentStack(GroupActivity.class);
|
||||||
tsb.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(tsb.getPendingIntent(0, 0));
|
b.setContentIntent(t.getPendingIntent(0, FLAG_UPDATE_CURRENT));
|
||||||
} else {
|
} else {
|
||||||
Intent i = new Intent(appContext, GroupListActivity.class);
|
Intent i = new Intent(appContext, GroupListActivity.class);
|
||||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
TaskStackBuilder tsb = TaskStackBuilder.create(appContext);
|
TaskStackBuilder t = TaskStackBuilder.create(appContext);
|
||||||
tsb.addParentStack(GroupListActivity.class);
|
t.addParentStack(GroupListActivity.class);
|
||||||
tsb.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(tsb.getPendingIntent(0, 0));
|
b.setContentIntent(t.getPendingIntent(0, FLAG_UPDATE_CURRENT));
|
||||||
}
|
}
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
|
|||||||
@@ -95,9 +95,7 @@ public class PasswordActivity extends RoboActivity {
|
|||||||
layout.addView(passwordEntry);
|
layout.addView(passwordEntry);
|
||||||
|
|
||||||
// Adjusting the padding of buttons and EditTexts has the wrong results
|
// Adjusting the padding of buttons and EditTexts has the wrong results
|
||||||
FixedVerticalSpace space = new FixedVerticalSpace(this);
|
layout.addView(new FixedVerticalSpace(this));
|
||||||
space.setHeight(pad);
|
|
||||||
layout.addView(space);
|
|
||||||
|
|
||||||
continueButton = new Button(this);
|
continueButton = new Button(this);
|
||||||
continueButton.setLayoutParams(WRAP_WRAP);
|
continueButton.setLayoutParams(WRAP_WRAP);
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package org.briarproject.android;
|
package org.briarproject.android;
|
||||||
|
|
||||||
|
import static android.graphics.Typeface.DEFAULT_BOLD;
|
||||||
import static android.view.Gravity.CENTER;
|
import static android.view.Gravity.CENTER;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static android.widget.LinearLayout.VERTICAL;
|
import static android.widget.LinearLayout.VERTICAL;
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
|
import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
|
||||||
import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
|
import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
|
||||||
@@ -16,10 +18,14 @@ import org.briarproject.R;
|
|||||||
import org.briarproject.android.util.HorizontalBorder;
|
import org.briarproject.android.util.HorizontalBorder;
|
||||||
import org.briarproject.android.util.LayoutUtils;
|
import org.briarproject.android.util.LayoutUtils;
|
||||||
import org.briarproject.android.util.ListLoadingProgressBar;
|
import org.briarproject.android.util.ListLoadingProgressBar;
|
||||||
|
import org.briarproject.api.Settings;
|
||||||
import org.briarproject.api.TransportConfig;
|
import org.briarproject.api.TransportConfig;
|
||||||
import org.briarproject.api.TransportId;
|
import org.briarproject.api.TransportId;
|
||||||
import org.briarproject.api.db.DatabaseComponent;
|
import org.briarproject.api.db.DatabaseComponent;
|
||||||
import org.briarproject.api.db.DbException;
|
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 android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -33,15 +39,20 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
public class SettingsActivity extends BriarActivity implements OnClickListener {
|
public class SettingsActivity extends BriarActivity implements EventListener,
|
||||||
|
OnClickListener {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(SettingsActivity.class.getName());
|
Logger.getLogger(SettingsActivity.class.getName());
|
||||||
|
|
||||||
private CheckBox bluetooth = null;
|
|
||||||
private ScrollView scroll = null;
|
private ScrollView scroll = null;
|
||||||
|
private TextView enableBluetooth = null, enableBluetoothHint = null;
|
||||||
|
private CheckBox notifyPrivateMessages = null, notifyGroupPosts = null;
|
||||||
|
private CheckBox notifyVibration = null;
|
||||||
|
private TextView notifySound = null, notifySoundHint = null;
|
||||||
private ListLoadingProgressBar progress = null;
|
private ListLoadingProgressBar progress = null;
|
||||||
private ImageButton testingButton = null;
|
private ImageButton testingButton = null;
|
||||||
|
private boolean bluetoothSetting = true, soundSetting = true;
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
@Inject private volatile DatabaseComponent db;
|
@Inject private volatile DatabaseComponent db;
|
||||||
@@ -60,16 +71,87 @@ public class SettingsActivity extends BriarActivity implements OnClickListener {
|
|||||||
int pad = LayoutUtils.getPadding(this);
|
int pad = LayoutUtils.getPadding(this);
|
||||||
settings.setPadding(pad, pad, pad, pad);
|
settings.setPadding(pad, pad, pad, pad);
|
||||||
|
|
||||||
bluetooth = new CheckBox(this);
|
TextView bluetoothTitle = new TextView(this);
|
||||||
bluetooth.setLayoutParams(MATCH_WRAP);
|
bluetoothTitle.setPadding(pad, 0, pad, 0);
|
||||||
bluetooth.setTextSize(18);
|
bluetoothTitle.setTypeface(DEFAULT_BOLD);
|
||||||
bluetooth.setText(R.string.activate_bluetooth_option);
|
Resources res = getResources();
|
||||||
bluetooth.setOnClickListener(this);
|
int titleText = res.getColor(R.color.settings_title_text);
|
||||||
settings.addView(bluetooth);
|
bluetoothTitle.setTextColor(titleText);
|
||||||
|
bluetoothTitle.setText(R.string.bluetooth_setting_title);
|
||||||
|
settings.addView(bluetoothTitle);
|
||||||
|
|
||||||
TextView bluetoothHint = new TextView(this);
|
HorizontalBorder underline = new HorizontalBorder(this);
|
||||||
bluetoothHint.setText(R.string.activate_bluetooth_explanation);
|
int titleUnderline = res.getColor(R.color.settings_title_underline);
|
||||||
settings.addView(bluetoothHint);
|
underline.setBackgroundColor(titleUnderline);
|
||||||
|
settings.addView(underline);
|
||||||
|
|
||||||
|
enableBluetooth = new TextView(this);
|
||||||
|
enableBluetooth.setPadding(pad, pad, pad, 0);
|
||||||
|
enableBluetooth.setTextSize(18);
|
||||||
|
enableBluetooth.setText(R.string.bluetooth_setting);
|
||||||
|
enableBluetooth.setOnClickListener(this);
|
||||||
|
settings.addView(enableBluetooth);
|
||||||
|
|
||||||
|
enableBluetoothHint = new TextView(this);
|
||||||
|
enableBluetoothHint.setPadding(pad, 0, pad, pad);
|
||||||
|
enableBluetoothHint.setText(R.string.bluetooth_setting_enabled);
|
||||||
|
enableBluetoothHint.setOnClickListener(this);
|
||||||
|
settings.addView(enableBluetoothHint);
|
||||||
|
|
||||||
|
TextView notificationsTitle = new TextView(this);
|
||||||
|
notificationsTitle.setPadding(pad, 0, pad, 0);
|
||||||
|
notificationsTitle.setTypeface(DEFAULT_BOLD);
|
||||||
|
notificationsTitle.setTextColor(titleText);
|
||||||
|
notificationsTitle.setText(R.string.notification_settings_title);
|
||||||
|
settings.addView(notificationsTitle);
|
||||||
|
|
||||||
|
underline = new HorizontalBorder(this);
|
||||||
|
underline.setBackgroundColor(titleUnderline);
|
||||||
|
settings.addView(underline);
|
||||||
|
|
||||||
|
notifyPrivateMessages = new CheckBox(this);
|
||||||
|
notifyPrivateMessages.setPadding(0, pad, 0, pad);
|
||||||
|
notifyPrivateMessages.setTextSize(18);
|
||||||
|
notifyPrivateMessages.setText(R.string.notify_private_messages_setting);
|
||||||
|
notifyPrivateMessages.setChecked(true);
|
||||||
|
notifyPrivateMessages.setOnClickListener(this);
|
||||||
|
settings.addView(notifyPrivateMessages);
|
||||||
|
|
||||||
|
settings.addView(new HorizontalBorder(this));
|
||||||
|
|
||||||
|
notifyGroupPosts = new CheckBox(this);
|
||||||
|
notifyGroupPosts.setPadding(0, pad, 0, pad);
|
||||||
|
notifyGroupPosts.setTextSize(18);
|
||||||
|
notifyGroupPosts.setText(R.string.notify_group_posts_setting);
|
||||||
|
notifyGroupPosts.setChecked(true);
|
||||||
|
notifyGroupPosts.setOnClickListener(this);
|
||||||
|
settings.addView(notifyGroupPosts);
|
||||||
|
|
||||||
|
settings.addView(new HorizontalBorder(this));
|
||||||
|
|
||||||
|
notifyVibration = new CheckBox(this);
|
||||||
|
notifyVibration.setPadding(0, pad, 0, pad);
|
||||||
|
notifyVibration.setTextSize(18);
|
||||||
|
notifyVibration.setText(R.string.notify_vibration_setting);
|
||||||
|
notifyVibration.setOnClickListener(this);
|
||||||
|
settings.addView(notifyVibration);
|
||||||
|
|
||||||
|
settings.addView(new HorizontalBorder(this));
|
||||||
|
|
||||||
|
notifySound = new TextView(this);
|
||||||
|
notifySound.setPadding(pad, pad, pad, 0);
|
||||||
|
notifySound.setTextSize(18);
|
||||||
|
notifySound.setText(R.string.notify_sound_setting);
|
||||||
|
notifySound.setOnClickListener(this);
|
||||||
|
settings.addView(notifySound);
|
||||||
|
|
||||||
|
notifySoundHint = new TextView(this);
|
||||||
|
notifySoundHint.setPadding(pad, 0, pad, pad);
|
||||||
|
notifySoundHint.setText(R.string.notify_sound_setting_enabled);
|
||||||
|
notifySoundHint.setOnClickListener(this);
|
||||||
|
settings.addView(notifySoundHint);
|
||||||
|
|
||||||
|
settings.addView(new HorizontalBorder(this));
|
||||||
|
|
||||||
scroll.addView(settings);
|
scroll.addView(settings);
|
||||||
scroll.setLayoutParams(MATCH_WRAP_1);
|
scroll.setLayoutParams(MATCH_WRAP_1);
|
||||||
@@ -84,7 +166,6 @@ public class SettingsActivity extends BriarActivity implements OnClickListener {
|
|||||||
LinearLayout footer = new LinearLayout(this);
|
LinearLayout footer = new LinearLayout(this);
|
||||||
footer.setLayoutParams(MATCH_WRAP);
|
footer.setLayoutParams(MATCH_WRAP);
|
||||||
footer.setGravity(CENTER);
|
footer.setGravity(CENTER);
|
||||||
Resources res = getResources();
|
|
||||||
footer.setBackgroundColor(res.getColor(R.color.button_bar_background));
|
footer.setBackgroundColor(res.getColor(R.color.button_bar_background));
|
||||||
testingButton = new ImageButton(this);
|
testingButton = new ImageButton(this);
|
||||||
testingButton.setBackgroundResource(0);
|
testingButton.setBackgroundResource(0);
|
||||||
@@ -99,6 +180,7 @@ public class SettingsActivity extends BriarActivity implements OnClickListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
db.addListener(this);
|
||||||
loadSettings();
|
loadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,11 +188,14 @@ public class SettingsActivity extends BriarActivity implements OnClickListener {
|
|||||||
runOnDbThread(new Runnable() {
|
runOnDbThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
boolean activateBluetooth = true;
|
long now = System.currentTimeMillis();
|
||||||
TransportConfig c = db.getConfig(new TransportId("bt"));
|
TransportConfig c = db.getConfig(new TransportId("bt"));
|
||||||
if(c != null && "false".equals(c.get("enable")))
|
Settings settings = db.getSettings();
|
||||||
activateBluetooth = false;
|
long duration = System.currentTimeMillis() - now;
|
||||||
displaySettings(activateBluetooth);
|
if(LOG.isLoggable(INFO))
|
||||||
|
LOG.info("Loading settings took " + duration + " ms");
|
||||||
|
boolean btSetting = c.getBoolean("enable", true);
|
||||||
|
displaySettings(btSetting, settings);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
if(LOG.isLoggable(WARNING))
|
if(LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
@@ -119,37 +204,82 @@ public class SettingsActivity extends BriarActivity implements OnClickListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displaySettings(final boolean activateBluetooth) {
|
private void displaySettings(final boolean btSetting,
|
||||||
|
final Settings settings) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
scroll.setVisibility(VISIBLE);
|
scroll.setVisibility(VISIBLE);
|
||||||
progress.setVisibility(GONE);
|
progress.setVisibility(GONE);
|
||||||
bluetooth.setChecked(activateBluetooth);
|
|
||||||
|
bluetoothSetting = btSetting;
|
||||||
|
int resId;
|
||||||
|
if(bluetoothSetting) resId = R.string.bluetooth_setting_enabled;
|
||||||
|
else resId = R.string.bluetooth_setting_disabled;
|
||||||
|
enableBluetoothHint.setText(resId);
|
||||||
|
|
||||||
|
notifyPrivateMessages.setChecked(settings.getBoolean(
|
||||||
|
"notifyPrivateMessages", true));
|
||||||
|
|
||||||
|
notifyGroupPosts.setChecked(settings.getBoolean(
|
||||||
|
"notifyGroupPosts", true));
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClick(View view) {
|
@Override
|
||||||
if(testingButton == null) return; // Not created yet
|
public void onPause() {
|
||||||
if(view == bluetooth) {
|
super.onPause();
|
||||||
boolean activateBluetooth = bluetooth.isChecked();
|
db.removeListener(this);
|
||||||
if(!activateBluetooth) {
|
|
||||||
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
if(adapter != null) adapter.disable();
|
|
||||||
}
|
|
||||||
storeSettings(activateBluetooth);
|
|
||||||
} else if(view == testingButton) {
|
|
||||||
startActivity(new Intent(this, TestingActivity.class));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeSettings(final boolean activateBluetooth) {
|
public void onClick(View view) {
|
||||||
|
if(testingButton == null) return; // Not created yet
|
||||||
|
if(view == testingButton) {
|
||||||
|
startActivity(new Intent(this, TestingActivity.class));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(view == enableBluetooth || view == enableBluetoothHint) {
|
||||||
|
bluetoothSetting = !bluetoothSetting;
|
||||||
|
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
if(adapter != null) {
|
||||||
|
if(bluetoothSetting) adapter.enable();
|
||||||
|
else adapter.disable();
|
||||||
|
}
|
||||||
|
} else if(view == notifySound || view == notifySoundHint) {
|
||||||
|
soundSetting = !soundSetting;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
runOnDbThread(new Runnable() {
|
runOnDbThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
TransportConfig c = new TransportConfig();
|
TransportConfig c = new TransportConfig();
|
||||||
c.put("enable", String.valueOf(activateBluetooth));
|
c.putBoolean("enable", btSetting);
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
db.mergeConfig(new TransportId("bt"), c);
|
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");
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
if(LOG.isLoggable(WARNING))
|
if(LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
@@ -157,4 +287,11 @@ public class SettingsActivity extends BriarActivity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if(e instanceof SettingsUpdatedEvent) {
|
||||||
|
LOG.info("Settings updated");
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -234,33 +234,33 @@ public class SetupActivity extends RoboActivity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void storeEncryptedDatabaseKey(final byte[] encrypted) {
|
private void storeEncryptedDatabaseKey(final byte[] encrypted) {
|
||||||
long start = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
SharedPreferences prefs = getSharedPreferences("db", MODE_PRIVATE);
|
SharedPreferences prefs = getSharedPreferences("db", MODE_PRIVATE);
|
||||||
Editor editor = prefs.edit();
|
Editor editor = prefs.edit();
|
||||||
editor.putString("key", StringUtils.toHexString(encrypted));
|
editor.putString("key", StringUtils.toHexString(encrypted));
|
||||||
editor.commit();
|
editor.commit();
|
||||||
long duration = System.currentTimeMillis() - start;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Key storage took " + duration + " ms");
|
LOG.info("Key storage took " + duration + " ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] encryptDatabaseKey(byte[] key, char[] password) {
|
private byte[] encryptDatabaseKey(byte[] key, char[] password) {
|
||||||
long start = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
byte[] encrypted = crypto.encryptWithPassword(key, password);
|
byte[] encrypted = crypto.encryptWithPassword(key, password);
|
||||||
long duration = System.currentTimeMillis() - start;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Key derivation took " + duration + " ms");
|
LOG.info("Key derivation took " + duration + " ms");
|
||||||
return encrypted;
|
return encrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalAuthor createLocalAuthor(String nickname) {
|
private LocalAuthor createLocalAuthor(String nickname) {
|
||||||
long start = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
||||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||||
byte[] privateKey = keyPair.getPrivate().getEncoded();
|
byte[] privateKey = keyPair.getPrivate().getEncoded();
|
||||||
LocalAuthor localAuthor = authorFactory.createLocalAuthor(nickname,
|
LocalAuthor localAuthor = authorFactory.createLocalAuthor(nickname,
|
||||||
publicKey, privateKey);
|
publicKey, privateKey);
|
||||||
long duration = System.currentTimeMillis() - start;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Identity creation took " + duration + " ms");
|
LOG.info("Identity creation took " + duration + " ms");
|
||||||
return localAuthor;
|
return localAuthor;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class SplashScreenActivity extends RoboSplashActivity {
|
|||||||
// Default log level - change this to OFF for release builds
|
// Default log level - change this to OFF for release builds
|
||||||
private static final Level DEFAULT_LOG_LEVEL = INFO;
|
private static final Level DEFAULT_LOG_LEVEL = INFO;
|
||||||
|
|
||||||
private long start = System.currentTimeMillis();
|
private long now = System.currentTimeMillis();
|
||||||
|
|
||||||
public SplashScreenActivity() {
|
public SplashScreenActivity() {
|
||||||
Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL);
|
Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL);
|
||||||
@@ -60,7 +60,7 @@ public class SplashScreenActivity extends RoboSplashActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void startNextActivity() {
|
protected void startNextActivity() {
|
||||||
long duration = System.currentTimeMillis() - start;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Guice startup took " + duration + " ms");
|
LOG.info("Guice startup took " + duration + " ms");
|
||||||
if(System.currentTimeMillis() >= EXPIRY_DATE) {
|
if(System.currentTimeMillis() >= EXPIRY_DATE) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package org.briarproject.android.util;
|
package org.briarproject.android.util;
|
||||||
|
|
||||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
@@ -9,9 +9,7 @@ public class FixedVerticalSpace extends View {
|
|||||||
|
|
||||||
public FixedVerticalSpace(Context ctx) {
|
public FixedVerticalSpace(Context ctx) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
}
|
int height = LayoutUtils.getPadding(ctx);
|
||||||
|
setLayoutParams(new LayoutParams(MATCH_PARENT, height));
|
||||||
public void setHeight(int height) {
|
|
||||||
setLayoutParams(new LayoutParams(WRAP_CONTENT, height));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,11 +43,12 @@ public class AndroidPluginsModule extends AbstractModule {
|
|||||||
AndroidExecutor androidExecutor, Application app,
|
AndroidExecutor androidExecutor, Application app,
|
||||||
CryptoComponent crypto, LocationUtils locationUtils,
|
CryptoComponent crypto, LocationUtils locationUtils,
|
||||||
ShutdownManager shutdownManager) {
|
ShutdownManager shutdownManager) {
|
||||||
Context ctx = app.getApplicationContext();
|
Context appContext = app.getApplicationContext();
|
||||||
DuplexPluginFactory droidtooth = new DroidtoothPluginFactory(
|
DuplexPluginFactory droidtooth = new DroidtoothPluginFactory(
|
||||||
pluginExecutor, androidExecutor, ctx, crypto.getSecureRandom());
|
pluginExecutor, androidExecutor, appContext,
|
||||||
|
crypto.getSecureRandom());
|
||||||
DuplexPluginFactory tor = new TorPluginFactory(pluginExecutor,
|
DuplexPluginFactory tor = new TorPluginFactory(pluginExecutor,
|
||||||
ctx, locationUtils, shutdownManager);
|
appContext, locationUtils, shutdownManager);
|
||||||
DuplexPluginFactory lan = new LanTcpPluginFactory(pluginExecutor);
|
DuplexPluginFactory lan = new LanTcpPluginFactory(pluginExecutor);
|
||||||
final Collection<DuplexPluginFactory> factories =
|
final Collection<DuplexPluginFactory> factories =
|
||||||
Arrays.asList(droidtooth, tor, lan);
|
Arrays.asList(droidtooth, tor, lan);
|
||||||
|
|||||||
@@ -155,8 +155,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
private boolean enableBluetooth() {
|
private boolean enableBluetooth() {
|
||||||
if(adapter.isEnabled()) return true;
|
if(adapter.isEnabled()) return true;
|
||||||
String enable = callback.getConfig().get("enable");
|
if(!callback.getConfig().getBoolean("enable", true)) {
|
||||||
if("false".equals(enable)) {
|
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Not enabling Bluetooth");
|
if(LOG.isLoggable(INFO)) LOG.info("Not enabling Bluetooth");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -267,7 +266,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
if(!running) return;
|
if(!running) return;
|
||||||
if(!enableBluetooth()) return;
|
if(!adapter.isEnabled()) return;
|
||||||
// Try to connect to known devices in parallel
|
// Try to connect to known devices in parallel
|
||||||
Map<ContactId, TransportProperties> remote =
|
Map<ContactId, TransportProperties> remote =
|
||||||
callback.getRemoteProperties();
|
callback.getRemoteProperties();
|
||||||
@@ -349,7 +348,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||||
long timeout) {
|
long timeout) {
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
if(!enableBluetooth()) return null;
|
if(!adapter.isEnabled()) return null;
|
||||||
// Use the invitation codes to generate the UUID
|
// Use the invitation codes to generate the UUID
|
||||||
byte[] b = r.nextBytes(UUID_BYTES);
|
byte[] b = r.nextBytes(UUID_BYTES);
|
||||||
UUID uuid = UUID.nameUUIDFromBytes(b);
|
UUID uuid = UUID.nameUUIDFromBytes(b);
|
||||||
|
|||||||
Reference in New Issue
Block a user