mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 03:09:04 +01:00
Compare commits
11 Commits
beta-0.16.
...
beta-0.16.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
078534889e | ||
|
|
e92713006a | ||
|
|
18f43f3bc1 | ||
|
|
a4118b40e1 | ||
|
|
de29fbc324 | ||
|
|
3197dcf9b5 | ||
|
|
35aad409fd | ||
|
|
08ce6a7331 | ||
|
|
33a0099065 | ||
|
|
34d20fafda | ||
|
|
0d6983b4ef |
@@ -12,8 +12,8 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 22
|
targetSdkVersion 22
|
||||||
versionCode 14
|
versionCode 1609
|
||||||
versionName "0.14"
|
versionName "0.16.9"
|
||||||
consumerProguardFiles 'proguard-rules.txt'
|
consumerProguardFiles 'proguard-rules.txt'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,15 +78,19 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 22
|
targetSdkVersion 22
|
||||||
versionCode 1608
|
versionCode 1609
|
||||||
versionName "0.16.8"
|
versionName "0.16.9"
|
||||||
applicationId "org.briarproject.briar.beta"
|
applicationId "org.briarproject.briar.beta"
|
||||||
resValue "string", "app_package", "org.briarproject.briar.beta"
|
resValue "string", "app_package", "org.briarproject.briar.beta"
|
||||||
|
resValue "string", "app_name", "Briar Beta"
|
||||||
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
|
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
|
applicationIdSuffix ".debug"
|
||||||
|
resValue "string", "app_package", "org.briarproject.briar.beta.debug"
|
||||||
|
resValue "string", "app_name", "Briar Debug"
|
||||||
shrinkResources false
|
shrinkResources false
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ import android.app.NotificationManager;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
@@ -25,12 +22,14 @@ import org.briarproject.bramble.api.settings.SettingsManager;
|
|||||||
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.contact.ConversationActivity;
|
import org.briarproject.briar.android.contact.ConversationActivity;
|
||||||
import org.briarproject.briar.android.forum.ForumActivity;
|
import org.briarproject.briar.android.forum.ForumActivity;
|
||||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||||
|
import org.briarproject.briar.android.util.BriarNotificationBuilder;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||||
import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
|
import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
|
||||||
@@ -48,6 +47,7 @@ import java.util.concurrent.Callable;
|
|||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -61,8 +61,6 @@ import static android.content.Context.NOTIFICATION_SERVICE;
|
|||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
|
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
|
||||||
import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
|
import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
|
||||||
import static android.support.v4.app.NotificationCompat.VISIBILITY_PRIVATE;
|
|
||||||
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||||
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
|
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
|
||||||
@@ -95,6 +93,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
private static final String BLOG_URI =
|
private static final String BLOG_URI =
|
||||||
"content://org.briarproject.briar/blog";
|
"content://org.briarproject.briar/blog";
|
||||||
|
|
||||||
|
private static final long SOUND_DELAY = TimeUnit.SECONDS.toMillis(2);
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(AndroidNotificationManagerImpl.class.getName());
|
Logger.getLogger(AndroidNotificationManagerImpl.class.getName());
|
||||||
|
|
||||||
@@ -102,6 +102,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
private final SettingsManager settingsManager;
|
private final SettingsManager settingsManager;
|
||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
|
private final Clock clock;
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
// The following must only be accessed on the main UI thread
|
// The following must only be accessed on the main UI thread
|
||||||
@@ -117,16 +118,18 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
private boolean blockContacts = false, blockGroups = false;
|
private boolean blockContacts = false, blockGroups = false;
|
||||||
private boolean blockForums = false, blockBlogs = false;
|
private boolean blockForums = false, blockBlogs = false;
|
||||||
private boolean blockIntroductions = false;
|
private boolean blockIntroductions = false;
|
||||||
|
private long lastSound = 0;
|
||||||
|
|
||||||
private volatile Settings settings = new Settings();
|
private volatile Settings settings = new Settings();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AndroidNotificationManagerImpl(@DatabaseExecutor Executor dbExecutor,
|
AndroidNotificationManagerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||||
SettingsManager settingsManager, AndroidExecutor androidExecutor,
|
SettingsManager settingsManager, AndroidExecutor androidExecutor,
|
||||||
Application app) {
|
Application app, Clock clock) {
|
||||||
this.dbExecutor = dbExecutor;
|
this.dbExecutor = dbExecutor;
|
||||||
this.settingsManager = settingsManager;
|
this.settingsManager = settingsManager;
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
|
this.clock = clock;
|
||||||
appContext = app.getApplicationContext();
|
appContext = app.getApplicationContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,22 +291,19 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
if (contactTotal == 0) {
|
if (contactTotal == 0) {
|
||||||
clearContactNotification();
|
clearContactNotification();
|
||||||
} else if (settings.getBoolean(PREF_NOTIFY_PRIVATE, true)) {
|
} else if (settings.getBoolean(PREF_NOTIFY_PRIVATE, true)) {
|
||||||
NotificationCompat.Builder b =
|
BriarNotificationBuilder b =
|
||||||
new NotificationCompat.Builder(appContext);
|
new BriarNotificationBuilder(appContext);
|
||||||
b.setSmallIcon(R.drawable.notification_private_message);
|
b.setSmallIcon(R.drawable.notification_private_message);
|
||||||
b.setColor(ContextCompat.getColor(appContext,
|
b.setColorRes(R.color.briar_primary);
|
||||||
R.color.briar_primary));
|
|
||||||
b.setContentTitle(appContext.getText(R.string.app_name));
|
b.setContentTitle(appContext.getText(R.string.app_name));
|
||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.private_message_notification_text, contactTotal,
|
R.plurals.private_message_notification_text, contactTotal,
|
||||||
contactTotal));
|
contactTotal));
|
||||||
boolean sound = settings.getBoolean(PREF_NOTIFY_SOUND, true);
|
b.setNumber(contactTotal);
|
||||||
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
boolean showOnLockScreen =
|
||||||
if (sound && !StringUtils.isNullOrEmpty(ringtoneUri))
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
b.setSound(Uri.parse(ringtoneUri));
|
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
|
||||||
b.setDefaults(getDefaults());
|
playSound(b);
|
||||||
b.setOnlyAlertOnce(true);
|
|
||||||
b.setAutoCancel(true);
|
|
||||||
if (contactCounts.size() == 1) {
|
if (contactCounts.size() == 1) {
|
||||||
// Touching the notification shows the relevant conversation
|
// Touching the notification shows the relevant conversation
|
||||||
Intent i = new Intent(appContext, ConversationActivity.class);
|
Intent i = new Intent(appContext, ConversationActivity.class);
|
||||||
@@ -326,21 +326,27 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
t.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
b.setCategory(CATEGORY_MESSAGE);
|
|
||||||
boolean showOnLockScreen =
|
|
||||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
|
||||||
if (showOnLockScreen)
|
|
||||||
b.setVisibility(VISIBILITY_PRIVATE);
|
|
||||||
else
|
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
|
||||||
}
|
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
nm.notify(PRIVATE_MESSAGE_NOTIFICATION_ID, b.build());
|
nm.notify(PRIVATE_MESSAGE_NOTIFICATION_ID, b.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
private void playSound(BriarNotificationBuilder b) {
|
||||||
|
boolean sound = settings.getBoolean(PREF_NOTIFY_SOUND, true);
|
||||||
|
if (!sound) return;
|
||||||
|
|
||||||
|
long currentTime = clock.currentTimeMillis();
|
||||||
|
if (currentTime - lastSound > SOUND_DELAY) {
|
||||||
|
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
||||||
|
if (!StringUtils.isNullOrEmpty(ringtoneUri))
|
||||||
|
b.setSound(Uri.parse(ringtoneUri));
|
||||||
|
b.setDefaults(getDefaults());
|
||||||
|
lastSound = clock.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private int getDefaults() {
|
private int getDefaults() {
|
||||||
int defaults = DEFAULT_LIGHTS;
|
int defaults = DEFAULT_LIGHTS;
|
||||||
@@ -387,21 +393,19 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
if (groupTotal == 0) {
|
if (groupTotal == 0) {
|
||||||
clearGroupMessageNotification();
|
clearGroupMessageNotification();
|
||||||
} else if (settings.getBoolean(PREF_NOTIFY_GROUP, true)) {
|
} else if (settings.getBoolean(PREF_NOTIFY_GROUP, true)) {
|
||||||
NotificationCompat.Builder b =
|
BriarNotificationBuilder b =
|
||||||
new NotificationCompat.Builder(appContext);
|
new BriarNotificationBuilder(appContext);
|
||||||
b.setSmallIcon(R.drawable.notification_private_group);
|
b.setSmallIcon(R.drawable.notification_private_group);
|
||||||
b.setColor(ContextCompat.getColor(appContext,
|
b.setColorRes(R.color.briar_primary);
|
||||||
R.color.briar_primary));
|
|
||||||
b.setContentTitle(appContext.getText(R.string.app_name));
|
b.setContentTitle(appContext.getText(R.string.app_name));
|
||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.group_message_notification_text, groupTotal,
|
R.plurals.group_message_notification_text, groupTotal,
|
||||||
groupTotal));
|
groupTotal));
|
||||||
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
b.setNumber(groupTotal);
|
||||||
if (!StringUtils.isNullOrEmpty(ringtoneUri))
|
boolean showOnLockScreen =
|
||||||
b.setSound(Uri.parse(ringtoneUri));
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
b.setDefaults(getDefaults());
|
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||||
b.setOnlyAlertOnce(true);
|
playSound(b);
|
||||||
b.setAutoCancel(true);
|
|
||||||
if (groupCounts.size() == 1) {
|
if (groupCounts.size() == 1) {
|
||||||
// Touching the notification shows the relevant group
|
// Touching the notification shows the relevant group
|
||||||
Intent i = new Intent(appContext, GroupActivity.class);
|
Intent i = new Intent(appContext, GroupActivity.class);
|
||||||
@@ -425,15 +429,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
t.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
b.setCategory(CATEGORY_SOCIAL);
|
|
||||||
boolean showOnLockScreen =
|
|
||||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
|
||||||
if (showOnLockScreen)
|
|
||||||
b.setVisibility(VISIBILITY_PRIVATE);
|
|
||||||
else
|
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
|
||||||
}
|
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
nm.notify(GROUP_MESSAGE_NOTIFICATION_ID, b.build());
|
nm.notify(GROUP_MESSAGE_NOTIFICATION_ID, b.build());
|
||||||
@@ -474,21 +469,19 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
if (forumTotal == 0) {
|
if (forumTotal == 0) {
|
||||||
clearForumPostNotification();
|
clearForumPostNotification();
|
||||||
} else if (settings.getBoolean(PREF_NOTIFY_FORUM, true)) {
|
} else if (settings.getBoolean(PREF_NOTIFY_FORUM, true)) {
|
||||||
NotificationCompat.Builder b =
|
BriarNotificationBuilder b =
|
||||||
new NotificationCompat.Builder(appContext);
|
new BriarNotificationBuilder(appContext);
|
||||||
b.setSmallIcon(R.drawable.notification_forum);
|
b.setSmallIcon(R.drawable.notification_forum);
|
||||||
b.setColor(ContextCompat.getColor(appContext,
|
b.setColorRes(R.color.briar_primary);
|
||||||
R.color.briar_primary));
|
|
||||||
b.setContentTitle(appContext.getText(R.string.app_name));
|
b.setContentTitle(appContext.getText(R.string.app_name));
|
||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.forum_post_notification_text, forumTotal,
|
R.plurals.forum_post_notification_text, forumTotal,
|
||||||
forumTotal));
|
forumTotal));
|
||||||
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
b.setNumber(forumTotal);
|
||||||
if (!StringUtils.isNullOrEmpty(ringtoneUri))
|
boolean showOnLockScreen =
|
||||||
b.setSound(Uri.parse(ringtoneUri));
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
b.setDefaults(getDefaults());
|
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||||
b.setOnlyAlertOnce(true);
|
playSound(b);
|
||||||
b.setAutoCancel(true);
|
|
||||||
if (forumCounts.size() == 1) {
|
if (forumCounts.size() == 1) {
|
||||||
// Touching the notification shows the relevant forum
|
// Touching the notification shows the relevant forum
|
||||||
Intent i = new Intent(appContext, ForumActivity.class);
|
Intent i = new Intent(appContext, ForumActivity.class);
|
||||||
@@ -512,15 +505,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
t.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
b.setCategory(CATEGORY_SOCIAL);
|
|
||||||
boolean showOnLockScreen =
|
|
||||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
|
||||||
if (showOnLockScreen)
|
|
||||||
b.setVisibility(VISIBILITY_PRIVATE);
|
|
||||||
else
|
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
|
||||||
}
|
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
nm.notify(FORUM_POST_NOTIFICATION_ID, b.build());
|
nm.notify(FORUM_POST_NOTIFICATION_ID, b.build());
|
||||||
@@ -561,21 +545,19 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
if (blogTotal == 0) {
|
if (blogTotal == 0) {
|
||||||
clearBlogPostNotification();
|
clearBlogPostNotification();
|
||||||
} else if (settings.getBoolean(PREF_NOTIFY_BLOG, true)) {
|
} else if (settings.getBoolean(PREF_NOTIFY_BLOG, true)) {
|
||||||
NotificationCompat.Builder b =
|
BriarNotificationBuilder b =
|
||||||
new NotificationCompat.Builder(appContext);
|
new BriarNotificationBuilder(appContext);
|
||||||
b.setSmallIcon(R.drawable.notification_blog);
|
b.setSmallIcon(R.drawable.notification_blog);
|
||||||
b.setColor(ContextCompat.getColor(appContext,
|
b.setColorRes(R.color.briar_primary);
|
||||||
R.color.briar_primary));
|
|
||||||
b.setContentTitle(appContext.getText(R.string.app_name));
|
b.setContentTitle(appContext.getText(R.string.app_name));
|
||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.blog_post_notification_text, blogTotal,
|
R.plurals.blog_post_notification_text, blogTotal,
|
||||||
blogTotal));
|
blogTotal));
|
||||||
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
b.setNumber(blogTotal);
|
||||||
if (!StringUtils.isNullOrEmpty(ringtoneUri))
|
boolean showOnLockScreen =
|
||||||
b.setSound(Uri.parse(ringtoneUri));
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
b.setDefaults(getDefaults());
|
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||||
b.setOnlyAlertOnce(true);
|
playSound(b);
|
||||||
b.setAutoCancel(true);
|
|
||||||
// Touching the notification shows the combined blog feed
|
// Touching the notification shows the combined blog feed
|
||||||
Intent i = new Intent(appContext, NavDrawerActivity.class);
|
Intent i = new Intent(appContext, NavDrawerActivity.class);
|
||||||
i.putExtra(INTENT_BLOGS, true);
|
i.putExtra(INTENT_BLOGS, true);
|
||||||
@@ -585,15 +567,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
t.addParentStack(NavDrawerActivity.class);
|
t.addParentStack(NavDrawerActivity.class);
|
||||||
t.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
b.setCategory(CATEGORY_SOCIAL);
|
|
||||||
boolean showOnLockScreen =
|
|
||||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
|
||||||
if (showOnLockScreen)
|
|
||||||
b.setVisibility(VISIBILITY_PRIVATE);
|
|
||||||
else
|
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
|
||||||
}
|
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
nm.notify(BLOG_POST_NOTIFICATION_ID, b.build());
|
nm.notify(BLOG_POST_NOTIFICATION_ID, b.build());
|
||||||
@@ -623,20 +597,17 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void updateIntroductionNotification() {
|
private void updateIntroductionNotification() {
|
||||||
NotificationCompat.Builder b =
|
BriarNotificationBuilder b = new BriarNotificationBuilder(appContext);
|
||||||
new NotificationCompat.Builder(appContext);
|
|
||||||
b.setSmallIcon(R.drawable.notification_introduction);
|
b.setSmallIcon(R.drawable.notification_introduction);
|
||||||
b.setColor(ContextCompat.getColor(appContext, R.color.briar_primary));
|
b.setColorRes(R.color.briar_primary);
|
||||||
b.setContentTitle(appContext.getText(R.string.app_name));
|
b.setContentTitle(appContext.getText(R.string.app_name));
|
||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.introduction_notification_text, introductionTotal,
|
R.plurals.introduction_notification_text, introductionTotal,
|
||||||
introductionTotal));
|
introductionTotal));
|
||||||
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
boolean showOnLockScreen =
|
||||||
if (!StringUtils.isNullOrEmpty(ringtoneUri))
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
b.setSound(Uri.parse(ringtoneUri));
|
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
|
||||||
b.setDefaults(getDefaults());
|
playSound(b);
|
||||||
b.setOnlyAlertOnce(true);
|
|
||||||
b.setAutoCancel(true);
|
|
||||||
// Touching the notification shows the contact list
|
// Touching the notification shows the contact list
|
||||||
Intent i = new Intent(appContext, NavDrawerActivity.class);
|
Intent i = new Intent(appContext, NavDrawerActivity.class);
|
||||||
i.putExtra(INTENT_CONTACTS, true);
|
i.putExtra(INTENT_CONTACTS, true);
|
||||||
@@ -646,15 +617,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
t.addParentStack(NavDrawerActivity.class);
|
t.addParentStack(NavDrawerActivity.class);
|
||||||
t.addNextIntent(i);
|
t.addNextIntent(i);
|
||||||
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
b.setCategory(CATEGORY_MESSAGE);
|
|
||||||
boolean showOnLockScreen =
|
|
||||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
|
||||||
if (showOnLockScreen)
|
|
||||||
b.setVisibility(VISIBILITY_PRIVATE);
|
|
||||||
else
|
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
|
||||||
}
|
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
nm.notify(INTRODUCTION_SUCCESS_NOTIFICATION_ID, b.build());
|
nm.notify(INTRODUCTION_SUCCESS_NOTIFICATION_ID, b.build());
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.briarproject.briar.android.keyagreement;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
class CameraException extends IOException {
|
||||||
|
|
||||||
|
CameraException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -84,16 +84,14 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public void start() {
|
public void start() throws CameraException {
|
||||||
|
LOG.info("Opening camera");
|
||||||
try {
|
try {
|
||||||
LOG.info("Opening camera");
|
|
||||||
camera = Camera.open();
|
camera = Camera.open();
|
||||||
if (camera == null)
|
|
||||||
throw new RuntimeException("No back-facing camera.");
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOG.log(WARNING, "Error opening camera", e);
|
throw new CameraException(e);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (camera == null) throw new CameraException("No back-facing camera");
|
||||||
setDisplayOrientation(0);
|
setDisplayOrientation(0);
|
||||||
// Use barcode scene mode if it's available
|
// Use barcode scene mode if it's available
|
||||||
Parameters params = camera.getParameters();
|
Parameters params = camera.getParameters();
|
||||||
@@ -117,64 +115,81 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public void stop() {
|
public void stop() throws CameraException {
|
||||||
if (camera == null) return;
|
if (camera == null) return;
|
||||||
stopPreview();
|
stopPreview();
|
||||||
|
LOG.info("Releasing camera");
|
||||||
try {
|
try {
|
||||||
LOG.info("Releasing camera");
|
|
||||||
camera.release();
|
camera.release();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOG.log(WARNING, "Error releasing camera", e);
|
throw new CameraException(e);
|
||||||
}
|
}
|
||||||
camera = null;
|
camera = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void startPreview(SurfaceHolder holder) {
|
private void startPreview(SurfaceHolder holder) throws CameraException {
|
||||||
LOG.info("Starting preview");
|
LOG.info("Starting preview");
|
||||||
|
if (camera == null) throw new CameraException("Camera is null");
|
||||||
try {
|
try {
|
||||||
if (camera == null) throw new IOException("Camera is null.");
|
|
||||||
camera.setPreviewDisplay(holder);
|
camera.setPreviewDisplay(holder);
|
||||||
camera.startPreview();
|
camera.startPreview();
|
||||||
previewStarted = true;
|
previewStarted = true;
|
||||||
startConsumer();
|
startConsumer();
|
||||||
} catch (IOException | RuntimeException e) {
|
} catch (IOException | RuntimeException e) {
|
||||||
LOG.log(WARNING, "Error starting camera preview", e);
|
throw new CameraException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void stopPreview() {
|
private void stopPreview() throws CameraException {
|
||||||
LOG.info("Stopping preview");
|
LOG.info("Stopping preview");
|
||||||
|
if (camera == null) throw new CameraException("Camera is null");
|
||||||
try {
|
try {
|
||||||
if (camera == null) throw new RuntimeException("Camera is null.");
|
|
||||||
stopConsumer();
|
stopConsumer();
|
||||||
camera.stopPreview();
|
camera.stopPreview();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOG.log(WARNING, "Error stopping camera preview", e);
|
throw new CameraException(e);
|
||||||
}
|
}
|
||||||
previewStarted = false;
|
previewStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void startConsumer() {
|
private void startConsumer() throws CameraException {
|
||||||
if (camera == null) throw new RuntimeException("Camera is null");
|
if (camera == null) throw new CameraException("Camera is null");
|
||||||
if (autoFocus) camera.autoFocus(this);
|
if (autoFocus) {
|
||||||
|
try {
|
||||||
|
camera.autoFocus(this);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new CameraException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
previewConsumer.start(camera);
|
previewConsumer.start(camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void stopConsumer() {
|
private void stopConsumer() throws CameraException {
|
||||||
if (camera == null) throw new RuntimeException("Camera is null");
|
if (camera == null) throw new CameraException("Camera is null");
|
||||||
if (autoFocus) camera.cancelAutoFocus();
|
if (autoFocus) {
|
||||||
|
try {
|
||||||
|
camera.cancelAutoFocus();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new CameraException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
previewConsumer.stop();
|
previewConsumer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void setDisplayOrientation(int rotationDegrees) {
|
private void setDisplayOrientation(int rotationDegrees)
|
||||||
|
throws CameraException {
|
||||||
int orientation;
|
int orientation;
|
||||||
CameraInfo info = new CameraInfo();
|
CameraInfo info = new CameraInfo();
|
||||||
Camera.getCameraInfo(0, info);
|
try {
|
||||||
|
Camera.getCameraInfo(0, info);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new CameraException(e);
|
||||||
|
}
|
||||||
if (info.facing == CAMERA_FACING_FRONT) {
|
if (info.facing == CAMERA_FACING_FRONT) {
|
||||||
orientation = (info.orientation + rotationDegrees) % 360;
|
orientation = (info.orientation + rotationDegrees) % 360;
|
||||||
orientation = (360 - orientation) % 360;
|
orientation = (360 - orientation) % 360;
|
||||||
@@ -183,54 +198,70 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Display orientation " + orientation + " degrees");
|
LOG.info("Display orientation " + orientation + " degrees");
|
||||||
|
if (camera == null) throw new CameraException("Camera is null");
|
||||||
try {
|
try {
|
||||||
if (camera == null) throw new RuntimeException("Camera is null");
|
|
||||||
camera.setDisplayOrientation(orientation);
|
camera.setDisplayOrientation(orientation);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOG.log(WARNING, "Error setting display orientation", e);
|
throw new CameraException(e);
|
||||||
}
|
}
|
||||||
displayOrientation = orientation;
|
displayOrientation = orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private Parameters setSceneMode(Camera camera, Parameters params) {
|
private Parameters setSceneMode(Camera camera, Parameters params)
|
||||||
|
throws CameraException {
|
||||||
List<String> sceneModes = params.getSupportedSceneModes();
|
List<String> sceneModes = params.getSupportedSceneModes();
|
||||||
if (sceneModes == null) return params;
|
if (sceneModes == null) return params;
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Scene modes: " + sceneModes);
|
if (LOG.isLoggable(INFO)) LOG.info("Scene modes: " + sceneModes);
|
||||||
if (sceneModes.contains(SCENE_MODE_BARCODE)) {
|
if (sceneModes.contains(SCENE_MODE_BARCODE)) {
|
||||||
params.setSceneMode(SCENE_MODE_BARCODE);
|
params.setSceneMode(SCENE_MODE_BARCODE);
|
||||||
camera.setParameters(params);
|
try {
|
||||||
return camera.getParameters();
|
camera.setParameters(params);
|
||||||
|
return camera.getParameters();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new CameraException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private Parameters disableFlash(Camera camera, Parameters params) {
|
private Parameters disableFlash(Camera camera, Parameters params)
|
||||||
|
throws CameraException {
|
||||||
params.setFlashMode(FLASH_MODE_OFF);
|
params.setFlashMode(FLASH_MODE_OFF);
|
||||||
camera.setParameters(params);
|
try {
|
||||||
return camera.getParameters();
|
camera.setParameters(params);
|
||||||
|
return camera.getParameters();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new CameraException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private Parameters disableSceneMode(Camera camera, Parameters params) {
|
private Parameters disableSceneMode(Camera camera, Parameters params)
|
||||||
|
throws CameraException {
|
||||||
params.setSceneMode(SCENE_MODE_AUTO);
|
params.setSceneMode(SCENE_MODE_AUTO);
|
||||||
camera.setParameters(params);
|
try {
|
||||||
return camera.getParameters();
|
camera.setParameters(params);
|
||||||
|
return camera.getParameters();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new CameraException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private Parameters setBestParameters(Camera camera, Parameters params) {
|
private Parameters setBestParameters(Camera camera, Parameters params)
|
||||||
|
throws CameraException {
|
||||||
setVideoStabilisation(params);
|
setVideoStabilisation(params);
|
||||||
setFocusMode(params);
|
setFocusMode(params);
|
||||||
params.setFlashMode(FLASH_MODE_OFF);
|
params.setFlashMode(FLASH_MODE_OFF);
|
||||||
setPreviewSize(params);
|
setPreviewSize(params);
|
||||||
try {
|
try {
|
||||||
camera.setParameters(params);
|
camera.setParameters(params);
|
||||||
|
return camera.getParameters();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOG.log(WARNING, "Error setting best camera parameters", e);
|
throw new CameraException(e);
|
||||||
}
|
}
|
||||||
return camera.getParameters();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@@ -299,9 +330,15 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void logCameraParameters() {
|
private void logCameraParameters() throws CameraException {
|
||||||
if (camera != null && LOG.isLoggable(INFO)) {
|
if (camera == null) throw new AssertionError();
|
||||||
Parameters params = camera.getParameters();
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
Parameters params;
|
||||||
|
try {
|
||||||
|
params = camera.getParameters();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new CameraException(e);
|
||||||
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 15) {
|
if (Build.VERSION.SDK_INT >= 15) {
|
||||||
LOG.info("Video stabilisation enabled: "
|
LOG.info("Video stabilisation enabled: "
|
||||||
+ params.getVideoStabilization());
|
+ params.getVideoStabilization());
|
||||||
@@ -319,13 +356,18 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
post(new Runnable() {
|
post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
surfaceCreatedUi(holder);
|
try {
|
||||||
|
surfaceCreatedUi(holder);
|
||||||
|
} catch (CameraException e) {
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void surfaceCreatedUi(SurfaceHolder holder) {
|
private void surfaceCreatedUi(SurfaceHolder holder) throws CameraException {
|
||||||
LOG.info("Surface created");
|
LOG.info("Surface created");
|
||||||
if (surface != null && surface != holder.getSurface()) {
|
if (surface != null && surface != holder.getSurface()) {
|
||||||
LOG.info("Releasing old surface");
|
LOG.info("Releasing old surface");
|
||||||
@@ -342,13 +384,19 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
post(new Runnable() {
|
post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
surfaceChangedUi(holder, w, h);
|
try {
|
||||||
|
surfaceChangedUi(holder, w, h);
|
||||||
|
} catch (CameraException e) {
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void surfaceChangedUi(SurfaceHolder holder, int w, int h) {
|
private void surfaceChangedUi(SurfaceHolder holder, int w, int h)
|
||||||
|
throws CameraException {
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Surface changed: " + w + "x" + h);
|
if (LOG.isLoggable(INFO)) LOG.info("Surface changed: " + w + "x" + h);
|
||||||
if (surface != null && surface != holder.getSurface()) {
|
if (surface != null && surface != holder.getSurface()) {
|
||||||
LOG.info("Releasing old surface");
|
LOG.info("Releasing old surface");
|
||||||
@@ -365,7 +413,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
camera.setParameters(params);
|
camera.setParameters(params);
|
||||||
logCameraParameters();
|
logCameraParameters();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOG.log(WARNING, "Error setting preview size", e);
|
throw new CameraException(e);
|
||||||
}
|
}
|
||||||
startPreview(holder);
|
startPreview(holder);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import static android.view.View.INVISIBLE;
|
|||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static android.widget.Toast.LENGTH_LONG;
|
import static android.widget.Toast.LENGTH_LONG;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -143,6 +144,12 @@ public class ShowQrCodeFragment extends BaseEventFragment
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
||||||
|
try {
|
||||||
|
cameraView.start();
|
||||||
|
} catch (CameraException e) {
|
||||||
|
logCameraExceptionAndFinish(e);
|
||||||
|
}
|
||||||
|
|
||||||
// Listen for changes to the Bluetooth state
|
// Listen for changes to the Bluetooth state
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(ACTION_STATE_CHANGED);
|
filter.addAction(ACTION_STATE_CHANGED);
|
||||||
@@ -162,7 +169,6 @@ public class ShowQrCodeFragment extends BaseEventFragment
|
|||||||
} else {
|
} else {
|
||||||
startListening();
|
startListening();
|
||||||
}
|
}
|
||||||
cameraView.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -170,7 +176,19 @@ public class ShowQrCodeFragment extends BaseEventFragment
|
|||||||
super.onStop();
|
super.onStop();
|
||||||
stopListening();
|
stopListening();
|
||||||
if (receiver != null) getActivity().unregisterReceiver(receiver);
|
if (receiver != null) getActivity().unregisterReceiver(receiver);
|
||||||
cameraView.stop();
|
try {
|
||||||
|
cameraView.stop();
|
||||||
|
} catch (CameraException e) {
|
||||||
|
logCameraExceptionAndFinish(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
private void logCameraExceptionAndFinish(CameraException e) {
|
||||||
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
Toast.makeText(getActivity(), R.string.camera_error,
|
||||||
|
LENGTH_LONG).show();
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.briarproject.briar.android.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.support.annotation.ColorRes;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v7.app.NotificationCompat;
|
||||||
|
|
||||||
|
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
|
||||||
|
import static android.support.v4.app.NotificationCompat.VISIBILITY_PRIVATE;
|
||||||
|
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
|
||||||
|
|
||||||
|
|
||||||
|
public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
||||||
|
|
||||||
|
public BriarNotificationBuilder(Context context) {
|
||||||
|
super(context);
|
||||||
|
setAutoCancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BriarNotificationBuilder setColorRes(@ColorRes int res) {
|
||||||
|
setColor(ContextCompat.getColor(mContext, res));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BriarNotificationBuilder setLockscreenVisibility(String category,
|
||||||
|
boolean show) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
setCategory(category);
|
||||||
|
if (show)
|
||||||
|
setVisibility(VISIBILITY_PRIVATE);
|
||||||
|
else
|
||||||
|
setVisibility(VISIBILITY_SECRET);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
<string name="introduction_activity_title">Seleccionar contacto</string>
|
<string name="introduction_activity_title">Seleccionar contacto</string>
|
||||||
<string name="introduction_message_title">Presentar a dos contactos</string>
|
<string name="introduction_message_title">Presentar a dos contactos</string>
|
||||||
<string name="introduction_message_hint">Añade un mensaje (opcional)</string>
|
<string name="introduction_message_hint">Añade un mensaje (opcional)</string>
|
||||||
<string name="introduction_button">Presentarle a</string>
|
<string name="introduction_button">Presentar contactos</string>
|
||||||
<string name="introduction_sent">Tu presentación se ha mandado.</string>
|
<string name="introduction_sent">Tu presentación se ha mandado.</string>
|
||||||
<string name="introduction_error">Ocurrió un error realizando la presentación.</string>
|
<string name="introduction_error">Ocurrió un error realizando la presentación.</string>
|
||||||
<string name="introduction_response_error">Error al responder a la presentación</string>
|
<string name="introduction_response_error">Error al responder a la presentación</string>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string translatable="false" name="app_name">Briar Beta</string>
|
|
||||||
|
|
||||||
<!-- Setup -->
|
<!-- Setup -->
|
||||||
<string name="setup_title">Briar Setup</string>
|
<string name="setup_title">Briar Setup</string>
|
||||||
@@ -121,6 +120,7 @@
|
|||||||
<string name="contact_already_exists">Contact %s already exists</string>
|
<string name="contact_already_exists">Contact %s already exists</string>
|
||||||
<string name="contact_exchange_failed">Contact exchange failed</string>
|
<string name="contact_exchange_failed">Contact exchange failed</string>
|
||||||
<string name="qr_code_invalid">The QR code is invalid</string>
|
<string name="qr_code_invalid">The QR code is invalid</string>
|
||||||
|
<string name="camera_error">Camera error</string>
|
||||||
<string name="connecting_to_device">Connecting to device\u2026</string>
|
<string name="connecting_to_device">Connecting to device\u2026</string>
|
||||||
<string name="authenticating_with_device">Authenticating with device\u2026</string>
|
<string name="authenticating_with_device">Authenticating with device\u2026</string>
|
||||||
<string name="connection_aborted_local">Connection aborted by us! This could mean that someone is trying to interfere with your connection</string>
|
<string name="connection_aborted_local">Connection aborted by us! This could mean that someone is trying to interfere with your connection</string>
|
||||||
|
|||||||
@@ -291,8 +291,12 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
|
|||||||
* This method is called periodically from a background service.
|
* This method is called periodically from a background service.
|
||||||
* It fetches all available feeds and posts new entries to the respective
|
* It fetches all available feeds and posts new entries to the respective
|
||||||
* blog.
|
* blog.
|
||||||
|
*
|
||||||
|
* We can not do this within one database {@link Transaction},
|
||||||
|
* because fetching can take a long time
|
||||||
|
* and we can not block the database that long.
|
||||||
*/
|
*/
|
||||||
private void fetchFeeds() {
|
void fetchFeeds() {
|
||||||
LOG.info("Updating RSS feeds...");
|
LOG.info("Updating RSS feeds...");
|
||||||
|
|
||||||
// Get current feeds
|
// Get current feeds
|
||||||
@@ -313,12 +317,15 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
|
|||||||
} catch (FeedException e) {
|
} catch (FeedException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
if (LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
newFeeds.add(feed);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
if (LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
newFeeds.add(feed);
|
||||||
} 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);
|
||||||
|
newFeeds.add(feed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package org.briarproject.briar.feed;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
|
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.data.BdfEntry;
|
||||||
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.api.sync.Group;
|
||||||
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
|
import org.briarproject.bramble.test.ImmediateExecutor;
|
||||||
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
|
import org.briarproject.briar.api.blog.BlogPostFactory;
|
||||||
|
import org.briarproject.briar.api.feed.Feed;
|
||||||
|
import org.jmock.Expectations;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
|
import okhttp3.Dns;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEEDS;
|
||||||
|
import static org.briarproject.briar.api.feed.FeedManager.CLIENT_ID;
|
||||||
|
|
||||||
|
public class FeedManagerImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
|
private final ScheduledExecutorService scheduler =
|
||||||
|
context.mock(ScheduledExecutorService.class);
|
||||||
|
private final Executor ioExecutor = new ImmediateExecutor();
|
||||||
|
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||||
|
private final ContactGroupFactory contactGroupFactory =
|
||||||
|
context.mock(ContactGroupFactory.class);
|
||||||
|
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||||
|
private final BlogManager blogManager = context.mock(BlogManager.class);
|
||||||
|
private final BlogPostFactory blogPostFactory =
|
||||||
|
context.mock(BlogPostFactory.class);
|
||||||
|
private final FeedFactory feedFactory = context.mock(FeedFactory.class);
|
||||||
|
private final Clock clock = context.mock(Clock.class);
|
||||||
|
private final Dns noDnsLookups = context.mock(Dns.class);
|
||||||
|
|
||||||
|
private final GroupId localGroupId = new GroupId(getRandomId());
|
||||||
|
private final Group localGroup =
|
||||||
|
new Group(localGroupId, CLIENT_ID, getRandomBytes(42));
|
||||||
|
private final GroupId blogGroupId = new GroupId(getRandomId());
|
||||||
|
private final Group blogGroup =
|
||||||
|
new Group(blogGroupId, BlogManager.CLIENT_ID, getRandomBytes(42));
|
||||||
|
private final AuthorId authorId = new AuthorId(getRandomId());
|
||||||
|
private final LocalAuthor localAuthor =
|
||||||
|
new LocalAuthor(authorId, "author", getRandomBytes(2),
|
||||||
|
getRandomBytes(2), 0);
|
||||||
|
private final Blog blog = new Blog(blogGroup, localAuthor, true);
|
||||||
|
private final Feed feed =
|
||||||
|
new Feed("http://example.org", blog, localAuthor, 0);
|
||||||
|
private final BdfDictionary feedDict = new BdfDictionary();
|
||||||
|
|
||||||
|
private final FeedManagerImpl feedManager =
|
||||||
|
new FeedManagerImpl(scheduler, ioExecutor, db, contactGroupFactory,
|
||||||
|
clientHelper, blogManager, blogPostFactory, feedFactory,
|
||||||
|
SocketFactory.getDefault(), clock, noDnsLookups);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyFetchFeed() throws Exception {
|
||||||
|
BdfList feedList = new BdfList();
|
||||||
|
expectGetFeeds(feedList);
|
||||||
|
expectStoreFeed(feedList);
|
||||||
|
feedManager.fetchFeeds();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFetchFeedIoException() throws Exception {
|
||||||
|
final BdfDictionary feedDict= new BdfDictionary();
|
||||||
|
BdfList feedList = BdfList.of(feedDict);
|
||||||
|
|
||||||
|
expectGetFeeds(feedList);
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(noDnsLookups).lookup("example.org");
|
||||||
|
will(throwException(new UnknownHostException()));
|
||||||
|
}});
|
||||||
|
expectStoreFeed(feedList);
|
||||||
|
|
||||||
|
feedManager.fetchFeeds();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectGetLocalGroup() {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID);
|
||||||
|
will(returnValue(localGroup));
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectGetFeeds(final BdfList feedList) throws Exception {
|
||||||
|
final Transaction txn = new Transaction(null, true);
|
||||||
|
final BdfDictionary feedsDict =
|
||||||
|
BdfDictionary.of(new BdfEntry(KEY_FEEDS, feedList));
|
||||||
|
expectGetLocalGroup();
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, localGroupId);
|
||||||
|
will(returnValue(feedsDict));
|
||||||
|
if (feedList.size() == 1) {
|
||||||
|
oneOf(feedFactory).createFeed(feedDict);
|
||||||
|
will(returnValue(feed));
|
||||||
|
}
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectStoreFeed(final BdfList feedList) throws Exception {
|
||||||
|
final BdfDictionary feedDict =
|
||||||
|
BdfDictionary.of(new BdfEntry(KEY_FEEDS, feedList));
|
||||||
|
expectGetLocalGroup();
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(localGroupId, feedDict);
|
||||||
|
if (feedList.size() == 1) {
|
||||||
|
oneOf(feedFactory).feedToBdfDictionary(feed);
|
||||||
|
will(returnValue(feedList.getDictionary(0)));
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user