diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml index 93f248c9ba9feab132a28ee6bd1a7871df567c38..44027595bfa1cdb6c2e4867484687dff76cc21d9 100644 --- a/briar-android/AndroidManifest.xml +++ b/briar-android/AndroidManifest.xml @@ -25,16 +25,20 @@ </intent-filter> </service> <activity - android:name=".android.helloworld.HelloWorldActivity" + android:name=".android.HomeScreenActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity + android:name=".android.contact.ContactListActivity" + android:label="@string/contact_list_title" > + </activity> <activity android:name=".android.invitation.AddContactActivity" - android:label="@string/add_a_contact" > + android:label="@string/add_contact_title" > </activity> </application> </manifest> diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index d60559cb541c6ee2c3fe38364975686830e50363..e56b8652ad0ec137eb3e2e7598ae9b54b7d32c8d 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -1,14 +1,14 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Briar</string> - <string name="notification_title">FIXME: Notification title</string> - <string name="notification_text">FIXME: Notification text</string> - <string name="welcome">Welcome to Briar! Add a contact to get started.</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="add_contact_button">Add a contact</string> + <string name="notification_title">Syncing messages</string> + <string name="notification_text">Touch to quit.</string> + <string name="contact_list_button">Contacts</string> <string name="quit_button">Quit</string> - <string name="add_a_contact">Add 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="contact_list_title">Contacts</string> + <string name="add_contact_button">Add a contact</string> + <string name="add_contact_title">Add a Contact</string> + <string name="same_network">Briar can add contacts via Wi-Fi or Bluetooth. For security reasons, you must be face-to-face to add someone as a contact. 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="wifi_disconnected">Wi-Fi is DISCONNECTED</string> @@ -16,7 +16,7 @@ <string name="bluetooth_not_available">Bluetooth is not available on this device</string> <string name="bluetooth_disabled">Bluetooth is OFF</string> <string name="bluetooth_not_discoverable">Bluetooth is NOT DISCOVERABLE</string> - <string name="bluetooth_enabled">Bluetooth is ON</string> + <string name="bluetooth_enabled">Bluetooth is DISCOVERABLE</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> diff --git a/briar-android/src/net/sf/briar/android/BriarService.java b/briar-android/src/net/sf/briar/android/BriarService.java index ebcd1d04e936509414999041f372ca37fc4abe19..06c24e4b772d7e6bf10fb71efafbea53af27215a 100644 --- a/briar-android/src/net/sf/briar/android/BriarService.java +++ b/briar-android/src/net/sf/briar/android/BriarService.java @@ -1,5 +1,7 @@ package net.sf.briar.android; +import static android.app.PendingIntent.FLAG_ONE_SHOT; +import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; @@ -13,6 +15,7 @@ import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; import net.sf.briar.api.plugins.PluginManager; import roboguice.service.RoboService; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; @@ -39,13 +42,20 @@ public class BriarService extends RoboService { public void onCreate() { super.onCreate(); if(LOG.isLoggable(INFO)) LOG.info("Created"); + // Show an ongoing notification that the service is running NotificationCompat.Builder b = new NotificationCompat.Builder(this); b.setSmallIcon(R.drawable.notification_icon); b.setContentTitle(getText(R.string.notification_title)); b.setContentText(getText(R.string.notification_text)); + // Touch the notification to quit + Intent i = new Intent(this, HomeScreenActivity.class); + i.addFlags(FLAG_ACTIVITY_CLEAR_TOP); + i.putExtra("net.sf.briar.QUIT", true); + PendingIntent pi = PendingIntent.getActivity(this, 0, i, FLAG_ONE_SHOT); + b.setContentIntent(pi); b.setOngoing(true); startForeground(1, b.build()); - if(LOG.isLoggable(INFO)) LOG.info("Running in the foreground"); + // Start the services in the background thread new Thread() { @Override public void run() { @@ -69,6 +79,7 @@ public class BriarService extends RoboService { public void onDestroy() { super.onDestroy(); if(LOG.isLoggable(INFO)) LOG.info("Destroyed"); + // Stop the services in a background thread new Thread() { @Override public void run() { @@ -117,14 +128,14 @@ public class BriarService extends RoboService { startupLatch.await(); } - public void shutdown() { - stopSelf(); - } - public void waitForShutdown() throws InterruptedException { shutdownLatch.await(); } + public void shutdown() { + stopSelf(); + } + public class BriarBinder extends Binder { public BriarService getService() { diff --git a/briar-android/src/net/sf/briar/android/HomeScreenActivity.java b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..c6db489c9340f4e32bf8256c36f8b963c5bb0214 --- /dev/null +++ b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java @@ -0,0 +1,124 @@ +package net.sf.briar.android; + +import static android.view.Gravity.CENTER; +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 static java.util.logging.Level.INFO; + +import java.util.logging.Logger; + +import net.sf.briar.R; +import net.sf.briar.android.BriarService.BriarBinder; +import net.sf.briar.android.BriarService.BriarServiceConnection; +import net.sf.briar.android.contact.ContactListActivity; +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout.LayoutParams; + +public class HomeScreenActivity extends BriarActivity +implements OnClickListener { + + private static final Logger LOG = + Logger.getLogger(HomeScreenActivity.class.getName()); + + private final BriarServiceConnection serviceConnection = + new BriarServiceConnection(); + + Button contactListButton = null, quitButton = null; + + @Override + public void onCreate(Bundle state) { + super.onCreate(null); + if(LOG.isLoggable(INFO)) LOG.info("Created"); + LinearLayout layout = new LinearLayout(this); + layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); + layout.setOrientation(VERTICAL); + layout.setGravity(CENTER); + + // If this activity was launched from the notification bar, quit + if(getIntent().getBooleanExtra("net.sf.briar.QUIT", false)) { + ProgressBar spinner = new ProgressBar(this); + spinner.setIndeterminate(true); + layout.addView(spinner); + quit(); + } else { + LinearLayout innerLayout = new LinearLayout(this); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + contactListButton = new Button(this); + LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + contactListButton.setLayoutParams(lp); + contactListButton.setText(R.string.contact_list_button); + contactListButton.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.social_person, 0, 0, 0); + contactListButton.setOnClickListener(this); + innerLayout.addView(contactListButton); + + quitButton = new Button(this); + quitButton.setLayoutParams(lp); + quitButton.setText(R.string.quit_button); + quitButton.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.navigation_cancel, 0, 0, 0); + quitButton.setOnClickListener(this); + innerLayout.addView(quitButton); + layout.addView(innerLayout); + } + + setContentView(layout); + + // Start the service and bind to it + startService(new Intent(BriarService.class.getName())); + bindService(new Intent(BriarService.class.getName()), + serviceConnection, 0); + } + + @Override + public void onDestroy() { + super.onDestroy(); + unbindService(serviceConnection); + } + + public void onClick(View view) { + if(view == contactListButton) + startActivity(new Intent(this, ContactListActivity.class)); + else if(view == quitButton) quit(); + } + + private void quit() { + new Thread() { + @Override + public void run() { + try { + // Wait for the service to be bound and started + IBinder binder = serviceConnection.waitForBinder(); + BriarService service = ((BriarBinder) binder).getService(); + service.waitForStartup(); + // Shut down the service and wait for it to shut down + if(LOG.isLoggable(INFO)) LOG.info("Shutting down service"); + service.shutdown(); + service.waitForShutdown(); + // Finish the activity and kill the JVM + runOnUiThread(new Runnable() { + public void run() { + finish(); + if(LOG.isLoggable(INFO)) LOG.info("Exiting"); + System.exit(0); + } + }); + } catch(InterruptedException e) { + if(LOG.isLoggable(INFO)) + LOG.info("Interrupted while waiting for service"); + } + } + }.start(); + } +} diff --git a/briar-android/src/net/sf/briar/android/helloworld/HelloWorldActivity.java b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java similarity index 67% rename from briar-android/src/net/sf/briar/android/helloworld/HelloWorldActivity.java rename to briar-android/src/net/sf/briar/android/contact/ContactListActivity.java index 281267ae5efaf2836182f08844ab5687a51a6479..ef3b7897a8f35d06bf04b5ae4429e0f272ded59a 100644 --- a/briar-android/src/net/sf/briar/android/helloworld/HelloWorldActivity.java +++ b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java @@ -1,10 +1,8 @@ -package net.sf.briar.android.helloworld; +package net.sf.briar.android.contact; -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 static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; @@ -39,15 +37,14 @@ import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RelativeLayout.LayoutParams; -import android.widget.TextView; import com.google.inject.Inject; -public class HelloWorldActivity extends BriarActivity +public class ContactListActivity extends BriarActivity implements OnClickListener, DatabaseListener { private static final Logger LOG = - Logger.getLogger(HelloWorldActivity.class.getName()); + Logger.getLogger(ContactListActivity.class.getName()); private final BriarServiceConnection serviceConnection = new BriarServiceConnection(); @@ -55,7 +52,6 @@ implements OnClickListener, DatabaseListener { @Inject private DatabaseComponent db; @Inject @DatabaseExecutor private Executor dbExecutor; - Button addContact = null, quit = null; private ArrayAdapter<String> adapter = null; @Override @@ -67,36 +63,6 @@ implements OnClickListener, DatabaseListener { layout.setOrientation(VERTICAL); layout.setGravity(CENTER_HORIZONTAL); - TextView welcome = new TextView(this); - welcome.setPadding(0, 0, 0, 10); - welcome.setText(R.string.welcome); - layout.addView(welcome); - - TextView faceToFace = new TextView(this); - faceToFace.setPadding(0, 0, 0, 10); - faceToFace.setText(R.string.face_to_face); - layout.addView(faceToFace); - - LinearLayout innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - addContact = new Button(this); - LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); - addContact.setLayoutParams(lp); - addContact.setText(R.string.add_contact_button); - addContact.setCompoundDrawablesWithIntrinsicBounds( - R.drawable.social_add_person, 0, 0, 0); - addContact.setOnClickListener(this); - innerLayout.addView(addContact); - - quit = new Button(this); - quit.setLayoutParams(lp); - quit.setText(R.string.quit_button); - quit.setOnClickListener(this); - innerLayout.addView(quit); - layout.addView(innerLayout); - adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, new ArrayList<String>()); @@ -104,17 +70,29 @@ implements OnClickListener, DatabaseListener { listView.setAdapter(adapter); layout.addView(listView); - setContentView(layout); + Button addContactButton = new Button(this); + LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + addContactButton.setLayoutParams(lp); + addContactButton.setText(R.string.add_contact_button); + addContactButton.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.social_add_person, 0, 0, 0); + addContactButton.setOnClickListener(this); + layout.addView(addContactButton); + setContentView(layout); + // Listen for database events db.addListener(this); - // Start the service and bind to it - startService(new Intent(BriarService.class.getName())); + // Bind to the service bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); + // Load the contact list from the DB + reloadContactList(); + // Add some fake contacts to the database in a background thread + // FIXME: Remove this dbExecutor.execute(new Runnable() { public void run() { try { @@ -137,41 +115,14 @@ implements OnClickListener, DatabaseListener { }); } - public void onClick(View view) { - if(view == addContact) - startActivity(new Intent(this, AddContactActivity.class)); - else if(view == quit) - quit(); + @Override + public void onDestroy() { + super.onDestroy(); + unbindService(serviceConnection); } - private void quit() { - new Thread() { - @Override - public void run() { - try { - // Wait for the service to be bound and started - IBinder binder = serviceConnection.waitForBinder(); - BriarService service = ((BriarBinder) binder).getService(); - service.waitForStartup(); - // Shut down the service and wait for it to shut down - if(LOG.isLoggable(INFO)) LOG.info("Shutting down service"); - service.shutdown(); - service.waitForShutdown(); - // Unbind from the service, finish the activity, and die - runOnUiThread(new Runnable() { - public void run() { - unbindService(serviceConnection); - finish(); - if(LOG.isLoggable(INFO)) LOG.info("Exiting"); - System.exit(0); - } - }); - } catch(InterruptedException e) { - if(LOG.isLoggable(INFO)) - LOG.info("Interrupted while waiting for service"); - } - } - }.start(); + public void onClick(View view) { + startActivity(new Intent(this, AddContactActivity.class)); } public void eventOccurred(DatabaseEvent e) {