diff --git a/briar-android/artwork/qr_code.svg b/briar-android/artwork/qr_code.svg
new file mode 100644
index 000000000..07930f849
--- /dev/null
+++ b/briar-android/artwork/qr_code.svg
@@ -0,0 +1,67 @@
+
+
+
diff --git a/briar-android/res/drawable/bluetooth.xml b/briar-android/res/drawable/bluetooth.xml
index a39bbc2a8..26f10509b 100644
--- a/briar-android/res/drawable/bluetooth.xml
+++ b/briar-android/res/drawable/bluetooth.xml
@@ -1,5 +1,4 @@
-
-
+
+
diff --git a/briar-android/res/drawable/qr_code_intro.xml b/briar-android/res/drawable/qr_code_intro.xml
new file mode 100644
index 000000000..6b09db32d
--- /dev/null
+++ b/briar-android/res/drawable/qr_code_intro.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/briar-android/res/drawable/spinner_border.xml b/briar-android/res/drawable/spinner_border.xml
new file mode 100644
index 000000000..9720073e4
--- /dev/null
+++ b/briar-android/res/drawable/spinner_border.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout-land/fragment_keyagreement_id.xml b/briar-android/res/layout-land/fragment_keyagreement_id.xml
new file mode 100644
index 000000000..590a76fbf
--- /dev/null
+++ b/briar-android/res/layout-land/fragment_keyagreement_id.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout-land/invitation_bluetooth_start.xml b/briar-android/res/layout-land/invitation_bluetooth_start.xml
new file mode 100644
index 000000000..1449bad7c
--- /dev/null
+++ b/briar-android/res/layout-land/invitation_bluetooth_start.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout/dropdown_author.xml b/briar-android/res/layout/dropdown_author.xml
index ff994a18d..090e07da7 100644
--- a/briar-android/res/layout/dropdown_author.xml
+++ b/briar-android/res/layout/dropdown_author.xml
@@ -1,8 +1,8 @@
@@ -12,14 +12,15 @@
android:layout_width="@dimen/dropdown_picture_size"
android:layout_height="@dimen/dropdown_picture_size"
android:layout_margin="@dimen/margin_small"
- app:civ_border_width="@dimen/avatar_border_width"
- app:civ_border_color="@color/briar_text_primary"/>
+ app:civ_border_color="@color/briar_text_primary"
+ app:civ_border_width="@dimen/avatar_border_width"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout/fragment_keyagreement_qr.xml b/briar-android/res/layout/fragment_keyagreement_qr.xml
index 429f59526..5f1b175ed 100644
--- a/briar-android/res/layout/fragment_keyagreement_qr.xml
+++ b/briar-android/res/layout/fragment_keyagreement_qr.xml
@@ -1,32 +1,34 @@
-
+ android:layout_height="match_parent">
-
+ android:layout_height="match_parent"/>
-
+
+
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ android:padding="@dimen/margin_medium"
+ android:visibility="invisible">
-
+
-
-
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:background="@android:color/white">
-
+
-
\ No newline at end of file
+
+
+
+
diff --git a/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml b/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml
index 5597f6718..25d04b4c5 100644
--- a/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml
+++ b/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml
@@ -18,18 +18,6 @@
android:paddingLeft="@dimen/margin_activity_horizontal"
android:paddingTop="@dimen/margin_activity_vertical">
-
-
-
-
-
-
+ android:text="@string/your_nickname"/>
+ android:background="@drawable/spinner_border"
+ android:layout_marginTop="@dimen/margin_medium"
+ android:spinnerMode="dropdown"/>
+ android:scaleType="fitCenter"
+ android:src="@drawable/bluetooth"/>
+ android:layout_marginTop="@dimen/margin_xlarge"
+ android:text="@string/face_to_face"/>
+ android:layout_marginTop="@dimen/margin_medium"
+ android:text="@string/continue_button"/>
\ No newline at end of file
diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml
index 16a1983ed..9113861d7 100644
--- a/briar-android/res/values/color.xml
+++ b/briar-android/res/values/color.xml
@@ -39,4 +39,7 @@
#000000
#ffffff
#FFFFFF
+
+ #61000000
+ @color/briar_blue_dark
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java b/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java
index 3a87c7c35..3f2bc9f45 100644
--- a/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java
+++ b/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java
@@ -1,6 +1,8 @@
package org.briarproject.android.identity;
import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -97,7 +99,17 @@ public class LocalAuthorSpinnerAdapter extends BaseAdapter
}
public View getView(int position, View convertView, ViewGroup parent) {
- return getDropDownView(position, convertView, parent);
+ View view = getDropDownView(position, convertView, parent);
+ Drawable d = ctx.getResources()
+ .getDrawable(R.drawable.ic_expand_more_black_24dp);
+ if (d != null) {
+ d.setColorFilter(
+ ctx.getResources().getColor(R.color.spinner_arrow),
+ PorterDuff.Mode.SRC_IN);
+ }
+ ((TextView) view.findViewById(R.id.nameView))
+ .setCompoundDrawablesWithIntrinsicBounds(null, null, d, null);
+ return view;
}
@Override
diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
index 1d8b12fe0..2faf5f619 100644
--- a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
+++ b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
@@ -36,6 +36,11 @@ implements InvitationListener {
static final int REQUEST_BLUETOOTH = 1;
static final int REQUEST_CREATE_IDENTITY = 2;
+ private static final int STEP_CHOOSE = 1;
+ private static final int STEP_INVITE = 2;
+ private static final int STEP_CONFIRM = 3;
+ private static final int STEPS = 3;
+
private static final Logger LOG =
Logger.getLogger(AddContactActivity.class.getName());
@@ -189,10 +194,23 @@ implements InvitationListener {
}
}
+ @SuppressWarnings("ConstantConditions")
void setView(AddContactView view) {
this.view = view;
view.init(this);
setContentView(view);
+
+ int step = 0;
+ if (view instanceof ChooseIdentityView) step = STEP_CHOOSE;
+ else if (view instanceof InvitationCodeView) step = STEP_INVITE;
+ else if (view instanceof ConfirmationCodeView) step = STEP_CONFIRM;
+ if (step > 0) {
+ getSupportActionBar().setTitle(
+ String.format(getString(R.string.add_contact_title_step),
+ step, STEPS));
+ } else {
+ getSupportActionBar().setTitle(R.string.add_contact_title);
+ }
}
void reset(AddContactView view) {
diff --git a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
index 940de7e75..4dafd5645 100644
--- a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
+++ b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
@@ -9,7 +9,6 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.Spinner;
-import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.identity.CreateIdentityActivity;
@@ -45,11 +44,6 @@ implements OnItemSelectedListener, OnClickListener {
(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.invitation_bluetooth_start, this);
- // current step
- // TODO this could go into the ActionBar eventually
- TextView step = (TextView) view.findViewById(R.id.stepView);
- step.setText(String.format(ctx.getString(R.string.step), 1, 3));
-
adapter = new LocalAuthorSpinnerAdapter(ctx, false);
spinner = (Spinner) view.findViewById(R.id.spinner);
spinner.setAdapter(adapter);
diff --git a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java b/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
index 118744cc9..bfb2cc338 100644
--- a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
+++ b/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
@@ -15,7 +15,6 @@ import android.widget.TextView;
import org.briarproject.R;
import static android.content.Context.INPUT_METHOD_SERVICE;
-import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
class ConfirmationCodeView extends AddContactView {
@@ -40,11 +39,6 @@ class ConfirmationCodeView extends AddContactView {
(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.invitation_bluetooth_confirmation_code, this);
- // current step
- // TODO this could go into the ActionBar eventually
- TextView step = (TextView) view.findViewById(R.id.stepView);
- step.setText(String.format(ctx.getString(R.string.step), 3, 3));
-
// local confirmation code
TextView code = (TextView) view.findViewById(R.id.codeView);
int localCode = container.getLocalConfirmationCode();
diff --git a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java b/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
index ebd6fcc13..60c221798 100644
--- a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
+++ b/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
@@ -15,7 +15,6 @@ import android.widget.TextView;
import org.briarproject.R;
import static android.content.Context.INPUT_METHOD_SERVICE;
-import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
class InvitationCodeView extends AddContactView {
@@ -38,11 +37,6 @@ class InvitationCodeView extends AddContactView {
(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.invitation_bluetooth_invitation_code, this);
- // current step
- // TODO this could go into the ActionBar eventually
- TextView step = (TextView) view.findViewById(R.id.stepView);
- step.setText(String.format(ctx.getString(R.string.step), 2, 3));
-
// local invitation code
TextView code = (TextView) view.findViewById(R.id.codeView);
int localCode = container.getLocalInvitationCode();
diff --git a/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java b/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java
index 4615cd728..16818d36a 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java
+++ b/briar-android/src/org/briarproject/android/keyagreement/ChooseIdentityFragment.java
@@ -91,7 +91,7 @@ public class ChooseIdentityFragment extends BaseFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- return inflater.inflate(R.layout.invitation_bluetooth_start, container,
+ return inflater.inflate(R.layout.fragment_keyagreement_id, container,
false);
}
@@ -106,13 +106,12 @@ public class ChooseIdentityFragment extends BaseFragment
button = view.findViewById(R.id.continueButton);
button.setEnabled(false);
- button.setOnClickListener(
- new OnClickListener() {
- @Override
- public void onClick(View view) {
- lsnr.identitySelected(localAuthorId);
- }
- });
+ button.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ lsnr.identitySelected(localAuthorId);
+ }
+ });
loadLocalAuthors();
}
diff --git a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java b/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
index ee505a59e..cbe175d8e 100644
--- a/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
+++ b/briar-android/src/org/briarproject/android/keyagreement/ShowQrCodeFragment.java
@@ -10,13 +10,11 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Base64;
-import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -52,8 +50,6 @@ import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.WARNING;
@@ -78,8 +74,8 @@ public class ShowQrCodeFragment extends BaseEventFragment
@IoExecutor
protected Executor ioExecutor;
- private LinearLayout qrLayout;
private CameraView cameraView;
+ private View statusView;
private TextView status;
private ImageView qrCode;
@@ -119,8 +115,8 @@ public class ShowQrCodeFragment extends BaseEventFragment
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- qrLayout = (LinearLayout) view.findViewById(R.id.qr_layout);
cameraView = (CameraView) view.findViewById(R.id.camera_view);
+ statusView = view.findViewById(R.id.status_container);
status = (TextView) view.findViewById(R.id.connect_status);
qrCode = (ImageView) view.findViewById(R.id.qr_code);
}
@@ -132,10 +128,6 @@ public class ShowQrCodeFragment extends BaseEventFragment
getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
decoder = new QrCodeDecoder(this);
-
- Display display = getActivity().getWindowManager().getDefaultDisplay();
- boolean portrait = display.getWidth() < display.getHeight();
- qrLayout.setOrientation(portrait ? VERTICAL : HORIZONTAL);
}
@Override
@@ -165,13 +157,13 @@ public class ShowQrCodeFragment extends BaseEventFragment
@Override
public void onResume() {
super.onResume();
- if (!gotRemotePayload) openCamera();
+ openCamera();
}
@Override
public void onPause() {
super.onPause();
- if (!gotRemotePayload) releaseCamera();
+ releaseCamera();
}
@Override
@@ -183,7 +175,6 @@ public class ShowQrCodeFragment extends BaseEventFragment
private void startListening() {
task = keyAgreementTaskFactory.getTask();
- gotRemotePayload = false;
ioExecutor.execute(new Runnable() {
@Override
public void run() {
@@ -252,9 +243,11 @@ public class ShowQrCodeFragment extends BaseEventFragment
}
private void reset() {
+ statusView.setVisibility(View.INVISIBLE);
cameraView.setVisibility(View.VISIBLE);
+ gotRemotePayload = false;
+ cameraView.startConsumer();
startListening();
- openCamera();
}
private void qrCodeScanned(String content) {
@@ -262,7 +255,8 @@ public class ShowQrCodeFragment extends BaseEventFragment
// TODO use Base32
Payload remotePayload = payloadParser.parse(
Base64.decode(content, 0));
- cameraView.setVisibility(View.GONE);
+ cameraView.setVisibility(View.INVISIBLE);
+ statusView.setVisibility(View.VISIBLE);
status.setText(R.string.connecting_to_device);
task.connectAndRunProtocol(remotePayload);
} catch (IOException e) {
@@ -359,7 +353,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
LOG.info("Got result from decoder");
if (!gotRemotePayload) {
gotRemotePayload = true;
- releaseCamera();
+ cameraView.stopConsumer();
qrCodeScanned(result.getText());
}
}
diff --git a/briar-android/src/org/briarproject/android/util/CameraView.java b/briar-android/src/org/briarproject/android/util/CameraView.java
index 3cceafd50..d3690b189 100644
--- a/briar-android/src/org/briarproject/android/util/CameraView.java
+++ b/briar-android/src/org/briarproject/android/util/CameraView.java
@@ -97,8 +97,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
- if (autoFocus) camera.autoFocus(this);
- previewConsumer.start(camera);
+ startConsumer();
} catch (IOException | RuntimeException e) {
LOG.log(WARNING, "Error starting camera preview", e);
}
@@ -106,14 +105,23 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
private void stopPreview() {
try {
- previewConsumer.stop();
- if (autoFocus) camera.cancelAutoFocus();
+ stopConsumer();
camera.stopPreview();
} catch (RuntimeException e) {
LOG.log(WARNING, "Error stopping camera preview", e);
}
}
+ public void startConsumer() {
+ if (autoFocus) camera.autoFocus(this);
+ previewConsumer.start(camera);
+ }
+
+ public void stopConsumer() {
+ previewConsumer.stop();
+ if (autoFocus) camera.cancelAutoFocus();
+ }
+
private void setDisplayOrientation(int rotationDegrees) {
int orientation;
CameraInfo info = new CameraInfo();
@@ -124,7 +132,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
} else {
orientation = (info.orientation - rotationDegrees + 360) % 360;
}
- if(LOG.isLoggable(INFO))
+ if (LOG.isLoggable(INFO))
LOG.info("Display orientation " + orientation + " degrees");
try {
camera.setDisplayOrientation(orientation);
@@ -211,7 +219,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
}
}
if (bestSize != null) {
- if(LOG.isLoggable(INFO))
+ if (LOG.isLoggable(INFO))
LOG.info("Best size " + bestSize.width + "x" + bestSize.height);
params.setPreviewSize(bestSize.width, bestSize.height);
}