Update invitation UI when Bluetooth or WiFi status changes.

Fixes issue #3611925.
This commit is contained in:
akwizgran
2013-04-26 21:05:52 +01:00
parent 421ce90469
commit 3d9912b4ff
10 changed files with 97 additions and 94 deletions

View File

@@ -31,7 +31,7 @@
<string name="bluetooth_not_available">Bluetooth is NOT AVAILABLE</string> <string name="bluetooth_not_available">Bluetooth is NOT AVAILABLE</string>
<string name="bluetooth_disabled">Bluetooth is OFF</string> <string name="bluetooth_disabled">Bluetooth is OFF</string>
<string name="bluetooth_not_discoverable">Bluetooth is NOT DISCOVERABLE</string> <string name="bluetooth_not_discoverable">Bluetooth is NOT DISCOVERABLE</string>
<string name="bluetooth_enabled">Bluetooth is discoverable</string> <string name="bluetooth_discoverable">Bluetooth is discoverable</string>
<string name="fact_to_face">For security reasons you must be face-to-face with someone to add them as a contact</string> <string name="fact_to_face">For security reasons you must be face-to-face with someone to add them as a contact</string>
<string name="continue_button">Continue</string> <string name="continue_button">Continue</string>
<string name="your_invitation_code">Your invitation code is</string> <string name="your_invitation_code">Your invitation code is</string>

View File

