diff --git a/AndroidManifest.xml b/AndroidManifest.xml index e9dfd8090b5542eb6fa562ae1c19f357b769dc0f..799292896076ba4d1e6f9dde0ab63b54c972806c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3,11 +3,23 @@ package="net.sf.briar" android:versionCode="1" android:versionName="1.0" > + <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="16" /> + <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.INTERNET" /> - <application android:label="@string/app_name" > + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> + <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + <service android:name=".HelloWorldService" android:exported="false" > + <intent-filter> + <action android:name=".HelloWorldService" /> + </intent-filter> + </service> <activity android:name=".HelloWorldActivity" android:label="@string/app_name" > @@ -16,10 +28,37 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <service android:name=".HelloWorldService" android:exported="false" > - <intent-filter> - <action android:name="net.sf.briar.HelloWorldService" /> - </intent-filter> - </service> + <activity + android:name=".android.invitation.NetworkSetupActivity" + android:label="@string/title" > + </activity> + <activity + android:name=".android.invitation.InvitationCodeActivity" + android:label="@string/title" > + </activity> + <activity + android:name=".android.invitation.ConnectionActivity" + android:label="@string/title" > + </activity> + <activity + android:name=".android.invitation.ConnectionFailedActivity" + android:label="@string/title" > + </activity> + <activity + android:name=".android.invitation.ConfirmationCodeActivity" + android:label="@string/title" > + </activity> + <activity + android:name=".android.invitation.WaitForContactActivity" + android:label="@string/title" > + </activity> + <activity + android:name=".android.invitation.CodesDoNotMatchActivity" + android:label="@string/title" > + </activity> + <activity + android:name=".android.invitation.ContactAddedActivity" + android:label="@string/title" > + </activity> </application> </manifest> diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..1b63e455be32834b8e0a9240bfaed25b5c69f5f0 Binary files /dev/null and b/res/drawable-hdpi/ic_launcher.png differ diff --git a/res/drawable-ldpi/ic_launcher.png b/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e0119f08678c54c5efd851a1860c9a18978ec3cd Binary files /dev/null and b/res/drawable-ldpi/ic_launcher.png differ diff --git a/res/drawable-ldpi/iconic_check_alt_green.png b/res/drawable-ldpi/iconic_check_alt_green.png new file mode 100644 index 0000000000000000000000000000000000000000..0751e8d49172a3b2746ac1d442383d838586075f Binary files /dev/null and b/res/drawable-ldpi/iconic_check_alt_green.png differ diff --git a/res/drawable-ldpi/iconic_x_alt_red.png b/res/drawable-ldpi/iconic_x_alt_red.png new file mode 100644 index 0000000000000000000000000000000000000000..d560b26460ba89d7cb1cb8465841b7f8d7dd639c Binary files /dev/null and b/res/drawable-ldpi/iconic_x_alt_red.png differ diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..9873a76f01b7952e9ca72018763aa519a5b8f1e8 Binary files /dev/null and b/res/drawable-mdpi/ic_launcher.png differ diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0b22fd5d7a57db85fccf364f07052262aaf8ec22 Binary files /dev/null and b/res/drawable-xhdpi/ic_launcher.png differ diff --git a/res/layout/activity_add_contact.xml b/res/layout/activity_add_contact.xml new file mode 100644 index 0000000000000000000000000000000000000000..c37b80fec002560fe9afdadabb4851b2f32d89d1 --- /dev/null +++ b/res/layout/activity_add_contact.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/add_contact_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> diff --git a/res/layout/activity_codes_do_not_match.xml b/res/layout/activity_codes_do_not_match.xml new file mode 100644 index 0000000000000000000000000000000000000000..4bd1965bc9ce73dd643c1c0d4a27ca789b591530 --- /dev/null +++ b/res/layout/activity_codes_do_not_match.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/codes_do_not_match_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> diff --git a/res/layout/activity_connection.xml b/res/layout/activity_connection.xml new file mode 100644 index 0000000000000000000000000000000000000000..367b75fc552e993b3e7876fadbef2b845b0fd74f --- /dev/null +++ b/res/layout/activity_connection.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/connection_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> \ No newline at end of file diff --git a/res/layout/activity_connection_failed.xml b/res/layout/activity_connection_failed.xml new file mode 100644 index 0000000000000000000000000000000000000000..9672914f4ca5721234515e26b994ed1455d249a3 --- /dev/null +++ b/res/layout/activity_connection_failed.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/connection_failed_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> diff --git a/res/layout/activity_connection_succeeded.xml b/res/layout/activity_connection_succeeded.xml new file mode 100644 index 0000000000000000000000000000000000000000..0b6962125d6d24eed4d9440a18c9fa0374106649 --- /dev/null +++ b/res/layout/activity_connection_succeeded.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/connection_succeeded_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> \ No newline at end of file diff --git a/res/layout/activity_contact_added.xml b/res/layout/activity_contact_added.xml new file mode 100644 index 0000000000000000000000000000000000000000..05a3c684f1d1adfc729a5013e6dfe58195586838 --- /dev/null +++ b/res/layout/activity_contact_added.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/contact_added_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> diff --git a/res/layout/activity_invitation_code.xml b/res/layout/activity_invitation_code.xml new file mode 100644 index 0000000000000000000000000000000000000000..193e86aaf5497c14f487d6b76b601d502a40f3a5 --- /dev/null +++ b/res/layout/activity_invitation_code.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/invitation_code_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> diff --git a/res/layout/activity_network_setup.xml b/res/layout/activity_network_setup.xml new file mode 100644 index 0000000000000000000000000000000000000000..48d2de513f0178f509f0b2a2f47bf63675cd55fa --- /dev/null +++ b/res/layout/activity_network_setup.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/network_setup_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> \ No newline at end of file diff --git a/res/layout/activity_test_bluetooth.xml b/res/layout/activity_test_bluetooth.xml new file mode 100644 index 0000000000000000000000000000000000000000..eaf4032a4c172d97ced3df021eaed863ae993ee2 --- /dev/null +++ b/res/layout/activity_test_bluetooth.xml @@ -0,0 +1,71 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/test_bt_screen_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Testing Bluetooth actions" + android:textAppearance="?android:attr/textAppearanceLarge" /> + + <Button + android:id="@+id/button1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Show paired devices info" + android:onClick="showBtPairedDevicesButtonClicked" /> + + <Button + android:id="@+id/test_bt_conn_btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Connect bluetooh" + android:onClick="testBtConnButtonClicked" /> + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" > + + <Button + android:id="@+id/test_bt_sendData_btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:onClick="testBtSendDataButtonClicked" + android:text="Send data" /> + + <Button + android:id="@+id/test_bt_recvData_btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:onClick="testBtReceiveDataButtonClicked" + android:text="Recive data" /> + </LinearLayout> + + <ScrollView + android:id="@+id/test_bt_log_view" + android:layout_width="fill_parent" + android:layout_height="wrap_content" > + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/test_bt_log_console_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Bluetooth actions log" /> + + <TextView + android:id="@+id/test_bt_log_console_msgs" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="actions log..." /> + + </LinearLayout> + </ScrollView> + +</LinearLayout> diff --git a/res/layout/activity_wait_for_contact.xml b/res/layout/activity_wait_for_contact.xml new file mode 100644 index 0000000000000000000000000000000000000000..cd96d411b253935b9d8819f08a72ea6ff0e39401 --- /dev/null +++ b/res/layout/activity_wait_for_contact.xml @@ -0,0 +1,5 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/wait_for_contact_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" /> \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index eeabdb397e19999f3f41484dd608c492eaeb6cf4..0a2f6313dfc5356be2094f881d70130fd15abed8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,4 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Briar</string> + <string name="menu_settings">Settings</string> + <string name="title">Add a Contact</string> + <string name="welcome">Welcome to Briar! Add a contact to get started.</string> + <string name="add_contact_button">Add a contact</string> + <string name="face_to_face">For security reasons you must be face to face with someone to add them as a contact.</string> + <string name="same_network">Briar can add contacts via Wi-Fi or Bluetooth. To use Wi-Fi you must both be connected to the same network.</string> + <string name="wifi_not_available">Wi-Fi is not available on this device.</string> + <string name="wifi_disabled">Wi-Fi is OFF.</string> + <string name="turn_on_wifi_button">Turn on Wi-Fi</string> + <string name="wifi_disconnected">Wi-Fi is DISCONNECTED.</string> + <string name="connect_to_wifi_button">Connect to Wi-Fi</string> + <string name="wifi_connected">Wi-Fi is CONNECTED to %1$s.</string> + <string name="bluetooth_not_available">Bluetooth is not available on this device.</string> + <string name="bluetooth_disabled">Bluetooth is OFF.</string> + <string name="turn_on_bluetooth_button">Turn on Bluetooth</string> + <string name="bluetooth_not_discoverable">Bluetooth is NOT DISCOVERABLE.</string> + <string name="make_bluetooth_discoverable_button">Make Bluetooth discoverable</string> + <string name="bluetooth_enabled">Bluetooth is ON.</string> + <string name="continue_button">Continue</string> + <string name="your_invitation_code">Your invitation code is</string> + <string name="enter_invitation_code">Please enter your contact\'s invitation code:</string> + <string name="connecting_wifi">Connecting via %1$s\u2026</string> + <string name="connecting_bluetooth">Connecting via Bluetooth\u2026</string> + <string name="connection_failed">Connection failed.</string> + <string name="check_same_network">Please check that you are both using the same network.</string> + <string name="try_again_button">Try again</string> + <string name="connected_to_contact">Connected to contact.</string> + <string name="your_confirmation_code">Your confirmation code is</string> + <string name="enter_confirmation_code">Please enter your contact\'s confirmation code:</string> + <string name="waiting_for_contact">Waiting for contact\u2026</string> + <string name="codes_do_not_match">Codes do not match!</string> + <string name="interfering">This could mean that someone is trying to interfere with your connection.</string> + <string name="contact_added">Contact added.</string> + <string name="enter_nickname">Please enter a nickname for this contact:</string> + <string name="add_another_contact_button">Add another contact</string> + <string name="done_button">Done</string> </resources> diff --git a/src/net/sf/briar/HelloWorldActivity.java b/src/net/sf/briar/HelloWorldActivity.java index 53607532d3557428ee3790a27a0d6d86a7be7ef7..76868cb80646b61a2855cb60ceb95dd25834b655 100644 --- a/src/net/sf/briar/HelloWorldActivity.java +++ b/src/net/sf/briar/HelloWorldActivity.java @@ -1,19 +1,41 @@ package net.sf.briar; +import net.sf.briar.android.invitation.NetworkSetupActivity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.LinearLayout; import android.widget.TextView; -public class HelloWorldActivity extends Activity { +public class HelloWorldActivity extends Activity implements OnClickListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - TextView text = new TextView(this); - text.setText("Hello world"); - setContentView(text); + setContentView(R.layout.activity_add_contact); + LinearLayout layout = (LinearLayout) findViewById( + R.id.add_contact_container); + + TextView welcome = new TextView(this); + welcome.setText(R.string.welcome); + layout.addView(welcome); + Button addContact = new Button(this); + addContact.setText(R.string.add_contact_button); + addContact.setOnClickListener(this); + layout.addView(addContact); + TextView faceToFace = new TextView(this); + faceToFace.setText(R.string.face_to_face); + layout.addView(faceToFace); + Intent intent = new Intent("net.sf.briar.HelloWorldService"); startService(intent); } + + public void onClick(View view) { + startActivity(new Intent(this, NetworkSetupActivity.class)); + finish(); + } } diff --git a/src/net/sf/briar/android/invitation/BluetoothStateListener.java b/src/net/sf/briar/android/invitation/BluetoothStateListener.java new file mode 100644 index 0000000000000000000000000000000000000000..fa7846c7c4d79bac01fa724623fdd80b25e8632d --- /dev/null +++ b/src/net/sf/briar/android/invitation/BluetoothStateListener.java @@ -0,0 +1,6 @@ +package net.sf.briar.android.invitation; + +interface BluetoothStateListener { + + void bluetoothStateChanged(boolean enabled); +} diff --git a/src/net/sf/briar/android/invitation/BluetoothWidget.java b/src/net/sf/briar/android/invitation/BluetoothWidget.java new file mode 100644 index 0000000000000000000000000000000000000000..e97d7d86e91f6a8f4b6cd2bb4beaf5775865096a --- /dev/null +++ b/src/net/sf/briar/android/invitation/BluetoothWidget.java @@ -0,0 +1,71 @@ +package net.sf.briar.android.invitation; + +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; +import static android.provider.Settings.ACTION_BLUETOOTH_SETTINGS; +import static android.view.Gravity.CENTER_HORIZONTAL; +import net.sf.briar.R; +import android.bluetooth.BluetoothAdapter; +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class BluetoothWidget extends LinearLayout implements OnClickListener { + + private BluetoothStateListener listener = null; + + public BluetoothWidget(Context ctx) { + super(ctx); + } + + void init(BluetoothStateListener listener) { + this.listener = listener; + setOrientation(VERTICAL); + setPadding(0, 10, 0, 10); + populate(); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + TextView status = new TextView(ctx); + status.setGravity(CENTER_HORIZONTAL); + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if(adapter == null) { + bluetoothStateChanged(false); + status.setText(R.string.bluetooth_not_available); + addView(status); + } else if(adapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE) { + bluetoothStateChanged(true); + status.setText(R.string.bluetooth_enabled); + addView(status); + } else if(adapter.isEnabled()) { + bluetoothStateChanged(false); + status.setText(R.string.bluetooth_not_discoverable); + addView(status); + Button turnOn = new Button(ctx); + turnOn.setText(R.string.make_bluetooth_discoverable_button); + turnOn.setOnClickListener(this); + addView(turnOn); + } else { + bluetoothStateChanged(false); + status.setText(R.string.bluetooth_disabled); + addView(status); + Button turnOn = new Button(ctx); + turnOn.setText(R.string.turn_on_bluetooth_button); + turnOn.setOnClickListener(this); + addView(turnOn); + } + } + + private void bluetoothStateChanged(boolean enabled) { + listener.bluetoothStateChanged(enabled); + } + + public void onClick(View view) { + getContext().startActivity(new Intent(ACTION_BLUETOOTH_SETTINGS)); + } +} diff --git a/src/net/sf/briar/android/invitation/CodeEntryListener.java b/src/net/sf/briar/android/invitation/CodeEntryListener.java new file mode 100644 index 0000000000000000000000000000000000000000..1a8f7b3d8d58a9925c030bdf83d428ed57023c6c --- /dev/null +++ b/src/net/sf/briar/android/invitation/CodeEntryListener.java @@ -0,0 +1,6 @@ +package net.sf.briar.android.invitation; + +interface CodeEntryListener { + + void codeEntered(String code); +} diff --git a/src/net/sf/briar/android/invitation/CodeEntryWidget.java b/src/net/sf/briar/android/invitation/CodeEntryWidget.java new file mode 100644 index 0000000000000000000000000000000000000000..5565782753448cb19fad83b62ec4872d9f9344a3 --- /dev/null +++ b/src/net/sf/briar/android/invitation/CodeEntryWidget.java @@ -0,0 +1,76 @@ +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 net.sf.briar.R; +import android.content.Context; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; + +public class CodeEntryWidget extends LinearLayout implements +OnEditorActionListener, OnClickListener { + + private CodeEntryListener listener = null; + private EditText codeEntry = null; + + public CodeEntryWidget(Context ctx) { + super(ctx); + } + + void init(CodeEntryListener listener, String prompt) { + this.listener = listener; + setOrientation(VERTICAL); + + Context ctx = getContext(); + TextView enterCode = new TextView(ctx); + enterCode.setGravity(CENTER_HORIZONTAL); + enterCode.setText(prompt); + addView(enterCode); + + final Button continueButton = new Button(ctx); + continueButton.setText(R.string.continue_button); + continueButton.setEnabled(false); + continueButton.setOnClickListener(this); + + codeEntry = new EditText(ctx) { + @Override + protected void onTextChanged(CharSequence text, int start, + int lengthBefore, int lengthAfter) { + continueButton.setEnabled(text.length() == 6); + } + }; + codeEntry.setOnEditorActionListener(this); + codeEntry.setMinEms(5); + codeEntry.setMaxEms(5); + codeEntry.setMaxLines(1); + codeEntry.setInputType(TYPE_CLASS_NUMBER); + + LinearLayout innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + innerLayout.addView(codeEntry); + innerLayout.addView(continueButton); + addView(innerLayout); + } + + public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { + validateAndReturnCode(); + return true; + } + + public void onClick(View view) { + validateAndReturnCode(); + } + + private void validateAndReturnCode() { + CharSequence code = codeEntry.getText(); + if(code.length() == 6) listener.codeEntered(code.toString()); + } +} diff --git a/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java b/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..c981bc067092c6acbae39b7063e8fabad76352b3 --- /dev/null +++ b/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java @@ -0,0 +1,54 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.widget.LinearLayout.HORIZONTAL; +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.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); + setContentView(R.layout.activity_codes_do_not_match); + LinearLayout outerLayout = (LinearLayout) findViewById( + R.id.codes_do_not_match_container); + + LinearLayout innerLayout = new LinearLayout(this); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + ImageView icon = new ImageView(this); + icon.setImageResource(R.drawable.iconic_x_alt_red); + icon.setPadding(10, 10, 10, 10); + innerLayout.addView(icon); + TextView failed = new TextView(this); + failed.setTextSize(20); + failed.setText(R.string.codes_do_not_match); + innerLayout.addView(failed); + outerLayout.addView(innerLayout); + + TextView interfering = new TextView(this); + interfering.setText(R.string.interfering); + outerLayout.addView(interfering); + Button tryAgain = new Button(this); + tryAgain.setText(R.string.try_again_button); + tryAgain.setOnClickListener(this); + outerLayout.addView(tryAgain); + } + + 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/ConfirmationCodeActivity.java b/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..e4bb901df00ad5b414edca1fba0510365a485ed5 --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java @@ -0,0 +1,69 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.widget.LinearLayout.HORIZONTAL; +import net.sf.briar.R; +import android.app.Activity; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ConfirmationCodeActivity extends Activity +implements CodeEntryListener { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_connection_succeeded); + LinearLayout outerLayout = (LinearLayout) findViewById( + R.id.connection_succeeded_container); + + LinearLayout innerLayout = new LinearLayout(this); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + ImageView icon = new ImageView(this); + icon.setImageResource(R.drawable.iconic_check_alt_green); + icon.setPadding(10, 10, 10, 10); + innerLayout.addView(icon); + TextView failed = new TextView(this); + failed.setTextSize(20); + failed.setText(R.string.connected_to_contact); + innerLayout.addView(failed); + outerLayout.addView(innerLayout); + + TextView checkNetwork = new TextView(this); + checkNetwork.setGravity(CENTER_HORIZONTAL); + checkNetwork.setText(R.string.your_confirmation_code); + outerLayout.addView(checkNetwork); + TextView code = new TextView(this); + code.setGravity(CENTER_HORIZONTAL); + InvitationManager im = InvitationManagerFactory.getInvitationManager(); + String localConfirmationCode = im.getLocalConfirmationCode(); + code.setText(localConfirmationCode); + code.setTextSize(50); + outerLayout.addView(code); + CodeEntryWidget codeEntry = new CodeEntryWidget(this); + Resources res = getResources(); + codeEntry.init(this, res.getString(R.string.enter_confirmation_code)); + outerLayout.addView(codeEntry); + } + + public void codeEntered(String code) { + InvitationManager im = InvitationManagerFactory.getInvitationManager(); + String remoteConfirmationCode = im.getRemoteConfirmationCode(); + if(code.equals(String.valueOf(remoteConfirmationCode))) { + 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/ConfirmationListener.java b/src/net/sf/briar/android/invitation/ConfirmationListener.java new file mode 100644 index 0000000000000000000000000000000000000000..af2024676a4731cb7aa4f73479fa7fa50cbda756 --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConfirmationListener.java @@ -0,0 +1,8 @@ +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 new file mode 100644 index 0000000000000000000000000000000000000000..2564adf002c7077c750bc77013fa1cda8cff634b --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConnectionActivity.java @@ -0,0 +1,99 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.widget.LinearLayout.HORIZONTAL; +import net.sf.briar.R; +import android.app.Activity; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +public class ConnectionActivity extends Activity implements ConnectionListener { + + private final InvitationManager manager = + InvitationManagerFactory.getInvitationManager(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_connection); + LinearLayout outerLayout = (LinearLayout) findViewById( + R.id.connection_container); + + 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); + outerLayout.addView(yourCode); + TextView code = new TextView(this); + code.setGravity(CENTER_HORIZONTAL); + code.setText(manager.getLocalInvitationCode()); + code.setTextSize(50); + outerLayout.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 text = res.getString(R.string.connecting_wifi); + text = String.format(text, networkName); + connecting.setText(text); + innerLayout.addView(connecting); + outerLayout.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); + outerLayout.addView(innerLayout); + manager.startBluetoothConnectionWorker(this); + } + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..0b868a1740276af0387873cac79e8e02bd7e1ffe --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConnectionFailedActivity.java @@ -0,0 +1,96 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; +import static android.widget.LinearLayout.HORIZONTAL; +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.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); + setContentView(R.layout.activity_connection_failed); + LinearLayout outerLayout = (LinearLayout) findViewById( + R.id.connection_failed_container); + + LinearLayout innerLayout = new LinearLayout(this); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + ImageView icon = new ImageView(this); + icon.setImageResource(R.drawable.iconic_x_alt_red); + icon.setPadding(10, 10, 10, 10); + innerLayout.addView(icon); + TextView failed = new TextView(this); + failed.setTextSize(20); + failed.setText(R.string.connection_failed); + innerLayout.addView(failed); + outerLayout.addView(innerLayout); + + TextView checkNetwork = new TextView(this); + checkNetwork.setText(R.string.check_same_network); + outerLayout.addView(checkNetwork); + wifi = new WifiWidget(this); + wifi.init(this); + outerLayout.addView(wifi); + bluetooth = new BluetoothWidget(this); + bluetooth.init(this); + outerLayout.addView(bluetooth); + tryAgainButton = new Button(this); + tryAgainButton.setText(R.string.try_again_button); + tryAgainButton.setOnClickListener(this); + setTryAgainButtonVisibility(); + outerLayout.addView(tryAgainButton); + } + + @Override + public void onResume() { + super.onResume(); + wifi.populate(); + bluetooth.populate(); + } + + public void wifiStateChanged(String networkName) { + this.networkName = networkName; + setTryAgainButtonVisibility(); + } + + public void bluetoothStateChanged(boolean enabled) { + useBluetooth = enabled; + setTryAgainButtonVisibility(); + } + + private void setTryAgainButtonVisibility() { + if(tryAgainButton == null) return; + if(useBluetooth || networkName != null) + tryAgainButton.setVisibility(VISIBLE); + else tryAgainButton.setVisibility(INVISIBLE); + } + + 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/ConnectionListener.java b/src/net/sf/briar/android/invitation/ConnectionListener.java new file mode 100644 index 0000000000000000000000000000000000000000..a1bc643dc3bdc53b17f748759c824104feece6a2 --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConnectionListener.java @@ -0,0 +1,8 @@ +package net.sf.briar.android.invitation; + +interface ConnectionListener { + + void connectionEstablished(); + + void connectionNotEstablished(); +} diff --git a/src/net/sf/briar/android/invitation/ContactAddedActivity.java b/src/net/sf/briar/android/invitation/ContactAddedActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..846c25bf1ae9932d1a1dd83322b5b305eb77bb46 --- /dev/null +++ b/src/net/sf/briar/android/invitation/ContactAddedActivity.java @@ -0,0 +1,91 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.widget.LinearLayout.HORIZONTAL; +import net.sf.briar.R; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; + +public class ContactAddedActivity extends Activity implements OnClickListener, +OnEditorActionListener { + + private volatile Button done = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_contact_added); + LinearLayout outerLayout = (LinearLayout) findViewById( + R.id.contact_added_container); + + LinearLayout innerLayout = new LinearLayout(this); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + ImageView icon = new ImageView(this); + icon.setImageResource(R.drawable.iconic_check_alt_green); + icon.setPadding(10, 10, 10, 10); + innerLayout.addView(icon); + TextView failed = new TextView(this); + failed.setTextSize(20); + failed.setText(R.string.contact_added); + innerLayout.addView(failed); + outerLayout.addView(innerLayout); + + TextView enterNickname = new TextView(this); + enterNickname.setGravity(CENTER_HORIZONTAL); + enterNickname.setText(R.string.enter_nickname); + outerLayout.addView(enterNickname); + final Button addAnother = new Button(this); + final Button done = new Button(this); + this.done = done; + EditText nicknameEntry = new EditText(this) { + @Override + protected void onTextChanged(CharSequence text, int start, + int lengthBefore, int lengthAfter) { + addAnother.setEnabled(text.length() > 0); + done.setEnabled(text.length() > 0); + } + }; + nicknameEntry.setMinEms(10); + nicknameEntry.setMaxEms(20); + nicknameEntry.setMaxLines(1); + nicknameEntry.setOnEditorActionListener(this); + outerLayout.addView(nicknameEntry); + + innerLayout = new LinearLayout(this); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + addAnother.setText(R.string.add_another_contact_button); + addAnother.setEnabled(false); + addAnother.setOnClickListener(this); + innerLayout.addView(addAnother); + done.setText(R.string.done_button); + done.setEnabled(false); + done.setOnClickListener(this); + innerLayout.addView(done); + outerLayout.addView(innerLayout); + } + + public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { + if(textView.getText().length() > 0) finish(); + return true; + } + + public void onClick(View view) { + if(done == null) return; + if(view != done) + startActivity(new Intent(this, NetworkSetupActivity.class)); + finish(); + } +} diff --git a/src/net/sf/briar/android/invitation/InvitationCodeActivity.java b/src/net/sf/briar/android/invitation/InvitationCodeActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..79e7a22cd97bd0351696b74406b9d88b45def5ea --- /dev/null +++ b/src/net/sf/briar/android/invitation/InvitationCodeActivity.java @@ -0,0 +1,48 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER_HORIZONTAL; +import net.sf.briar.R; +import android.app.Activity; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class InvitationCodeActivity extends Activity +implements CodeEntryListener { + + private final InvitationManager manager = + InvitationManagerFactory.getInvitationManager(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_invitation_code); + LinearLayout layout = (LinearLayout) findViewById( + R.id.invitation_code_container); + + 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); + String localInvitationCode = manager.getLocalInvitationCode(); + code.setText(localInvitationCode); + code.setTextSize(50); + layout.addView(code); + CodeEntryWidget codeEntry = new CodeEntryWidget(this); + Resources res = getResources(); + codeEntry.init(this, res.getString(R.string.enter_invitation_code)); + layout.addView(codeEntry); + } + + 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/InvitationManager.java b/src/net/sf/briar/android/invitation/InvitationManager.java new file mode 100644 index 0000000000000000000000000000000000000000..f77baa4c33aa76824a0603eb6eb7e52cde5682b7 --- /dev/null +++ b/src/net/sf/briar/android/invitation/InvitationManager.java @@ -0,0 +1,26 @@ +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/InvitationManagerFactory.java b/src/net/sf/briar/android/invitation/InvitationManagerFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..a38ac435ade195507a70316a2890c7da29afe586 --- /dev/null +++ b/src/net/sf/briar/android/invitation/InvitationManagerFactory.java @@ -0,0 +1,14 @@ +package net.sf.briar.android.invitation; + +class InvitationManagerFactory { + + private static final Object LOCK = new Object(); + private static InvitationManager instance = null; // Locking: lock + + static InvitationManager getInvitationManager() { + synchronized(LOCK) { + if(instance == null) instance = new InvitationManagerImpl(); + return instance; + } + } +} diff --git a/src/net/sf/briar/android/invitation/InvitationManagerImpl.java b/src/net/sf/briar/android/invitation/InvitationManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..c5afcacec161d9bd116b7846a8bd8aa61640ef96 --- /dev/null +++ b/src/net/sf/briar/android/invitation/InvitationManagerImpl.java @@ -0,0 +1,67 @@ +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 new file mode 100644 index 0000000000000000000000000000000000000000..2488e4d12525968f971b73d8aed3a0ad92c1999b --- /dev/null +++ b/src/net/sf/briar/android/invitation/NetworkSetupActivity.java @@ -0,0 +1,88 @@ +package net.sf.briar.android.invitation; + +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; +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.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); + setContentView(R.layout.activity_network_setup); + LinearLayout layout = (LinearLayout) findViewById( + R.id.network_setup_container); + + TextView sameNetwork = new TextView(this); + 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); + continueButton.setText(R.string.continue_button); + continueButton.setOnClickListener(this); + setContinueButtonVisibility(); + layout.addView(continueButton); + } + + @Override + public void onResume() { + super.onResume(); + wifi.populate(); + bluetooth.populate(); + } + + public void wifiStateChanged(final String name) { + runOnUiThread(new Runnable() { + public void run() { + networkName = name; + setContinueButtonVisibility(); + } + }); + } + + public void bluetoothStateChanged(final boolean enabled) { + runOnUiThread(new Runnable() { + public void run() { + useBluetooth = enabled; + setContinueButtonVisibility(); + } + }); + } + + private void setContinueButtonVisibility() { + if(continueButton == null) return; + if(useBluetooth || networkName != null) + continueButton.setVisibility(VISIBLE); + else continueButton.setVisibility(INVISIBLE); + } + + 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/WaitForContactActivity.java b/src/net/sf/briar/android/invitation/WaitForContactActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..ed778ff23ffc1db084b4625db0139f42ef8ab88f --- /dev/null +++ b/src/net/sf/briar/android/invitation/WaitForContactActivity.java @@ -0,0 +1,76 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.widget.LinearLayout.HORIZONTAL; +import net.sf.briar.R; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +public class WaitForContactActivity extends Activity +implements ConfirmationListener { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wait_for_contact); + LinearLayout outerLayout = (LinearLayout) findViewById( + R.id.wait_for_contact_container); + + LinearLayout innerLayout = new LinearLayout(this); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + ImageView icon = new ImageView(this); + icon.setImageResource(R.drawable.iconic_check_alt_green); + icon.setPadding(10, 10, 10, 10); + innerLayout.addView(icon); + TextView failed = new TextView(this); + failed.setTextSize(20); + failed.setText(R.string.connected_to_contact); + innerLayout.addView(failed); + outerLayout.addView(innerLayout); + + TextView yourCode = new TextView(this); + yourCode.setGravity(CENTER_HORIZONTAL); + yourCode.setText(R.string.your_confirmation_code); + outerLayout.addView(yourCode); + TextView code = new TextView(this); + code.setGravity(CENTER_HORIZONTAL); + InvitationManager im = InvitationManagerFactory.getInvitationManager(); + String localConfirmationCode = im.getLocalConfirmationCode(); + code.setText(localConfirmationCode); + code.setTextSize(50); + outerLayout.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); + outerLayout.addView(innerLayout); + + im.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/WifiStateListener.java b/src/net/sf/briar/android/invitation/WifiStateListener.java new file mode 100644 index 0000000000000000000000000000000000000000..c668b0d2d37df6b224445777eed662509b2347f4 --- /dev/null +++ b/src/net/sf/briar/android/invitation/WifiStateListener.java @@ -0,0 +1,6 @@ +package net.sf.briar.android.invitation; + +interface WifiStateListener { + + void wifiStateChanged(String networkName); +} diff --git a/src/net/sf/briar/android/invitation/WifiWidget.java b/src/net/sf/briar/android/invitation/WifiWidget.java new file mode 100644 index 0000000000000000000000000000000000000000..d27d6e8b3a871c98479e456aacb883e5429f3f0f --- /dev/null +++ b/src/net/sf/briar/android/invitation/WifiWidget.java @@ -0,0 +1,77 @@ +package net.sf.briar.android.invitation; + +import static android.content.Context.WIFI_SERVICE; +import static android.provider.Settings.ACTION_WIFI_SETTINGS; +import static android.view.Gravity.CENTER_HORIZONTAL; +import net.sf.briar.R; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.wifi.WifiManager; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class WifiWidget extends LinearLayout implements OnClickListener { + + private WifiStateListener listener = null; + + public WifiWidget(Context ctx) { + super(ctx); + } + + void init(WifiStateListener listener) { + this.listener = listener; + setOrientation(VERTICAL); + setPadding(0, 10, 0, 0); + populate(); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + TextView status = new TextView(ctx); + status.setGravity(CENTER_HORIZONTAL); + WifiManager wifi = (WifiManager) ctx.getSystemService(WIFI_SERVICE); + if(wifi == null) { + wifiStateChanged(null); + status.setText(R.string.wifi_not_available); + addView(status); + } else if(wifi.isWifiEnabled()) { + String networkName = wifi.getConnectionInfo().getSSID(); + if(networkName == null) { + wifiStateChanged(null); + status.setText(R.string.wifi_disconnected); + addView(status); + Button connect = new Button(ctx); + connect.setText(R.string.connect_to_wifi_button); + connect.setOnClickListener(this); + addView(connect); + } else { + wifiStateChanged(networkName); + Resources res = getResources(); + String connected = res.getString(R.string.wifi_connected); + status.setText(String.format(connected, networkName)); + addView(status); + } + } else { + wifiStateChanged(null); + status.setText(R.string.wifi_disabled); + addView(status); + Button connect = new Button(ctx); + connect.setText(R.string.connect_to_wifi_button); + connect.setOnClickListener(this); + addView(connect); + } + } + + private void wifiStateChanged(String networkName) { + if(listener != null) listener.wifiStateChanged(networkName); + } + + public void onClick(View view) { + getContext().startActivity(new Intent(ACTION_WIFI_SETTINGS)); + } +}