- net.sf.briar.android.AndroidModule
- net.sf.briar.android.helloworld.HelloWorldModule
- - net.sf.briar.android.invitation.AndroidInvitationModule
- net.sf.briar.clock.ClockModule
- net.sf.briar.crypto.CryptoModule
- net.sf.briar.db.DatabaseModule
+ - net.sf.briar.invitation.InvitationModule
- net.sf.briar.lifecycle.LifecycleModule
- net.sf.briar.plugins.PluginsModule
- net.sf.briar.protocol.ProtocolModule
diff --git a/src/net/sf/briar/android/helloworld/HelloWorldActivity.java b/src/net/sf/briar/android/helloworld/HelloWorldActivity.java
index 794495d24..98f9e52d5 100644
--- a/src/net/sf/briar/android/helloworld/HelloWorldActivity.java
+++ b/src/net/sf/briar/android/helloworld/HelloWorldActivity.java
@@ -9,7 +9,7 @@ import static java.util.logging.Level.INFO;
import java.util.logging.Logger;
import net.sf.briar.R;
-import net.sf.briar.android.invitation.NetworkSetupActivity;
+import net.sf.briar.android.invitation.AddContactActivity;
import roboguice.activity.RoboActivity;
import android.content.Intent;
import android.os.Bundle;
@@ -66,6 +66,6 @@ implements OnClickListener {
}
public void onClick(View view) {
- startActivity(new Intent(this, NetworkSetupActivity.class));
+ startActivity(new Intent(this, AddContactActivity.class));
}
}
diff --git a/src/net/sf/briar/android/invitation/AddContactActivity.java b/src/net/sf/briar/android/invitation/AddContactActivity.java
new file mode 100644
index 000000000..20c7cdd63
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/AddContactActivity.java
@@ -0,0 +1,128 @@
+package net.sf.briar.android.invitation;
+
+import net.sf.briar.api.crypto.CryptoComponent;
+import net.sf.briar.api.invitation.ConfirmationCallback;
+import net.sf.briar.api.invitation.ConnectionCallback;
+import net.sf.briar.api.invitation.InvitationManager;
+import roboguice.activity.RoboActivity;
+
+import com.google.inject.Inject;
+
+public class AddContactActivity extends RoboActivity
+implements ConnectionCallback, ConfirmationCallback {
+
+ @Inject private CryptoComponent crypto;
+ @Inject private InvitationManager invitationManager;
+
+ // All of the following must be accessed on the UI thread
+ private AddContactView view = null;
+ private String networkName = null;
+ private boolean useBluetooth = false;
+ private int localInvitationCode = -1;
+ private int localConfirmationCode = -1, remoteConfirmationCode = -1;
+ private ConfirmationCallback callback = null;
+ private boolean localMatched = false;
+ private boolean remoteCompared = false, remoteMatched = false;
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if(view == null) setView(new NetworkSetupView(this));
+ else view.populate();
+ }
+
+ void setView(AddContactView view) {
+ this.view = view;
+ view.init(this);
+ setContentView(view);
+ }
+
+ void setNetworkName(String networkName) {
+ this.networkName = networkName;
+ }
+
+ String getNetworkName() {
+ return networkName;
+ }
+
+ void setUseBluetooth(boolean useBluetooth) {
+ this.useBluetooth = useBluetooth;
+ }
+
+ boolean getUseBluetooth() {
+ return useBluetooth;
+ }
+
+ int generateLocalInvitationCode() {
+ localInvitationCode = crypto.generateInvitationCode();
+ return localInvitationCode;
+ }
+
+ int getLocalInvitationCode() {
+ return localInvitationCode;
+ }
+
+ void remoteInvitationCodeEntered(int code) {
+ setView(new ConnectionView(this));
+ localMatched = remoteCompared = remoteMatched = false;
+ invitationManager.connect(localInvitationCode, code, this);
+ }
+
+ int getLocalConfirmationCode() {
+ return localConfirmationCode;
+ }
+
+ void remoteConfirmationCodeEntered(int code) {
+ if(code == remoteConfirmationCode) {
+ localMatched = true;
+ if(remoteMatched) setView(new ContactAddedView(this));
+ else if(remoteCompared) setView(new CodesDoNotMatchView(this));
+ else setView(new WaitForContactView(this));
+ callback.codesMatch();
+ } else {
+ setView(new CodesDoNotMatchView(this));
+ callback.codesDoNotMatch();
+ }
+ }
+
+ public void connectionEstablished(final int localCode, final int remoteCode,
+ final ConfirmationCallback c) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ localConfirmationCode = localCode;
+ remoteConfirmationCode = remoteCode;
+ callback = c;
+ setView(new ConfirmationCodeView(AddContactActivity.this));
+ }
+ });
+ }
+
+ public void connectionNotEstablished() {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ setView(new ConnectionFailedView(AddContactActivity.this));
+ }
+ });
+ }
+
+ public void codesMatch() {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ remoteCompared = true;
+ remoteMatched = true;
+ if(localMatched)
+ setView(new ContactAddedView(AddContactActivity.this));
+ }
+ });
+ }
+
+ public void codesDoNotMatch() {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ remoteCompared = true;
+ if(localMatched)
+ setView(new CodesDoNotMatchView(AddContactActivity.this));
+ }
+ });
+ }
+}
diff --git a/src/net/sf/briar/android/invitation/AddContactView.java b/src/net/sf/briar/android/invitation/AddContactView.java
new file mode 100644
index 000000000..cd90bc0fd
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/AddContactView.java
@@ -0,0 +1,25 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import android.content.Context;
+import android.widget.LinearLayout;
+
+abstract class AddContactView extends LinearLayout {
+
+ protected AddContactActivity container = null;
+
+ AddContactView(Context context) {
+ super(context);
+ }
+
+ void init(AddContactActivity container) {
+ this.container = container;
+ setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
+ setOrientation(VERTICAL);
+ setGravity(CENTER_HORIZONTAL);
+ populate();
+ }
+
+ abstract void populate();
+}
diff --git a/src/net/sf/briar/android/invitation/AndroidInvitationModule.java b/src/net/sf/briar/android/invitation/AndroidInvitationModule.java
deleted file mode 100644
index c917e2256..000000000
--- a/src/net/sf/briar/android/invitation/AndroidInvitationModule.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import javax.inject.Singleton;
-
-import com.google.inject.AbstractModule;
-
-public class AndroidInvitationModule extends AbstractModule {
-
- @Override
- protected void configure() {
- bind(InvitationManager.class).to(InvitationManagerImpl.class).in(
- Singleton.class);
- }
-}
diff --git a/src/net/sf/briar/android/invitation/CodeEntryListener.java b/src/net/sf/briar/android/invitation/CodeEntryListener.java
index 1a8f7b3d8..43c324564 100644
--- a/src/net/sf/briar/android/invitation/CodeEntryListener.java
+++ b/src/net/sf/briar/android/invitation/CodeEntryListener.java
@@ -2,5 +2,5 @@ package net.sf.briar.android.invitation;
interface CodeEntryListener {
- void codeEntered(String code);
+ void codeEntered(int remoteCode);
}
diff --git a/src/net/sf/briar/android/invitation/CodeEntryWidget.java b/src/net/sf/briar/android/invitation/CodeEntryWidget.java
index 788e23b85..5f129481b 100644
--- a/src/net/sf/briar/android/invitation/CodeEntryWidget.java
+++ b/src/net/sf/briar/android/invitation/CodeEntryWidget.java
@@ -3,6 +3,7 @@ package net.sf.briar.android.invitation;
import static android.text.InputType.TYPE_CLASS_NUMBER;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
+import static net.sf.briar.api.plugins.InvitationConstants.MAX_CODE;
import net.sf.briar.R;
import android.content.Context;
import android.view.KeyEvent;
@@ -53,6 +54,7 @@ OnEditorActionListener, OnClickListener {
codeEntry.setMaxEms(5);
codeEntry.setMaxLines(1);
codeEntry.setInputType(TYPE_CLASS_NUMBER);
+ codeEntry.requestFocus();
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
@@ -63,16 +65,24 @@ OnEditorActionListener, OnClickListener {
}
public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) {
- validateAndReturnCode();
+ if(!validateAndReturnCode()) codeEntry.setText("");
return true;
}
public void onClick(View view) {
- validateAndReturnCode();
+ if(!validateAndReturnCode()) codeEntry.setText("");
}
- private void validateAndReturnCode() {
- CharSequence code = codeEntry.getText();
- if(code.length() == 6) listener.codeEntered(code.toString());
+ private boolean validateAndReturnCode() {
+ String remoteCodeString = codeEntry.getText().toString();
+ int remoteCode;
+ try {
+ remoteCode = Integer.valueOf(remoteCodeString);
+ } catch(NumberFormatException e) {
+ return false;
+ }
+ if(remoteCode < 0 || remoteCode > MAX_CODE) return false;
+ listener.codeEntered(remoteCode);
+ return true;
}
}
diff --git a/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java b/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java
deleted file mode 100644
index 861a80c70..000000000
--- a/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-import net.sf.briar.R;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class CodesDoNotMatchActivity extends Activity
-implements OnClickListener {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
-
- LinearLayout innerLayout = new LinearLayout(this);
- innerLayout.setOrientation(HORIZONTAL);
- innerLayout.setGravity(CENTER);
-
- ImageView icon = new ImageView(this);
- icon.setPadding(10, 10, 10, 10);
- icon.setImageResource(R.drawable.alerts_and_states_error);
- innerLayout.addView(icon);
-
- TextView failed = new TextView(this);
- failed.setTextSize(20);
- failed.setText(R.string.codes_do_not_match);
- innerLayout.addView(failed);
- layout.addView(innerLayout);
-
- TextView interfering = new TextView(this);
- interfering.setGravity(CENTER_HORIZONTAL);
- interfering.setPadding(0, 0, 0, 10);
- interfering.setText(R.string.interfering);
- layout.addView(interfering);
-
- Button tryAgain = new Button(this);
- LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- tryAgain.setLayoutParams(lp);
- tryAgain.setText(R.string.try_again_button);
- tryAgain.setOnClickListener(this);
- layout.addView(tryAgain);
-
- setContentView(layout);
- }
-
- public void onClick(View view) {
- Intent intent = new Intent(this, InvitationCodeActivity.class);
- intent.putExtras(getIntent().getExtras());
- startActivity(intent);
- finish();
- }
-}
diff --git a/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java b/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java
new file mode 100644
index 000000000..d801d01ae
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java
@@ -0,0 +1,58 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import net.sf.briar.R;
+import android.content.Context;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class CodesDoNotMatchView extends AddContactView
+implements OnClickListener {
+
+ CodesDoNotMatchView(Context ctx) {
+ super(ctx);
+ }
+
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ LinearLayout innerLayout = new LinearLayout(ctx);
+ innerLayout.setOrientation(HORIZONTAL);
+ innerLayout.setGravity(CENTER);
+
+ ImageView icon = new ImageView(ctx);
+ icon.setPadding(10, 10, 10, 10);
+ icon.setImageResource(R.drawable.alerts_and_states_error);
+ innerLayout.addView(icon);
+
+ TextView failed = new TextView(ctx);
+ failed.setTextSize(20);
+ failed.setText(R.string.codes_do_not_match);
+ innerLayout.addView(failed);
+ addView(innerLayout);
+
+ TextView interfering = new TextView(ctx);
+ interfering.setGravity(CENTER_HORIZONTAL);
+ interfering.setPadding(0, 0, 0, 10);
+ interfering.setText(R.string.interfering);
+ addView(interfering);
+
+ Button tryAgain = new Button(ctx);
+ LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
+ tryAgain.setLayoutParams(lp);
+ tryAgain.setText(R.string.try_again_button);
+ tryAgain.setOnClickListener(this);
+ addView(tryAgain);
+ }
+
+ public void onClick(View view) {
+ // Try again
+ container.setView(new NetworkSetupView(container));
+ }
+}
diff --git a/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java b/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java
deleted file mode 100644
index 220548b58..000000000
--- a/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-import net.sf.briar.R;
-import roboguice.activity.RoboActivity;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.google.inject.Inject;
-
-public class ConfirmationCodeActivity extends RoboActivity
-implements CodeEntryListener {
-
- @Inject private InvitationManager manager;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
-
- LinearLayout innerLayout = new LinearLayout(this);
- innerLayout.setOrientation(HORIZONTAL);
- innerLayout.setGravity(CENTER);
-
- ImageView icon = new ImageView(this);
- icon.setPadding(10, 10, 10, 10);
- icon.setImageResource(R.drawable.navigation_accept);
- innerLayout.addView(icon);
-
- TextView connected = new TextView(this);
- connected.setTextSize(20);
- connected.setText(R.string.connected_to_contact);
- innerLayout.addView(connected);
- layout.addView(innerLayout);
-
- TextView yourCode = new TextView(this);
- yourCode.setGravity(CENTER_HORIZONTAL);
- yourCode.setText(R.string.your_confirmation_code);
- layout.addView(yourCode);
-
- TextView code = new TextView(this);
- code.setGravity(CENTER_HORIZONTAL);
- code.setTextSize(50);
- code.setText(manager.getLocalConfirmationCode());
- layout.addView(code);
-
- CodeEntryWidget codeEntry = new CodeEntryWidget(this);
- Resources res = getResources();
- codeEntry.init(this, res.getString(R.string.enter_confirmation_code));
- layout.addView(codeEntry);
-
- setContentView(layout);
- }
-
- public void codeEntered(String code) {
- if(code.equals(manager.getRemoteConfirmationCode())) {
- Intent intent = new Intent(this, WaitForContactActivity.class);
- intent.putExtras(getIntent().getExtras());
- startActivity(intent);
- } else {
- Intent intent = new Intent(this, CodesDoNotMatchActivity.class);
- intent.putExtras(getIntent().getExtras());
- startActivity(intent);
- }
- finish();
- }
-}
diff --git a/src/net/sf/briar/android/invitation/ConfirmationCodeView.java b/src/net/sf/briar/android/invitation/ConfirmationCodeView.java
new file mode 100644
index 000000000..04688795f
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/ConfirmationCodeView.java
@@ -0,0 +1,58 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import net.sf.briar.R;
+import android.content.Context;
+import android.content.res.Resources;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class ConfirmationCodeView extends AddContactView
+implements CodeEntryListener {
+
+ ConfirmationCodeView(Context ctx) {
+ super(ctx);
+ }
+
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ LinearLayout innerLayout = new LinearLayout(ctx);
+ innerLayout.setOrientation(HORIZONTAL);
+ innerLayout.setGravity(CENTER);
+
+ ImageView icon = new ImageView(ctx);
+ icon.setPadding(10, 10, 10, 10);
+ icon.setImageResource(R.drawable.navigation_accept);
+ innerLayout.addView(icon);
+
+ TextView connected = new TextView(ctx);
+ connected.setTextSize(20);
+ connected.setText(R.string.connected_to_contact);
+ innerLayout.addView(connected);
+ addView(innerLayout);
+
+ TextView yourCode = new TextView(ctx);
+ yourCode.setGravity(CENTER_HORIZONTAL);
+ yourCode.setText(R.string.your_confirmation_code);
+ addView(yourCode);
+
+ TextView code = new TextView(ctx);
+ code.setGravity(CENTER_HORIZONTAL);
+ code.setTextSize(50);
+ int localCode = container.getLocalConfirmationCode();
+ code.setText(String.format("%06d", localCode));
+ addView(code);
+
+ CodeEntryWidget codeEntry = new CodeEntryWidget(ctx);
+ Resources res = getResources();
+ codeEntry.init(this, res.getString(R.string.enter_confirmation_code));
+ addView(codeEntry);
+ }
+
+ public void codeEntered(int remoteCode) {
+ container.remoteConfirmationCodeEntered(remoteCode);
+ }
+}
diff --git a/src/net/sf/briar/android/invitation/ConfirmationListener.java b/src/net/sf/briar/android/invitation/ConfirmationListener.java
deleted file mode 100644
index af2024676..000000000
--- a/src/net/sf/briar/android/invitation/ConfirmationListener.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package net.sf.briar.android.invitation;
-
-interface ConfirmationListener {
-
- void confirmationReceived();
-
- void confirmationNotReceived();
-}
diff --git a/src/net/sf/briar/android/invitation/ConnectionActivity.java b/src/net/sf/briar/android/invitation/ConnectionActivity.java
deleted file mode 100644
index 5ed8b80d3..000000000
--- a/src/net/sf/briar/android/invitation/ConnectionActivity.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-import net.sf.briar.R;
-import roboguice.activity.RoboActivity;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.google.inject.Inject;
-
-public class ConnectionActivity extends RoboActivity
-implements ConnectionListener {
-
- @Inject private InvitationManager manager;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
-
- Bundle b = getIntent().getExtras();
- String networkName = b.getString(
- "net.sf.briar.android.invitation.NETWORK_NAME");
- boolean useBluetooth = b.getBoolean(
- "net.sf.briar.android.invitation.USE_BLUETOOTH");
-
- TextView yourCode = new TextView(this);
- yourCode.setGravity(CENTER_HORIZONTAL);
- yourCode.setText(R.string.your_invitation_code);
- layout.addView(yourCode);
-
- TextView code = new TextView(this);
- code.setGravity(CENTER_HORIZONTAL);
- code.setTextSize(50);
- code.setText(manager.getLocalInvitationCode());
- layout.addView(code);
-
- if(networkName != null) {
- LinearLayout innerLayout = new LinearLayout(this);
- innerLayout.setOrientation(HORIZONTAL);
- innerLayout.setGravity(CENTER);
-
- ProgressBar progress = new ProgressBar(this);
- progress.setIndeterminate(true);
- progress.setPadding(0, 10, 10, 0);
- innerLayout.addView(progress);
-
- TextView connecting = new TextView(this);
- Resources res = getResources();
- String connectingVia = res.getString(R.string.connecting_wifi);
- connecting.setText(String.format(connectingVia, networkName));
- innerLayout.addView(connecting);
-
- layout.addView(innerLayout);
- manager.startWifiConnectionWorker(this);
- }
-
- if(useBluetooth) {
- LinearLayout innerLayout = new LinearLayout(this);
- innerLayout.setOrientation(HORIZONTAL);
- innerLayout.setGravity(CENTER);
-
- ProgressBar progress = new ProgressBar(this);
- progress.setPadding(0, 10, 10, 0);
- progress.setIndeterminate(true);
- innerLayout.addView(progress);
-
- TextView connecting = new TextView(this);
- connecting.setText(R.string.connecting_bluetooth);
- innerLayout.addView(connecting);
-
- layout.addView(innerLayout);
- manager.startBluetoothConnectionWorker(this);
- }
-
- setContentView(layout);
-
- manager.tryToConnect(this);
- }
-
- public void connectionEstablished() {
- final Intent intent = new Intent(this, ConfirmationCodeActivity.class);
- intent.putExtras(getIntent().getExtras());
- runOnUiThread(new Runnable() {
- public void run() {
- startActivity(intent);
- finish();
- }
- });
- }
-
- public void connectionNotEstablished() {
- final Intent intent = new Intent(this, ConnectionFailedActivity.class);
- runOnUiThread(new Runnable() {
- public void run() {
- startActivity(intent);
- finish();
- }
- });
- }
-}
diff --git a/src/net/sf/briar/android/invitation/ConnectionFailedActivity.java b/src/net/sf/briar/android/invitation/ConnectionFailedActivity.java
deleted file mode 100644
index a18e90a19..000000000
--- a/src/net/sf/briar/android/invitation/ConnectionFailedActivity.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-import net.sf.briar.R;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class ConnectionFailedActivity extends Activity
-implements WifiStateListener, BluetoothStateListener, OnClickListener {
-
- private WifiWidget wifi = null;
- private BluetoothWidget bluetooth = null;
- private Button tryAgainButton = null;
- private String networkName = null;
- private boolean useBluetooth = false;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
-
- LinearLayout innerLayout = new LinearLayout(this);
- innerLayout.setOrientation(HORIZONTAL);
- innerLayout.setGravity(CENTER);
-
- ImageView icon = new ImageView(this);
- icon.setPadding(10, 10, 10, 10);
- icon.setImageResource(R.drawable.alerts_and_states_error);
- innerLayout.addView(icon);
-
- TextView failed = new TextView(this);
- failed.setTextSize(20);
- failed.setText(R.string.connection_failed);
- innerLayout.addView(failed);
- layout.addView(innerLayout);
-
- TextView checkNetwork = new TextView(this);
- checkNetwork.setGravity(CENTER_HORIZONTAL);
- checkNetwork.setText(R.string.check_same_network);
- layout.addView(checkNetwork);
-
- wifi = new WifiWidget(this);
- wifi.init(this);
- layout.addView(wifi);
-
- bluetooth = new BluetoothWidget(this);
- bluetooth.init(this);
- layout.addView(bluetooth);
-
- tryAgainButton = new Button(this);
- LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- tryAgainButton.setLayoutParams(lp);
- tryAgainButton.setText(R.string.try_again_button);
- tryAgainButton.setOnClickListener(this);
- enabledOrDisableTryAgainButton();
- layout.addView(tryAgainButton);
-
- setContentView(layout);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- wifi.populate();
- bluetooth.populate();
- }
-
- public void wifiStateChanged(String networkName) {
- this.networkName = networkName;
- enabledOrDisableTryAgainButton();
- }
-
- public void bluetoothStateChanged(boolean enabled) {
- useBluetooth = enabled;
- enabledOrDisableTryAgainButton();
- }
-
- private void enabledOrDisableTryAgainButton() {
- if(tryAgainButton == null) return; // Activity not created yet
- if(useBluetooth || networkName != null) tryAgainButton.setEnabled(true);
- else tryAgainButton.setEnabled(false);
- }
-
- public void onClick(View view) {
- Intent intent = new Intent(this, InvitationCodeActivity.class);
- intent.putExtra("net.sf.briar.android.invitation.NETWORK_NAME",
- networkName);
- intent.putExtra("net.sf.briar.android.invitation.USE_BLUETOOTH",
- useBluetooth);
- startActivity(intent);
- finish();
- }
-}
diff --git a/src/net/sf/briar/android/invitation/ConnectionFailedView.java b/src/net/sf/briar/android/invitation/ConnectionFailedView.java
new file mode 100644
index 000000000..970314cd9
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/ConnectionFailedView.java
@@ -0,0 +1,86 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import net.sf.briar.R;
+import android.content.Context;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class ConnectionFailedView extends AddContactView
+implements WifiStateListener, BluetoothStateListener, OnClickListener {
+
+ private Button tryAgainButton = null;
+
+ ConnectionFailedView(Context ctx) {
+ super(ctx);
+ }
+
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ LinearLayout innerLayout = new LinearLayout(ctx);
+ innerLayout.setOrientation(HORIZONTAL);
+ innerLayout.setGravity(CENTER);
+
+ ImageView icon = new ImageView(ctx);
+ icon.setPadding(10, 10, 10, 10);
+ icon.setImageResource(R.drawable.alerts_and_states_error);
+ innerLayout.addView(icon);
+
+ TextView failed = new TextView(ctx);
+ failed.setTextSize(20);
+ failed.setText(R.string.connection_failed);
+ innerLayout.addView(failed);
+ addView(innerLayout);
+
+ TextView checkNetwork = new TextView(ctx);
+ checkNetwork.setGravity(CENTER_HORIZONTAL);
+ checkNetwork.setText(R.string.check_same_network);
+ addView(checkNetwork);
+
+ WifiWidget wifi = new WifiWidget(ctx);
+ wifi.init(this);
+ addView(wifi);
+
+ BluetoothWidget bluetooth = new BluetoothWidget(ctx);
+ bluetooth.init(this);
+ addView(bluetooth);
+
+ tryAgainButton = new Button(ctx);
+ LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
+ tryAgainButton.setLayoutParams(lp);
+ tryAgainButton.setText(R.string.try_again_button);
+ tryAgainButton.setOnClickListener(this);
+ enabledOrDisableTryAgainButton();
+ addView(tryAgainButton);
+ }
+
+ public void wifiStateChanged(String networkName) {
+ container.setNetworkName(networkName);
+ enabledOrDisableTryAgainButton();
+ }
+
+ public void bluetoothStateChanged(boolean enabled) {
+ container.setUseBluetooth(enabled);
+ enabledOrDisableTryAgainButton();
+ }
+
+ private void enabledOrDisableTryAgainButton() {
+ if(tryAgainButton == null) return; // Activity not created yet
+ boolean useBluetooth = container.getUseBluetooth();
+ String networkName = container.getNetworkName();
+ if(useBluetooth || networkName != null) tryAgainButton.setEnabled(true);
+ else tryAgainButton.setEnabled(false);
+ }
+
+ public void onClick(View view) {
+ // Try again
+ container.setView(new InvitationCodeView(container));
+ }
+}
diff --git a/src/net/sf/briar/android/invitation/ConnectionListener.java b/src/net/sf/briar/android/invitation/ConnectionListener.java
deleted file mode 100644
index a1bc643dc..000000000
--- a/src/net/sf/briar/android/invitation/ConnectionListener.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package net.sf.briar.android.invitation;
-
-interface ConnectionListener {
-
- void connectionEstablished();
-
- void connectionNotEstablished();
-}
diff --git a/src/net/sf/briar/android/invitation/ConnectionView.java b/src/net/sf/briar/android/invitation/ConnectionView.java
new file mode 100644
index 000000000..5a35c26d6
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/ConnectionView.java
@@ -0,0 +1,71 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import net.sf.briar.R;
+import android.content.Context;
+import android.content.res.Resources;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+public class ConnectionView extends AddContactView {
+
+ ConnectionView(Context ctx) {
+ super(ctx);
+ }
+
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ TextView yourCode = new TextView(ctx);
+ yourCode.setGravity(CENTER_HORIZONTAL);
+ yourCode.setText(R.string.your_invitation_code);
+ addView(yourCode);
+
+ TextView code = new TextView(ctx);
+ code.setGravity(CENTER_HORIZONTAL);
+ code.setTextSize(50);
+ int localCode = container.getLocalInvitationCode();
+ code.setText(String.format("%06d", localCode));
+ addView(code);
+
+ String networkName = container.getNetworkName();
+ if(networkName != null) {
+ LinearLayout innerLayout = new LinearLayout(ctx);
+ innerLayout.setOrientation(HORIZONTAL);
+ innerLayout.setGravity(CENTER);
+
+ ProgressBar progress = new ProgressBar(ctx);
+ progress.setIndeterminate(true);
+ progress.setPadding(0, 10, 10, 0);
+ innerLayout.addView(progress);
+
+ TextView connecting = new TextView(ctx);
+ Resources res = getResources();
+ String connectingVia = res.getString(R.string.connecting_wifi);
+ connecting.setText(String.format(connectingVia, networkName));
+ innerLayout.addView(connecting);
+
+ addView(innerLayout);
+ }
+
+ boolean useBluetooth = container.getUseBluetooth();
+ if(useBluetooth) {
+ LinearLayout innerLayout = new LinearLayout(ctx);
+ innerLayout.setOrientation(HORIZONTAL);
+ innerLayout.setGravity(CENTER);
+
+ ProgressBar progress = new ProgressBar(ctx);
+ progress.setPadding(0, 10, 10, 0);
+ progress.setIndeterminate(true);
+ innerLayout.addView(progress);
+
+ TextView connecting = new TextView(ctx);
+ connecting.setText(R.string.connecting_bluetooth);
+ innerLayout.addView(connecting);
+
+ addView(innerLayout);
+ }
+ }
+}
diff --git a/src/net/sf/briar/android/invitation/ContactAddedActivity.java b/src/net/sf/briar/android/invitation/ContactAddedView.java
similarity index 56%
rename from src/net/sf/briar/android/invitation/ContactAddedActivity.java
rename to src/net/sf/briar/android/invitation/ContactAddedView.java
index 8f7503280..25ad3a3ab 100644
--- a/src/net/sf/briar/android/invitation/ContactAddedActivity.java
+++ b/src/net/sf/briar/android/invitation/ContactAddedView.java
@@ -2,17 +2,11 @@ package net.sf.briar.android.invitation;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
import net.sf.briar.R;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
+import android.content.Context;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
@@ -20,43 +14,42 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-public class ContactAddedActivity extends Activity implements OnClickListener,
+public class ContactAddedView extends AddContactView implements OnClickListener,
OnEditorActionListener {
- private volatile Button done = null;
+ private Button done = null;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
+ ContactAddedView(Context ctx) {
+ super(ctx);
+ }
- LinearLayout innerLayout = new LinearLayout(this);
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
- ImageView icon = new ImageView(this);
+ ImageView icon = new ImageView(ctx);
icon.setImageResource(R.drawable.navigation_accept);
icon.setPadding(10, 10, 10, 10);
innerLayout.addView(icon);
- TextView failed = new TextView(this);
+ TextView failed = new TextView(ctx);
failed.setText(R.string.contact_added);
failed.setTextSize(20);
innerLayout.addView(failed);
- layout.addView(innerLayout);
+ addView(innerLayout);
- TextView enterNickname = new TextView(this);
+ TextView enterNickname = new TextView(ctx);
enterNickname.setGravity(CENTER_HORIZONTAL);
enterNickname.setText(R.string.enter_nickname);
- layout.addView(enterNickname);
+ addView(enterNickname);
- final Button addAnother = new Button(this);
- final Button done = new Button(this);
+ final Button addAnother = new Button(ctx);
+ final Button done = new Button(ctx);
this.done = done;
- EditText nicknameEntry = new EditText(this) {
+ EditText nicknameEntry = new EditText(ctx) {
@Override
protected void onTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
@@ -68,9 +61,9 @@ OnEditorActionListener {
nicknameEntry.setMaxEms(20);
nicknameEntry.setMaxLines(1);
nicknameEntry.setOnEditorActionListener(this);
- layout.addView(nicknameEntry);
+ addView(nicknameEntry);
- innerLayout = new LinearLayout(this);
+ innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
@@ -83,20 +76,16 @@ OnEditorActionListener {
done.setEnabled(false);
done.setOnClickListener(this);
innerLayout.addView(done);
- layout.addView(innerLayout);
-
- setContentView(layout);
+ addView(innerLayout);
}
public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) {
- if(textView.getText().length() > 0) finish();
+ if(textView.getText().length() > 0) container.finish();
return true;
}
public void onClick(View view) {
- if(done == null) return;
- if(view != done)
- startActivity(new Intent(this, NetworkSetupActivity.class));
- finish();
+ if(view == done) container.finish(); // Done
+ else container.setView(new NetworkSetupView(container)); // Add another
}
}
diff --git a/src/net/sf/briar/android/invitation/InvitationCodeActivity.java b/src/net/sf/briar/android/invitation/InvitationCodeActivity.java
deleted file mode 100644
index 8f3bb1b41..000000000
--- a/src/net/sf/briar/android/invitation/InvitationCodeActivity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.widget.LinearLayout.VERTICAL;
-import net.sf.briar.R;
-import roboguice.activity.RoboActivity;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.google.inject.Inject;
-
-public class InvitationCodeActivity extends RoboActivity
-implements CodeEntryListener {
-
- @Inject private InvitationManager manager;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
-
- TextView yourCode = new TextView(this);
- yourCode.setGravity(CENTER_HORIZONTAL);
- yourCode.setText(R.string.your_invitation_code);
- layout.addView(yourCode);
-
- TextView code = new TextView(this);
- code.setGravity(CENTER_HORIZONTAL);
- code.setTextSize(50);
- code.setText(manager.getLocalInvitationCode());
- layout.addView(code);
-
- CodeEntryWidget codeEntry = new CodeEntryWidget(this);
- Resources res = getResources();
- codeEntry.init(this, res.getString(R.string.enter_invitation_code));
- layout.addView(codeEntry);
-
- setContentView(layout);
- }
-
- public void codeEntered(String code) {
- manager.setRemoteInvitationCode(code);
- Intent intent = new Intent(this, ConnectionActivity.class);
- intent.putExtras(getIntent().getExtras());
- startActivity(intent);
- finish();
- }
-}
diff --git a/src/net/sf/briar/android/invitation/InvitationCodeView.java b/src/net/sf/briar/android/invitation/InvitationCodeView.java
new file mode 100644
index 000000000..fae6cca52
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/InvitationCodeView.java
@@ -0,0 +1,46 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import net.sf.briar.R;
+import android.content.Context;
+import android.content.res.Resources;
+import android.widget.TextView;
+
+public class InvitationCodeView extends AddContactView
+implements CodeEntryListener {
+
+ private int localCode = -1;
+
+ InvitationCodeView(Context ctx) {
+ super(ctx);
+ }
+
+ void init(AddContactActivity container) {
+ localCode = container.generateLocalInvitationCode();
+ super.init(container);
+ }
+
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ TextView yourCode = new TextView(ctx);
+ yourCode.setGravity(CENTER_HORIZONTAL);
+ yourCode.setText(R.string.your_invitation_code);
+ addView(yourCode);
+
+ TextView code = new TextView(ctx);
+ code.setGravity(CENTER_HORIZONTAL);
+ code.setTextSize(50);
+ code.setText(String.format("%06d", localCode));
+ addView(code);
+
+ CodeEntryWidget codeEntry = new CodeEntryWidget(ctx);
+ Resources res = getResources();
+ codeEntry.init(this, res.getString(R.string.enter_invitation_code));
+ addView(codeEntry);
+ }
+
+ public void codeEntered(int remoteCode) {
+ container.remoteInvitationCodeEntered(remoteCode);
+ }
+}
diff --git a/src/net/sf/briar/android/invitation/InvitationManager.java b/src/net/sf/briar/android/invitation/InvitationManager.java
deleted file mode 100644
index f77baa4c3..000000000
--- a/src/net/sf/briar/android/invitation/InvitationManager.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import android.content.Context;
-
-interface InvitationManager {
-
- int TIMEOUT = 20 * 1000;
-
- void tryToConnect(ConnectionListener listener);
-
- String getLocalInvitationCode();
-
- String getRemoteInvitationCode();
-
- void setRemoteInvitationCode(String code);
-
- void startWifiConnectionWorker(Context ctx);
-
- void startBluetoothConnectionWorker(Context ctx);
-
- String getLocalConfirmationCode();
-
- String getRemoteConfirmationCode();
-
- void startConfirmationWorker(ConfirmationListener listener);
-}
diff --git a/src/net/sf/briar/android/invitation/InvitationManagerImpl.java b/src/net/sf/briar/android/invitation/InvitationManagerImpl.java
deleted file mode 100644
index c5afcacec..000000000
--- a/src/net/sf/briar/android/invitation/InvitationManagerImpl.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import android.content.Context;
-import android.util.Log;
-
-class InvitationManagerImpl implements InvitationManager {
-
- public void tryToConnect(final ConnectionListener listener) {
- new Thread() {
- @Override
- public void run() {
- try {
- // FIXME
- Thread.sleep((long) (Math.random() * TIMEOUT));
- if(Math.random() < 0.5) listener.connectionEstablished();
- else listener.connectionNotEstablished();
- } catch(InterruptedException e) {
- Log.w(getClass().getName(), e.toString());
- listener.connectionNotEstablished();
- }
- }
- }.start();
- }
-
- public String getLocalInvitationCode() {
- // FIXME
- return "123456";
- }
-
- public String getRemoteInvitationCode() {
- // FIXME
- return "123456";
- }
-
- public void setRemoteInvitationCode(String code) {
- // FIXME
- }
-
- public void startWifiConnectionWorker(Context ctx) {
- // FIXME
- }
-
- public void startBluetoothConnectionWorker(Context ctx) {
- // FIXME
- }
-
- public String getLocalConfirmationCode() {
- // FIXME
- return "123456";
- }
-
- public String getRemoteConfirmationCode() {
- // FIXME
- return "123456";
- }
-
- public void startConfirmationWorker(ConfirmationListener listener) {
- // FIXME
- try {
- Thread.sleep(1000 + (int) (Math.random() * 4 * 1000));
- } catch(InterruptedException e) {
- Log.w(getClass().getName(), e.toString());
- Thread.currentThread().interrupt();
- }
- listener.confirmationReceived();
- }
-}
diff --git a/src/net/sf/briar/android/invitation/NetworkSetupActivity.java b/src/net/sf/briar/android/invitation/NetworkSetupActivity.java
deleted file mode 100644
index abe9065db..000000000
--- a/src/net/sf/briar/android/invitation/NetworkSetupActivity.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.widget.LinearLayout.VERTICAL;
-import net.sf.briar.R;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class NetworkSetupActivity extends Activity
-implements WifiStateListener, BluetoothStateListener, OnClickListener {
-
- private WifiWidget wifi = null;
- private BluetoothWidget bluetooth = null;
- private Button continueButton = null;
- private String networkName = null;
- private boolean useBluetooth = false;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
-
- TextView sameNetwork = new TextView(this);
- sameNetwork.setGravity(CENTER_HORIZONTAL);
- sameNetwork.setText(R.string.same_network);
- layout.addView(sameNetwork);
-
- wifi = new WifiWidget(this);
- wifi.init(this);
- layout.addView(wifi);
-
- bluetooth = new BluetoothWidget(this);
- bluetooth.init(this);
- layout.addView(bluetooth);
-
- continueButton = new Button(this);
- LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- continueButton.setLayoutParams(lp);
- continueButton.setText(R.string.continue_button);
- continueButton.setOnClickListener(this);
- enableOrDisableContinueButton();
- layout.addView(continueButton);
-
- setContentView(layout);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- wifi.populate();
- bluetooth.populate();
- }
-
- public void wifiStateChanged(final String name) {
- runOnUiThread(new Runnable() {
- public void run() {
- networkName = name;
- enableOrDisableContinueButton();
- }
- });
- }
-
- public void bluetoothStateChanged(final boolean enabled) {
- runOnUiThread(new Runnable() {
- public void run() {
- useBluetooth = enabled;
- enableOrDisableContinueButton();
- }
- });
- }
-
- private void enableOrDisableContinueButton() {
- if(continueButton == null) return; // Activity not created yet
- if(useBluetooth || networkName != null) continueButton.setEnabled(true);
- else continueButton.setEnabled(false);
- }
-
- public void onClick(View view) {
- Intent intent = new Intent(this, InvitationCodeActivity.class);
- intent.putExtra("net.sf.briar.android.invitation.NETWORK_NAME",
- networkName);
- intent.putExtra("net.sf.briar.android.invitation.USE_BLUETOOTH",
- useBluetooth);
- startActivity(intent);
- finish();
- }
-}
diff --git a/src/net/sf/briar/android/invitation/NetworkSetupView.java b/src/net/sf/briar/android/invitation/NetworkSetupView.java
new file mode 100644
index 000000000..da4d7671e
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/NetworkSetupView.java
@@ -0,0 +1,76 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import net.sf.briar.R;
+import android.content.Context;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+public class NetworkSetupView extends AddContactView
+implements WifiStateListener, BluetoothStateListener, OnClickListener {
+
+ private Button continueButton = null;
+
+ NetworkSetupView(Context ctx) {
+ super(ctx);
+ }
+
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ TextView sameNetwork = new TextView(ctx);
+ sameNetwork.setGravity(CENTER_HORIZONTAL);
+ sameNetwork.setText(R.string.same_network);
+ addView(sameNetwork);
+
+ WifiWidget wifi = new WifiWidget(ctx);
+ wifi.init(this);
+ addView(wifi);
+
+ BluetoothWidget bluetooth = new BluetoothWidget(ctx);
+ bluetooth.init(this);
+ addView(bluetooth);
+
+ continueButton = new Button(ctx);
+ LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
+ continueButton.setLayoutParams(lp);
+ continueButton.setText(R.string.continue_button);
+ continueButton.setOnClickListener(this);
+ enableOrDisableContinueButton();
+ addView(continueButton);
+ }
+
+ public void wifiStateChanged(final String networkName) {
+ container.runOnUiThread(new Runnable() {
+ public void run() {
+ container.setNetworkName(networkName);
+ enableOrDisableContinueButton();
+ }
+ });
+ }
+
+ public void bluetoothStateChanged(final boolean enabled) {
+ container.runOnUiThread(new Runnable() {
+ public void run() {
+ container.setUseBluetooth(enabled);
+ enableOrDisableContinueButton();
+ }
+ });
+ }
+
+ private void enableOrDisableContinueButton() {
+ if(continueButton == null) return; // Activity not created yet
+ boolean useBluetooth = container.getUseBluetooth();
+ String networkName = container.getNetworkName();
+ if(useBluetooth || networkName != null) continueButton.setEnabled(true);
+ else continueButton.setEnabled(false);
+ }
+
+ public void onClick(View view) {
+ // Continue
+ container.setView(new InvitationCodeView(container));
+ }
+}
diff --git a/src/net/sf/briar/android/invitation/WaitForContactActivity.java b/src/net/sf/briar/android/invitation/WaitForContactActivity.java
deleted file mode 100644
index 7d93aea62..000000000
--- a/src/net/sf/briar/android/invitation/WaitForContactActivity.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package net.sf.briar.android.invitation;
-
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.widget.LinearLayout.HORIZONTAL;
-import static android.widget.LinearLayout.VERTICAL;
-import net.sf.briar.R;
-import roboguice.activity.RoboActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.google.inject.Inject;
-
-public class WaitForContactActivity extends RoboActivity
-implements ConfirmationListener {
-
- @Inject private InvitationManager manager;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
-
- LinearLayout innerLayout = new LinearLayout(this);
- innerLayout.setOrientation(HORIZONTAL);
- innerLayout.setGravity(CENTER);
-
- ImageView icon = new ImageView(this);
- icon.setPadding(10, 10, 10, 10);
- icon.setImageResource(R.drawable.navigation_accept);
- innerLayout.addView(icon);
-
- TextView failed = new TextView(this);
- failed.setTextSize(20);
- failed.setText(R.string.connected_to_contact);
- innerLayout.addView(failed);
- layout.addView(innerLayout);
-
- TextView yourCode = new TextView(this);
- yourCode.setGravity(CENTER_HORIZONTAL);
- yourCode.setText(R.string.your_confirmation_code);
- layout.addView(yourCode);
-
- TextView code = new TextView(this);
- code.setGravity(CENTER_HORIZONTAL);
- code.setTextSize(50);
- code.setText(manager.getLocalConfirmationCode());
- layout.addView(code);
-
- innerLayout = new LinearLayout(this);
- innerLayout.setOrientation(HORIZONTAL);
- innerLayout.setGravity(CENTER);
-
- ProgressBar progress = new ProgressBar(this);
- progress.setIndeterminate(true);
- progress.setPadding(0, 10, 10, 0);
- innerLayout.addView(progress);
-
- TextView connecting = new TextView(this);
- connecting.setText(R.string.waiting_for_contact);
- innerLayout.addView(connecting);
- layout.addView(innerLayout);
-
- setContentView(layout);
-
- manager.startConfirmationWorker(this);
- }
-
- public void confirmationReceived() {
- startActivity(new Intent(this, ContactAddedActivity.class));
- finish();
- }
-
- public void confirmationNotReceived() {
- Intent intent = new Intent(this, CodesDoNotMatchActivity.class);
- intent.putExtras(getIntent().getExtras());
- startActivity(intent);
- finish();
- }
-}
diff --git a/src/net/sf/briar/android/invitation/WaitForContactView.java b/src/net/sf/briar/android/invitation/WaitForContactView.java
new file mode 100644
index 000000000..d7c5824cb
--- /dev/null
+++ b/src/net/sf/briar/android/invitation/WaitForContactView.java
@@ -0,0 +1,62 @@
+package net.sf.briar.android.invitation;
+
+import static android.view.Gravity.CENTER;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import net.sf.briar.R;
+import android.content.Context;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+public class WaitForContactView extends AddContactView {
+
+ WaitForContactView(Context ctx) {
+ super(ctx);
+ }
+
+ void populate() {
+ removeAllViews();
+ Context ctx = getContext();
+ LinearLayout innerLayout = new LinearLayout(ctx);
+ innerLayout.setOrientation(HORIZONTAL);
+ innerLayout.setGravity(CENTER);
+
+ ImageView icon = new ImageView(ctx);
+ icon.setPadding(10, 10, 10, 10);
+ icon.setImageResource(R.drawable.navigation_accept);
+ innerLayout.addView(icon);
+
+ TextView failed = new TextView(ctx);
+ failed.setTextSize(20);
+ failed.setText(R.string.connected_to_contact);
+ innerLayout.addView(failed);
+ addView(innerLayout);
+
+ TextView yourCode = new TextView(ctx);
+ yourCode.setGravity(CENTER_HORIZONTAL);
+ yourCode.setText(R.string.your_confirmation_code);
+ addView(yourCode);
+
+ TextView code = new TextView(ctx);
+ code.setGravity(CENTER_HORIZONTAL);
+ code.setTextSize(50);
+ int localCode = container.getLocalConfirmationCode();
+ code.setText(String.format("%06d", localCode));
+ addView(code);
+
+ innerLayout = new LinearLayout(ctx);
+ innerLayout.setOrientation(HORIZONTAL);
+ innerLayout.setGravity(CENTER);
+
+ ProgressBar progress = new ProgressBar(ctx);
+ progress.setIndeterminate(true);
+ progress.setPadding(0, 10, 10, 0);
+ innerLayout.addView(progress);
+
+ TextView connecting = new TextView(ctx);
+ connecting.setText(R.string.waiting_for_contact);
+ innerLayout.addView(connecting);
+ addView(innerLayout);
+ }
+}
diff --git a/src/net/sf/briar/api/crypto/CryptoComponent.java b/src/net/sf/briar/api/crypto/CryptoComponent.java
index c6e4b34fd..ae63dfa3d 100644
--- a/src/net/sf/briar/api/crypto/CryptoComponent.java
+++ b/src/net/sf/briar/api/crypto/CryptoComponent.java
@@ -11,7 +11,7 @@ public interface CryptoComponent {
/**
* Derives a tag key from the given temporary secret.
- * @param alice Indicates whether the key is for connections initiated by
+ * @param alice indicates whether the key is for connections initiated by
* Alice or Bob.
*/
ErasableKey deriveTagKey(byte[] secret, boolean alice);
@@ -19,9 +19,9 @@ public interface CryptoComponent {
/**
* Derives a frame key from the given temporary secret and connection
* number.
- * @param alice Indicates whether the key is for a connection initiated by
+ * @param alice indicates whether the key is for a connection initiated by
* Alice or Bob.
- * @param initiator Indicates whether the key is for the initiator's or the
+ * @param initiator indicates whether the key is for the initiator's or the
* responder's side of the connection.
*/
ErasableKey deriveFrameKey(byte[] secret, long connection, boolean alice,
@@ -30,7 +30,7 @@ public interface CryptoComponent {
/**
* Derives an initial shared secret from two public keys and one of the
* corresponding private keys.
- * @param alice Indicates whether the private key belongs to Alice or Bob.
+ * @param alice indicates whether the private key belongs to Alice or Bob.
*/
byte[] deriveInitialSecret(byte[] ourPublicKey, byte[] theirPublicKey,
PrivateKey ourPrivateKey, boolean alice);
@@ -67,7 +67,7 @@ public interface CryptoComponent {
MessageDigest getMessageDigest();
- PseudoRandom getPseudoRandom(int seed);
+ PseudoRandom getPseudoRandom(int seed1, int seed2);
SecureRandom getSecureRandom();
diff --git a/src/net/sf/briar/api/db/DatabaseComponent.java b/src/net/sf/briar/api/db/DatabaseComponent.java
index cc6ae698f..b58483023 100644
--- a/src/net/sf/briar/api/db/DatabaseComponent.java
+++ b/src/net/sf/briar/api/db/DatabaseComponent.java
@@ -34,7 +34,7 @@ public interface DatabaseComponent {
/**
* Opens the database.
- * @param resume True to reopen an existing database or false to create a
+ * @param resume true to reopen an existing database or false to create a
* new one.
*/
void open(boolean resume) throws DbException, IOException;
diff --git a/src/net/sf/briar/api/invitation/ConfirmationCallback.java b/src/net/sf/briar/api/invitation/ConfirmationCallback.java
new file mode 100644
index 000000000..652773f86
--- /dev/null
+++ b/src/net/sf/briar/api/invitation/ConfirmationCallback.java
@@ -0,0 +1,14 @@
+package net.sf.briar.api.invitation;
+
+/** An interface for informing a peer of whether confirmation codes match. */
+public interface ConfirmationCallback {
+
+ /** Called to indicate that the confirmation codes match. */
+ void codesMatch();
+
+ /**
+ * Called to indicate that either the confirmation codes do not match or
+ * the result of the comparison is unknown.
+ */
+ void codesDoNotMatch();
+}
diff --git a/src/net/sf/briar/api/invitation/ConnectionCallback.java b/src/net/sf/briar/api/invitation/ConnectionCallback.java
new file mode 100644
index 000000000..56ce5c73b
--- /dev/null
+++ b/src/net/sf/briar/api/invitation/ConnectionCallback.java
@@ -0,0 +1,18 @@
+package net.sf.briar.api.invitation;
+
+/** An interface for monitoring the status of an invitation connection. */
+public interface ConnectionCallback extends ConfirmationCallback {
+
+ /**
+ * Called if the connection is successfully established.
+ * @param localCode the local confirmation code.
+ * @param remoteCode the remote confirmation code.
+ * @param c a callback to inform the remote peer of the result of the local
+ * peer's confirmation code comparison.
+ */
+ void connectionEstablished(int localCode, int remoteCode,
+ ConfirmationCallback c);
+
+ /** Called if the connection cannot be established. */
+ void connectionNotEstablished();
+}
diff --git a/src/net/sf/briar/api/invitation/InvitationManager.java b/src/net/sf/briar/api/invitation/InvitationManager.java
new file mode 100644
index 000000000..e0ae1774c
--- /dev/null
+++ b/src/net/sf/briar/api/invitation/InvitationManager.java
@@ -0,0 +1,17 @@
+package net.sf.briar.api.invitation;
+
+/**
+ * Allows invitation connections to be established and their status to be
+ * monitored.
+ */
+public interface InvitationManager {
+
+ /**
+ * Tries to establish an invitation connection.
+ * @param localCode the local invitation code.
+ * @param remoteCode the remote invitation code.
+ * @param c1 a callback to be informed of the connection's status and the
+ * result of the remote peer's confirmation code comparison.
+ */
+ void connect(int localCode, int remoteCode, ConnectionCallback c);
+}
diff --git a/src/net/sf/briar/api/plugins/InvitationConstants.java b/src/net/sf/briar/api/plugins/InvitationConstants.java
index 6941ad0e0..f27d35b82 100644
--- a/src/net/sf/briar/api/plugins/InvitationConstants.java
+++ b/src/net/sf/briar/api/plugins/InvitationConstants.java
@@ -6,9 +6,9 @@ public interface InvitationConstants {
int CODE_BITS = 19; // Codes must fit into six decimal digits
- int MAX_CODE = 1 << CODE_BITS - 1;
+ int MAX_CODE = (1 << CODE_BITS) - 1;
- int HASH_LENGTH = 48;
+ int HASH_LENGTH = 48; // Bytes
- int MAX_PUBLIC_KEY_LENGTH = 120;
+ int MAX_PUBLIC_KEY_LENGTH = 120; // Bytes
}
diff --git a/src/net/sf/briar/api/plugins/Plugin.java b/src/net/sf/briar/api/plugins/Plugin.java
index 319f58148..4debef1e2 100644
--- a/src/net/sf/briar/api/plugins/Plugin.java
+++ b/src/net/sf/briar/api/plugins/Plugin.java
@@ -21,14 +21,14 @@ public interface Plugin {
void stop() throws IOException;
/**
- * Returns true if the plugin's poll() method should be called
- * periodically to attempt to establish connections.
+ * Returns true if the plugin's {@link Plugin#poll(Collection)} method
+ * should be called periodically to attempt to establish connections.
*/
boolean shouldPoll();
/**
* Returns the desired interval in milliseconds between calls to the
- * plugin's poll() method.
+ * plugin's {@link Plugin#poll(Collection)} method.
*/
long getPollingInterval();
diff --git a/src/net/sf/briar/api/plugins/PluginCallback.java b/src/net/sf/briar/api/plugins/PluginCallback.java
index 63435f9f5..895d4a8b2 100644
--- a/src/net/sf/briar/api/plugins/PluginCallback.java
+++ b/src/net/sf/briar/api/plugins/PluginCallback.java
@@ -33,7 +33,7 @@ public interface PluginCallback {
* Presents the user with a choice among two or more named options and
* returns the user's response. The message may consist of a translatable
* format string and arguments.
- * @return An index into the array of options indicating the user's choice,
+ * @return an index into the array of options indicating the user's choice,
* or -1 if the user cancelled the choice.
*/
int showChoice(String[] options, String... message);
diff --git a/src/net/sf/briar/api/plugins/PluginManager.java b/src/net/sf/briar/api/plugins/PluginManager.java
index f3f49ab71..77bc1dc98 100644
--- a/src/net/sf/briar/api/plugins/PluginManager.java
+++ b/src/net/sf/briar/api/plugins/PluginManager.java
@@ -5,6 +5,10 @@ import java.util.Collection;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import android.content.Context;
+/**
+ * Responsible for starting transport plugins at startup, stopping them at
+ * shutdown, and providing access to plugins for exchanging invitations.
+ */
public interface PluginManager {
/**
diff --git a/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java b/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
index b7f0f35ed..ffda7ef0d 100644
--- a/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
+++ b/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
@@ -9,8 +9,7 @@ import java.io.InputStream;
*/
public interface SimplexTransportReader {
- /** Returns an input stream for reading from the transport.
- * @throws IOException */
+ /** Returns an input stream for reading from the transport. */
InputStream getInputStream() throws IOException;
/**
diff --git a/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java b/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
index c48b2795d..152b7fd67 100644
--- a/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
+++ b/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
@@ -12,8 +12,7 @@ public interface SimplexTransportWriter {
/** Returns the capacity of the transport in bytes. */
long getCapacity();
- /** Returns an output stream for writing to the transport.
- * @throws IOException */
+ /** Returns an output stream for writing to the transport. */
OutputStream getOutputStream() throws IOException;
/**
diff --git a/src/net/sf/briar/api/ui/UiCallback.java b/src/net/sf/briar/api/ui/UiCallback.java
index d241eadb3..4903ef89e 100644
--- a/src/net/sf/briar/api/ui/UiCallback.java
+++ b/src/net/sf/briar/api/ui/UiCallback.java
@@ -6,7 +6,7 @@ public interface UiCallback {
* Presents the user with a choice among two or more named options and
* returns the user's response. The message may consist of a translatable
* format string and arguments.
- * @return An index into the array of options indicating the user's choice,
+ * @return an index into the array of options indicating the user's choice,
* or -1 if the user cancelled the choice.
*/
int showChoice(String[] options, String... message);
diff --git a/src/net/sf/briar/crypto/CryptoComponentImpl.java b/src/net/sf/briar/crypto/CryptoComponentImpl.java
index bc1c07a53..7ac9d230e 100644
--- a/src/net/sf/briar/crypto/CryptoComponentImpl.java
+++ b/src/net/sf/briar/crypto/CryptoComponentImpl.java
@@ -274,8 +274,8 @@ class CryptoComponentImpl implements CryptoComponent {
}
}
- public PseudoRandom getPseudoRandom(int seed) {
- return new PseudoRandomImpl(getMessageDigest(), seed);
+ public PseudoRandom getPseudoRandom(int seed1, int seed2) {
+ return new PseudoRandomImpl(getMessageDigest(), seed1, seed2);
}
public SecureRandom getSecureRandom() {
diff --git a/src/net/sf/briar/crypto/PseudoRandomImpl.java b/src/net/sf/briar/crypto/PseudoRandomImpl.java
index 1f74586e4..c2751cf25 100644
--- a/src/net/sf/briar/crypto/PseudoRandomImpl.java
+++ b/src/net/sf/briar/crypto/PseudoRandomImpl.java
@@ -11,10 +11,11 @@ class PseudoRandomImpl implements PseudoRandom {
private byte[] state;
private int offset;
- PseudoRandomImpl(MessageDigest messageDigest, int seed) {
+ PseudoRandomImpl(MessageDigest messageDigest, int seed1, int seed2) {
this.messageDigest = messageDigest;
- byte[] seedBytes = new byte[4];
- ByteUtils.writeUint32(seed, seedBytes, 0);
+ byte[] seedBytes = new byte[8];
+ ByteUtils.writeUint32(seed1, seedBytes, 0);
+ ByteUtils.writeUint32(seed2, seedBytes, 4);
messageDigest.update(seedBytes);
state = messageDigest.digest();
offset = 0;
diff --git a/src/net/sf/briar/db/Database.java b/src/net/sf/briar/db/Database.java
index 5303fae3d..3959e735d 100644
--- a/src/net/sf/briar/db/Database.java
+++ b/src/net/sf/briar/db/Database.java
@@ -24,9 +24,9 @@ import net.sf.briar.api.transport.TemporarySecret;
/**
* A low-level interface to the database (DatabaseComponent provides a
* high-level interface). Most operations take a transaction argument, which is
- * obtained by calling startTransaction(). Every transaction must be
- * terminated by calling either abortTransaction() or commitTransaction(),
- * even if an exception is thrown.
+ * obtained by calling {@link #startTransaction()}. Every transaction must be
+ * terminated by calling either {@link #abortTransaction(T)} or
+ * {@link #commitTransaction(T)}, even if an exception is thrown.
*
* Locking is provided by the DatabaseComponent implementation. To prevent
* deadlock, locks must be acquired in the following order:
@@ -45,7 +45,7 @@ interface Database {
/**
* Opens the database.
- * @param resume True to reopen an existing database, false to create a
+ * @param resume true to reopen an existing database, false to create a
* new one.
*/
void open(boolean resume) throws DbException, IOException;
diff --git a/src/net/sf/briar/db/DatabaseComponentImpl.java b/src/net/sf/briar/db/DatabaseComponentImpl.java
index 147226633..84d63e81f 100644
--- a/src/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/src/net/sf/briar/db/DatabaseComponentImpl.java
@@ -326,7 +326,7 @@ DatabaseCleaner.Callback {
* that have changed from sendable to not sendable, or vice versa.
*
* Locking: message write.
- * @param increment True if the message's sendability has changed from 0 to
+ * @param increment true if the message's sendability has changed from 0 to
* greater than 0, or false if it has changed from greater than 0 to 0.
*/
private int updateAncestorSendability(T txn, MessageId m, boolean increment)
@@ -1396,7 +1396,7 @@ DatabaseCleaner.Callback {
* the ancestors of those messages if necessary.
*
* Locking: message write.
- * @param increment True if the user's rating for the author has changed
+ * @param increment true if the user's rating for the author has changed
* from not good to good, or false if it has changed from good to not good.
*/
private void updateAuthorSendability(T txn, AuthorId a, boolean increment)
diff --git a/src/net/sf/briar/invitation/InvitationManagerImpl.java b/src/net/sf/briar/invitation/InvitationManagerImpl.java
new file mode 100644
index 000000000..4d4967a06
--- /dev/null
+++ b/src/net/sf/briar/invitation/InvitationManagerImpl.java
@@ -0,0 +1,81 @@
+package net.sf.briar.invitation;
+
+import java.util.Collection;
+
+import net.sf.briar.api.crypto.CryptoComponent;
+import net.sf.briar.api.crypto.PseudoRandom;
+import net.sf.briar.api.invitation.ConfirmationCallback;
+import net.sf.briar.api.invitation.ConnectionCallback;
+import net.sf.briar.api.invitation.InvitationManager;
+import net.sf.briar.api.plugins.PluginManager;
+import net.sf.briar.api.plugins.duplex.DuplexPlugin;
+
+import com.google.inject.Inject;
+
+class InvitationManagerImpl implements InvitationManager {
+
+ private final CryptoComponent crypto;
+ private final PluginManager pluginManager;
+
+ @Inject
+ InvitationManagerImpl(CryptoComponent crypto, PluginManager pluginManager) {
+ this.crypto = crypto;
+ this.pluginManager = pluginManager;
+ }
+
+ public void connect(int localCode, int remoteCode, ConnectionCallback c) {
+ Collection plugins = pluginManager.getInvitationPlugins();
+ // Alice is the party with the smaller invitation code
+ if(localCode < remoteCode) {
+ PseudoRandom r = crypto.getPseudoRandom(localCode, remoteCode);
+ startAliceInvitationWorker(plugins, r, c);
+ } else {
+ PseudoRandom r = crypto.getPseudoRandom(remoteCode, localCode);
+ startBobInvitationWorker(plugins, r, c);
+ }
+ }
+
+ private void startAliceInvitationWorker(Collection plugins,
+ PseudoRandom r, ConnectionCallback c) {
+ // FIXME
+ new FakeWorkerThread(c).start();
+ }
+
+ private void startBobInvitationWorker(Collection plugins,
+ PseudoRandom r, ConnectionCallback c) {
+ // FIXME
+ new FakeWorkerThread(c).start();
+ }
+
+ private static class FakeWorkerThread extends Thread {
+
+ private final ConnectionCallback callback;
+
+ private FakeWorkerThread(ConnectionCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void run() {
+ try {
+ Thread.sleep((long) (Math.random() * 30 * 1000));
+ } catch(InterruptedException ignored) {}
+ if(Math.random() < 0.8) {
+ callback.connectionNotEstablished();
+ } else {
+ callback.connectionEstablished(123456, 123456,
+ new ConfirmationCallback() {
+
+ public void codesMatch() {}
+
+ public void codesDoNotMatch() {}
+ });
+ try {
+ Thread.sleep((long) (Math.random() * 10 * 1000));
+ } catch(InterruptedException ignored) {}
+ if(Math.random() < 0.5) callback.codesMatch();
+ else callback.codesDoNotMatch();
+ }
+ }
+ }
+}
diff --git a/src/net/sf/briar/invitation/InvitationModule.java b/src/net/sf/briar/invitation/InvitationModule.java
new file mode 100644
index 000000000..41197dc7f
--- /dev/null
+++ b/src/net/sf/briar/invitation/InvitationModule.java
@@ -0,0 +1,13 @@
+package net.sf.briar.invitation;
+
+import net.sf.briar.api.invitation.InvitationManager;
+
+import com.google.inject.AbstractModule;
+
+public class InvitationModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ bind(InvitationManager.class).to(InvitationManagerImpl.class);
+ }
+}
diff --git a/src/net/sf/briar/plugins/PluginManagerImpl.java b/src/net/sf/briar/plugins/PluginManagerImpl.java
index 4fb274889..110e201c0 100644
--- a/src/net/sf/briar/plugins/PluginManagerImpl.java
+++ b/src/net/sf/briar/plugins/PluginManagerImpl.java
@@ -95,6 +95,7 @@ class PluginManagerImpl implements PluginManager {
public synchronized int start(Context appContext) {
Set ids = new HashSet();
// Instantiate and start the simplex plugins
+ if(LOG.isLoggable(INFO)) LOG.info("Starting simplex plugins");
for(String s : getSimplexPluginFactoryNames()) {
try {
Class> c = Class.forName(s);
@@ -128,6 +129,7 @@ class PluginManagerImpl implements PluginManager {
}
}
// Instantiate and start the duplex plugins
+ if(LOG.isLoggable(INFO)) LOG.info("Starting duplex plugins");
for(String s : getDuplexPluginFactoryNames()) {
try {
Class> c = Class.forName(s);
@@ -161,6 +163,7 @@ class PluginManagerImpl implements PluginManager {
}
}
// Start the poller
+ if(LOG.isLoggable(INFO)) LOG.info("Starting poller");
List plugins = new ArrayList();
plugins.addAll(simplexPlugins);
plugins.addAll(duplexPlugins);
@@ -182,8 +185,10 @@ class PluginManagerImpl implements PluginManager {
public synchronized int stop() {
int stopped = 0;
// Stop the poller
+ if(LOG.isLoggable(INFO)) LOG.info("Stopping poller");
poller.stop();
// Stop the simplex plugins
+ if(LOG.isLoggable(INFO)) LOG.info("Stopping simplex plugins");
for(SimplexPlugin plugin : simplexPlugins) {
try {
plugin.stop();
@@ -192,7 +197,9 @@ class PluginManagerImpl implements PluginManager {
if(LOG.isLoggable(WARNING)) LOG.warning(e.toString());
}
}
+ simplexPlugins.clear();
// Stop the duplex plugins
+ if(LOG.isLoggable(INFO)) LOG.info("Stopping duplex plugins");
for(DuplexPlugin plugin : duplexPlugins) {
try {
plugin.stop();
@@ -201,7 +208,9 @@ class PluginManagerImpl implements PluginManager {
if(LOG.isLoggable(WARNING)) LOG.warning(e.toString());
}
}
+ duplexPlugins.clear();
// Shut down the executors
+ if(LOG.isLoggable(INFO)) LOG.info("Stopping executors");
pluginExecutor.shutdown();
androidExecutor.shutdown();
// Return the number of plugins successfully stopped
diff --git a/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java b/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
index 1c8b196c8..bfd543d06 100644
--- a/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
+++ b/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
@@ -349,10 +349,10 @@ class DroidtoothPlugin implements DuplexPlugin {
if(!running) return;
}
if(adapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE) return;
- Intent intent = new Intent(ACTION_REQUEST_DISCOVERABLE);
- intent.putExtra(EXTRA_DISCOVERABLE_DURATION, 60);
- intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
- appContext.startActivity(intent);
+ Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
+ i.putExtra(EXTRA_DISCOVERABLE_DURATION, 120);
+ i.addFlags(FLAG_ACTIVITY_NEW_TASK);
+ appContext.startActivity(i);
}
private static class BluetoothStateReceiver extends BroadcastReceiver {
diff --git a/src/net/sf/briar/transport/ConnectionWriterImpl.java b/src/net/sf/briar/transport/ConnectionWriterImpl.java
index d27905938..4d1b2c571 100644
--- a/src/net/sf/briar/transport/ConnectionWriterImpl.java
+++ b/src/net/sf/briar/transport/ConnectionWriterImpl.java
@@ -11,7 +11,7 @@ import net.sf.briar.api.transport.ConnectionWriter;
/**
* A ConnectionWriter that buffers its input and writes a frame whenever there
- * is a full frame to write or the flush() method is called.
+ * is a full frame to write or the {@link #flush()} method is called.
*
* This class is not thread-safe.
*/