@@ -1,5 +1,10 @@
package net.sf.briar.android.invitation; package net.sf.briar.android.invitation;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
@@ -25,7 +30,13 @@ import net.sf.briar.api.invitation.InvitationListener;
import net.sf.briar.api.invitation.InvitationState; import net.sf.briar.api.invitation.InvitationState;
import net.sf.briar.api.invitation.InvitationTask; import net.sf.briar.api.invitation.InvitationTask;
import net.sf.briar.api.invitation.InvitationTaskFactory; import net.sf.briar.api.invitation.InvitationTaskFactory;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -48,7 +59,7 @@ implements InvitationListener {
private long taskHandle = -1; private long taskHandle = -1;
private AuthorId localAuthorId = null; private AuthorId localAuthorId = null;
private String networkName = null; private String networkName = null;
private boolean useBluetooth = false; private boolean bluetoothEnabled = false;
private int localInvitationCode = -1, remoteInvitationCode = -1; private int localInvitationCode = -1, remoteInvitationCode = -1;
private int localConfirmationCode = -1, remoteConfirmationCode = -1; private int localConfirmationCode = -1, remoteConfirmationCode = -1;
private boolean connectionFailed = false; private boolean connectionFailed = false;
@@ -70,8 +81,6 @@ implements InvitationListener {
// Restore the activity's state // Restore the activity's state
byte[] b = state.getByteArray("net.sf.briar.LOCAL_AUTHOR_ID"); byte[] b = state.getByteArray("net.sf.briar.LOCAL_AUTHOR_ID");
if(b != null) localAuthorId = new AuthorId(b); if(b != null) localAuthorId = new AuthorId(b);
networkName = state.getString("net.sf.briar.NETWORK_NAME");
useBluetooth = state.getBoolean("net.sf.briar.USE_BLUETOOTH");
taskHandle = state.getLong("net.sf.briar.TASK_HANDLE", -1); taskHandle = state.getLong("net.sf.briar.TASK_HANDLE", -1);
task = referenceManager.getReference(taskHandle, task = referenceManager.getReference(taskHandle,
InvitationTask.class); InvitationTask.class);
@@ -133,6 +142,25 @@ implements InvitationListener {
} }
} }
// Listen for Bluetooth and WiFi state changes
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_STATE_CHANGED);
filter.addAction(ACTION_SCAN_MODE_CHANGED);
filter.addAction(NETWORK_STATE_CHANGED_ACTION);
BluetoothWifiStateReceiver receiver = new BluetoothWifiStateReceiver();
registerReceiver(receiver, filter);
// Get the current Bluetooth and WiFi state
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
if(bluetooth != null) bluetoothEnabled = bluetooth.isEnabled();
view.bluetoothStateChanged();
WifiManager wifi = (WifiManager) getSystemService(WIFI_SERVICE);
if(wifi != null && wifi.isWifiEnabled()) {
WifiInfo info = wifi.getConnectionInfo();
if(info.getNetworkId() != -1) networkName = info.getSSID();
}
view.wifiStateChanged();
// Bind to the service so we can wait for it to start // Bind to the service so we can wait for it to start
bindService(new Intent(BriarService.class.getName()), bindService(new Intent(BriarService.class.getName()),
serviceConnection, 0); serviceConnection, 0);
@@ -150,8 +178,6 @@ implements InvitationListener {
state.putByteArray("net.sf.briar.LOCAL_AUTHOR_ID", state.putByteArray("net.sf.briar.LOCAL_AUTHOR_ID",
localAuthorId.getBytes()); localAuthorId.getBytes());
} }
state.putString("net.sf.briar.NETWORK_NAME", networkName);
state.putBoolean("net.sf.briar.USE_BLUETOOTH", useBluetooth);
state.putInt("net.sf.briar.LOCAL_CODE", localInvitationCode); state.putInt("net.sf.briar.LOCAL_CODE", localInvitationCode);
state.putInt("net.sf.briar.REMOTE_CODE", remoteInvitationCode); state.putInt("net.sf.briar.REMOTE_CODE", remoteInvitationCode);
state.putBoolean("net.sf.briar.FAILED", connectionFailed); state.putBoolean("net.sf.briar.FAILED", connectionFailed);
@@ -174,7 +200,7 @@ implements InvitationListener {
} }
void reset(AddContactView view) { void reset(AddContactView view) {
// Don't reset localAuthorId, networkName or useBluetooth // Don't reset localAuthorId, networkName or bluetoothEnabled
task = null; task = null;
taskHandle = -1; taskHandle = -1;
localInvitationCode = -1; localInvitationCode = -1;
@@ -230,20 +256,12 @@ implements InvitationListener {
return localAuthorId; return localAuthorId;
} }
void setNetworkName(String networkName) {
this.networkName = networkName;
}
String getNetworkName() { String getNetworkName() {
return networkName; return networkName;
} }
void setUseBluetooth(boolean useBluetooth) { boolean isBluetoothEnabled() {
this.useBluetooth = useBluetooth; return bluetoothEnabled;
}
boolean getUseBluetooth() {
return useBluetooth;
} }
int getLocalInvitationCode() { int getLocalInvitationCode() {
@@ -341,6 +359,30 @@ implements InvitationListener {
}); });
} }
private class BluetoothWifiStateReceiver extends BroadcastReceiver {
public void onReceive(Context ctx, Intent intent) {
String action = intent.getAction();
if(action.equals(ACTION_STATE_CHANGED)) {
int state = intent.getIntExtra(EXTRA_STATE, 0);
bluetoothEnabled = state == STATE_ON;
view.bluetoothStateChanged();
} else if(action.equals(ACTION_SCAN_MODE_CHANGED)) {
view.bluetoothStateChanged();
} else if(action.equals(NETWORK_STATE_CHANGED_ACTION)) {
WifiManager wifi = (WifiManager) getSystemService(WIFI_SERVICE);
if(wifi == null || !wifi.isWifiEnabled()) {
networkName = null;
} else {
WifiInfo info = wifi.getConnectionInfo();
if(info.getNetworkId() == -1) networkName = null;
else networkName = info.getSSID();
}
view.wifiStateChanged();
}
}
}
/** /**
* Cleans up the reference to the invitation task when the task completes. * Cleans up the reference to the invitation task when the task completes.
* This class is static to prevent memory leaks. * This class is static to prevent memory leaks.

View File

@@ -22,4 +22,8 @@ abstract class AddContactView extends LinearLayout {
} }
abstract void populate(); abstract void populate();
void wifiStateChanged() {}
void bluetoothStateChanged() {}
} }

View File

@@ -1,6 +0,0 @@
package net.sf.briar.android.invitation;
interface BluetoothStateListener {
void bluetoothStateChanged(boolean enabled);
}

View File

@@ -17,14 +17,11 @@ import android.widget.TextView;
public class BluetoothWidget extends LinearLayout implements OnClickListener { public class BluetoothWidget extends LinearLayout implements OnClickListener {
private BluetoothStateListener listener = null;
public BluetoothWidget(Context ctx) { public BluetoothWidget(Context ctx) {
super(ctx); super(ctx);
} }
void init(BluetoothStateListener listener) { void init() {
this.listener = listener;
setOrientation(HORIZONTAL); setOrientation(HORIZONTAL);
setGravity(CENTER); setGravity(CENTER);
populate(); populate();
@@ -39,7 +36,6 @@ public class BluetoothWidget extends LinearLayout implements OnClickListener {
status.setPadding(10, 10, 10, 10); status.setPadding(10, 10, 10, 10);
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if(adapter == null) { if(adapter == null) {
listener.bluetoothStateChanged(false);
ImageView warning = new ImageView(ctx); ImageView warning = new ImageView(ctx);
warning.setPadding(5, 5, 5, 5); warning.setPadding(5, 5, 5, 5);
warning.setImageResource(R.drawable.alerts_and_states_warning); warning.setImageResource(R.drawable.alerts_and_states_warning);
@@ -47,19 +43,17 @@ public class BluetoothWidget extends LinearLayout implements OnClickListener {
status.setText(R.string.bluetooth_not_available); status.setText(R.string.bluetooth_not_available);
addView(status); addView(status);
} else if(adapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE) { } else if(adapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
listener.bluetoothStateChanged(true);
ImageView ok = new ImageView(ctx); ImageView ok = new ImageView(ctx);
ok.setPadding(5, 5, 5, 5); ok.setPadding(5, 5, 5, 5);
ok.setImageResource(R.drawable.navigation_accept); ok.setImageResource(R.drawable.navigation_accept);
addView(ok); addView(ok);
status.setText(R.string.bluetooth_enabled); status.setText(R.string.bluetooth_discoverable);
addView(status); addView(status);
ImageButton settings = new ImageButton(ctx); ImageButton settings = new ImageButton(ctx);
settings.setImageResource(R.drawable.action_settings); settings.setImageResource(R.drawable.action_settings);
settings.setOnClickListener(this); settings.setOnClickListener(this);
addView(settings); addView(settings);
} else if(adapter.isEnabled()) { } else if(adapter.isEnabled()) {
listener.bluetoothStateChanged(true);
ImageView warning = new ImageView(ctx); ImageView warning = new ImageView(ctx);
warning.setPadding(5, 5, 5, 5); warning.setPadding(5, 5, 5, 5);
warning.setImageResource(R.drawable.alerts_and_states_warning); warning.setImageResource(R.drawable.alerts_and_states_warning);
@@ -71,7 +65,6 @@ public class BluetoothWidget extends LinearLayout implements OnClickListener {
settings.setOnClickListener(this); settings.setOnClickListener(this);
addView(settings); addView(settings);
} else { } else {
listener.bluetoothStateChanged(false);
ImageView warning = new ImageView(ctx); ImageView warning = new ImageView(ctx);
warning.setPadding(5, 5, 5, 5); warning.setPadding(5, 5, 5, 5);
warning.setImageResource(R.drawable.alerts_and_states_warning); warning.setImageResource(R.drawable.alerts_and_states_warning);

View File

@@ -12,8 +12,10 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
public class ConnectionFailedView extends AddContactView public class ConnectionFailedView extends AddContactView
implements WifiStateListener, BluetoothStateListener, OnClickListener { implements OnClickListener {
private WifiWidget wifi = null;
private BluetoothWidget bluetooth = null;
private Button tryAgainButton = null; private Button tryAgainButton = null;
ConnectionFailedView(Context ctx) { ConnectionFailedView(Context ctx) {
@@ -44,12 +46,12 @@ implements WifiStateListener, BluetoothStateListener, OnClickListener {
checkNetwork.setText(R.string.check_same_network); checkNetwork.setText(R.string.check_same_network);
addView(checkNetwork); addView(checkNetwork);
WifiWidget wifi = new WifiWidget(ctx); wifi = new WifiWidget(ctx);
wifi.init(this); wifi.init();
addView(wifi); addView(wifi);
BluetoothWidget bluetooth = new BluetoothWidget(ctx); bluetooth = new BluetoothWidget(ctx);
bluetooth.init(this); bluetooth.init();
addView(bluetooth); addView(bluetooth);
tryAgainButton = new Button(ctx); tryAgainButton = new Button(ctx);
@@ -60,29 +62,21 @@ implements WifiStateListener, BluetoothStateListener, OnClickListener {
addView(tryAgainButton); addView(tryAgainButton);
} }
public void wifiStateChanged(final String networkName) { void wifiStateChanged() {
container.runOnUiThread(new Runnable() { if(wifi != null) wifi.populate();
public void run() { enableOrDisableTryAgainButton();
container.setNetworkName(networkName);
enableOrDisableTryAgainButton();
}
});
} }
public void bluetoothStateChanged(final boolean enabled) { void bluetoothStateChanged() {
container.runOnUiThread(new Runnable() { if(bluetooth != null) bluetooth.populate();
public void run() { enableOrDisableTryAgainButton();
container.setUseBluetooth(enabled);
enableOrDisableTryAgainButton();
}
});
} }
private void enableOrDisableTryAgainButton() { private void enableOrDisableTryAgainButton() {
if(tryAgainButton == null) return; // Activity not created yet if(tryAgainButton == null) return; // Activity not created yet
boolean useBluetooth = container.getUseBluetooth(); boolean bluetoothEnabled = container.isBluetoothEnabled();
String networkName = container.getNetworkName(); String networkName = container.getNetworkName();
tryAgainButton.setEnabled(useBluetooth || networkName != null); tryAgainButton.setEnabled(bluetoothEnabled || networkName != null);
} }
public void onClick(View view) { public void onClick(View view) {

View File

@@ -52,7 +52,7 @@ public class ConnectionView extends AddContactView {
addView(innerLayout); addView(innerLayout);
} }
if(container.getUseBluetooth()) { if(container.isBluetoothEnabled()) {
LinearLayout innerLayout = new LinearLayout(ctx); LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL); innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER); innerLayout.setGravity(CENTER);

View File

@@ -21,11 +21,12 @@ import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
public class NetworkSetupView extends AddContactView public class NetworkSetupView extends AddContactView
implements WifiStateListener, BluetoothStateListener, OnItemSelectedListener, implements OnItemSelectedListener, OnClickListener {
OnClickListener {
private LocalAuthorSpinnerAdapter adapter = null; private LocalAuthorSpinnerAdapter adapter = null;
private Spinner spinner = null; private Spinner spinner = null;
private WifiWidget wifi = null;
private BluetoothWidget bluetooth = null;
private Button continueButton = null; private Button continueButton = null;
NetworkSetupView(Context ctx) { NetworkSetupView(Context ctx) {
@@ -55,12 +56,12 @@ OnClickListener {
innerLayout.addView(spinner); innerLayout.addView(spinner);
addView(innerLayout); addView(innerLayout);
WifiWidget wifi = new WifiWidget(ctx); wifi = new WifiWidget(ctx);
wifi.init(this); wifi.init();
addView(wifi); addView(wifi);
BluetoothWidget bluetooth = new BluetoothWidget(ctx); bluetooth = new BluetoothWidget(ctx);
bluetooth.init(this); bluetooth.init();
addView(bluetooth); addView(bluetooth);
TextView faceToFace = new TextView(ctx); TextView faceToFace = new TextView(ctx);
@@ -78,30 +79,22 @@ OnClickListener {
addView(continueButton); addView(continueButton);
} }
public void wifiStateChanged(final String networkName) { void wifiStateChanged() {
container.runOnUiThread(new Runnable() { if(wifi != null) wifi.populate();
public void run() { enableOrDisableContinueButton();
container.setNetworkName(networkName);
enableOrDisableContinueButton();
}
});
} }
public void bluetoothStateChanged(final boolean enabled) { void bluetoothStateChanged() {
container.runOnUiThread(new Runnable() { if(bluetooth != null) bluetooth.populate();
public void run() { enableOrDisableContinueButton();
container.setUseBluetooth(enabled);
enableOrDisableContinueButton();
}
});
} }
private void enableOrDisableContinueButton() { private void enableOrDisableContinueButton() {
if(continueButton == null) return; // Activity not created yet if(continueButton == null) return; // Activity not created yet
AuthorId localAuthorId = container.getLocalAuthorId(); AuthorId localAuthorId = container.getLocalAuthorId();
boolean useBluetooth = container.getUseBluetooth(); boolean bluetoothEnabled = container.isBluetoothEnabled();
String networkName = container.getNetworkName(); String networkName = container.getNetworkName();
boolean networkAvailable = useBluetooth || networkName != null; boolean networkAvailable = bluetoothEnabled || networkName != null;
continueButton.setEnabled(localAuthorId != null && networkAvailable); continueButton.setEnabled(localAuthorId != null && networkAvailable);
} }

View File

@@ -1,6 +0,0 @@
package net.sf.briar.android.invitation;
interface WifiStateListener {
void wifiStateChanged(String networkName);
}

View File

@@ -18,14 +18,11 @@ import android.widget.TextView;
public class WifiWidget extends LinearLayout implements OnClickListener { public class WifiWidget extends LinearLayout implements OnClickListener {
private WifiStateListener listener = null;
public WifiWidget(Context ctx) { public WifiWidget(Context ctx) {
super(ctx); super(ctx);
} }
void init(WifiStateListener listener) { void init() {
this.listener = listener;
setOrientation(HORIZONTAL); setOrientation(HORIZONTAL);
setGravity(CENTER); setGravity(CENTER);
populate(); populate();
@@ -40,7 +37,6 @@ public class WifiWidget extends LinearLayout implements OnClickListener {
status.setLayoutParams(WRAP_WRAP_1); status.setLayoutParams(WRAP_WRAP_1);
WifiManager wifi = (WifiManager) ctx.getSystemService(WIFI_SERVICE); WifiManager wifi = (WifiManager) ctx.getSystemService(WIFI_SERVICE);
if(wifi == null) { if(wifi == null) {
wifiStateChanged(null);
ImageView warning = new ImageView(ctx); ImageView warning = new ImageView(ctx);
warning.setPadding(5, 5, 5, 5); warning.setPadding(5, 5, 5, 5);
warning.setImageResource(R.drawable.alerts_and_states_warning); warning.setImageResource(R.drawable.alerts_and_states_warning);
@@ -52,7 +48,6 @@ public class WifiWidget extends LinearLayout implements OnClickListener {
String networkName = info.getSSID(); String networkName = info.getSSID();
int networkId = info.getNetworkId(); int networkId = info.getNetworkId();
if(networkName == null || networkId == -1) { if(networkName == null || networkId == -1) {
wifiStateChanged(null);
ImageView warning = new ImageView(ctx); ImageView warning = new ImageView(ctx);
warning.setPadding(5, 5, 5, 5); warning.setPadding(5, 5, 5, 5);
warning.setImageResource(R.drawable.alerts_and_states_warning); warning.setImageResource(R.drawable.alerts_and_states_warning);
@@ -64,7 +59,6 @@ public class WifiWidget extends LinearLayout implements OnClickListener {
settings.setOnClickListener(this); settings.setOnClickListener(this);
addView(settings); addView(settings);
} else { } else {
wifiStateChanged(networkName);
ImageView ok = new ImageView(ctx); ImageView ok = new ImageView(ctx);
ok.setPadding(5, 5, 5, 5); ok.setPadding(5, 5, 5, 5);
ok.setImageResource(R.drawable.navigation_accept); ok.setImageResource(R.drawable.navigation_accept);
@@ -79,7 +73,6 @@ public class WifiWidget extends LinearLayout implements OnClickListener {
addView(settings); addView(settings);
} }
} else { } else {
wifiStateChanged(null);
ImageView warning = new ImageView(ctx); ImageView warning = new ImageView(ctx);
warning.setPadding(5, 5, 5, 5); warning.setPadding(5, 5, 5, 5);
warning.setImageResource(R.drawable.alerts_and_states_warning); warning.setImageResource(R.drawable.alerts_and_states_warning);
@@ -93,10 +86,6 @@ public class WifiWidget extends LinearLayout implements OnClickListener {
} }
} }
private void wifiStateChanged(String networkName) {
if(listener != null) listener.wifiStateChanged(networkName);
}
public void onClick(View view) { public void onClick(View view) {
getContext().startActivity(new Intent(ACTION_WIFI_SETTINGS)); getContext().startActivity(new Intent(ACTION_WIFI_SETTINGS));
} }