From de472ba2a630cd1a9f95d2e3e7b9fdee6e006947 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Mon, 8 Apr 2013 16:01:52 +0100 Subject: [PATCH] Create an identity at startup if the database doesn't exist. --- briar-android/AndroidManifest.xml | 16 +- briar-android/project.properties | 2 +- briar-android/res/values-v11/styles.xml | 2 + briar-android/res/values/strings.xml | 4 + briar-android/res/values/styles.xml | 2 + .../net/sf/briar/android/BriarService.java | 9 +- .../sf/briar/android/HomeScreenActivity.java | 340 ++++++++++-------- .../android/LocalAuthorSpinnerAdapter.java | 58 ++- .../net/sf/briar/android/SetupActivity.java | 138 +++++++ .../briar/android/SplashScreenActivity.java | 18 +- .../android/contact/ContactListActivity.java | 41 ++- .../android/contact/ContactListAdapter.java | 4 +- .../briar/android/groups/GroupActivity.java | 19 +- .../sf/briar/android/groups/GroupAdapter.java | 7 +- .../android/groups/GroupListActivity.java | 14 +- .../android/groups/GroupListAdapter.java | 4 +- .../groups/ReadGroupMessageActivity.java | 40 +-- .../groups/WriteGroupMessageActivity.java | 46 +-- .../android/helloworld/HelloWorldModule.java | 9 +- .../identity/CreateIdentityActivity.java | 165 +++++++++ .../invitation/AddContactActivity.java | 19 +- .../android/invitation/AddContactView.java | 4 +- .../android/invitation/BluetoothWidget.java | 4 +- .../android/invitation/CodeEntryWidget.java | 8 +- .../invitation/CodesDoNotMatchView.java | 4 +- .../invitation/ConnectionFailedView.java | 4 +- .../android/invitation/ContactAddedView.java | 6 +- .../android/invitation/NetworkSetupView.java | 18 +- .../briar/android/invitation/WifiWidget.java | 4 +- .../messages/ConversationActivity.java | 34 +- .../android/messages/ConversationAdapter.java | 58 ++- .../messages/ConversationListActivity.java | 11 +- .../messages/ConversationListAdapter.java | 6 +- .../messages/ConversationListItem.java | 5 + .../messages/ReadPrivateMessageActivity.java | 34 +- .../messages/WritePrivateMessageActivity.java | 49 +-- .../android/widgets/HorizontalBorder.java | 7 +- .../sf/briar/api/db/DatabaseComponent.java | 8 +- .../net/sf/briar/api/db/DatabaseConfig.java | 4 +- briar-core/src/net/sf/briar/db/Database.java | 8 +- .../sf/briar/db/DatabaseComponentImpl.java | 5 +- .../src/net/sf/briar/db/H2Database.java | 13 +- .../src/net/sf/briar/db/JdbcDatabase.java | 76 ++-- .../src/net/sf/briar/TestDatabaseConfig.java | 6 +- .../sf/briar/db/DatabaseComponentTest.java | 7 +- .../src/net/sf/briar/db/H2DatabaseTest.java | 3 +- .../SimplexMessagingIntegrationTest.java | 4 +- 47 files changed, 931 insertions(+), 416 deletions(-) create mode 100644 briar-android/src/net/sf/briar/android/SetupActivity.java create mode 100644 briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml index ad48f4aea1..711d5752b4 100644 --- a/briar-android/AndroidManifest.xml +++ b/briar-android/AndroidManifest.xml @@ -24,6 +24,14 @@ <action android:name="net.sf.briar.android.BriarService" /> </intent-filter> </service> + <activity + android:name=".android.HomeScreenActivity" + android:label="@string/app_name" > + </activity> + <activity + android:name=".android.SetupActivity" + android:label="@string/app_name" > + </activity> <activity android:name=".android.SplashScreenActivity" android:label="@string/app_name" > @@ -32,10 +40,6 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity - android:name=".android.HomeScreenActivity" - android:label="@string/app_name" > - </activity> <activity android:name=".android.contact.ContactListActivity" android:label="@string/contact_list_title" > @@ -56,6 +60,10 @@ android:name=".android.groups.WriteGroupMessageActivity" android:label="@string/compose_group_title" > </activity> + <activity + android:name=".android.identity.CreateIdentityActivity" + android:label="@string/create_identity_title" > + </activity> <activity android:name=".android.invitation.AddContactActivity" android:label="@string/add_contact_title" > diff --git a/briar-android/project.properties b/briar-android/project.properties index 9b84a6b4bf..a3ee5ab64f 100644 --- a/briar-android/project.properties +++ b/briar-android/project.properties @@ -11,4 +11,4 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-16 +target=android-17 diff --git a/briar-android/res/values-v11/styles.xml b/briar-android/res/values-v11/styles.xml index f5476f167a..dbc0841459 100644 --- a/briar-android/res/values-v11/styles.xml +++ b/briar-android/res/values-v11/styles.xml @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <style name="LightTheme" parent="android:Theme.Holo.Light" /> + <integer name="horizontal_border_width">5</integer> + <integer name="spinner_padding">10</integer> </resources> \ No newline at end of file diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index b43e6620e1..93f292b471 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -49,4 +49,8 @@ <string name="groups_title">Groups</string> <string name="compose_group_title">New Post</string> <string name="blogs_title">Blogs</string> + <string name="create_identity_item">New identity\u2026</string> + <string name="create_identity_title">Create an Identity</string> + <string name="choose_nickname">Choose your nickname:</string> + <string name="create_button">Create</string> </resources> diff --git a/briar-android/res/values/styles.xml b/briar-android/res/values/styles.xml index 7974ea7455..a65656192c 100644 --- a/briar-android/res/values/styles.xml +++ b/briar-android/res/values/styles.xml @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <style name="LightTheme" parent="android:Theme.Light" /> + <integer name="horizontal_border_width">2</integer> + <integer name="spinner_padding">0</integer> </resources> \ No newline at end of file diff --git a/briar-android/src/net/sf/briar/android/BriarService.java b/briar-android/src/net/sf/briar/android/BriarService.java index 0a1bfa11e3..bf96ef3254 100644 --- a/briar-android/src/net/sf/briar/android/BriarService.java +++ b/briar-android/src/net/sf/briar/android/BriarService.java @@ -56,7 +56,7 @@ public class BriarService extends RoboService { b.setContentIntent(pi); b.setOngoing(true); startForeground(1, b.build()); - // Start the services in the background thread + // Start the services in a background thread new Thread() { @Override public void run() { @@ -92,8 +92,11 @@ public class BriarService extends RoboService { private void startServices() { try { if(LOG.isLoggable(INFO)) LOG.info("Starting"); - db.open(false); - if(LOG.isLoggable(INFO)) LOG.info("Database opened"); + boolean reopened = db.open(); + if(LOG.isLoggable(INFO)) { + if(reopened) LOG.info("Database reopened"); + else LOG.info("Database created"); + } keyManager.start(); if(LOG.isLoggable(INFO)) LOG.info("Key manager started"); int pluginsStarted = pluginManager.start(this); diff --git a/briar-android/src/net/sf/briar/android/HomeScreenActivity.java b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java index 3cf5159051..8aeb809025 100644 --- a/briar-android/src/net/sf/briar/android/HomeScreenActivity.java +++ b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java @@ -3,9 +3,12 @@ package net.sf.briar.android; import static android.view.Gravity.CENTER; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static java.util.logging.Level.INFO; +import static java.util.logging.Level.WARNING; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Executor; import java.util.logging.Logger; import net.sf.briar.R; @@ -14,7 +17,11 @@ import net.sf.briar.android.BriarService.BriarServiceConnection; import net.sf.briar.android.contact.ContactListActivity; import net.sf.briar.android.groups.GroupListActivity; import net.sf.briar.android.messages.ConversationListActivity; -import net.sf.briar.android.widgets.CommonLayoutParams; +import net.sf.briar.api.LocalAuthor; +import net.sf.briar.api.android.DatabaseUiExecutor; +import net.sf.briar.api.android.ReferenceManager; +import net.sf.briar.api.db.DatabaseComponent; +import net.sf.briar.api.db.DbException; import android.content.Intent; import android.os.Bundle; import android.os.IBinder; @@ -28,6 +35,8 @@ import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; +import com.google.inject.Inject; + public class HomeScreenActivity extends BriarActivity { private static final Logger LOG = @@ -35,163 +44,49 @@ public class HomeScreenActivity extends BriarActivity { private final BriarServiceConnection serviceConnection = new BriarServiceConnection(); - private final List<Button> buttons = new ArrayList<Button>(); - public HomeScreenActivity() { - super(); - } + @Inject private ReferenceManager referenceManager = null; + @Inject @DatabaseUiExecutor private Executor dbUiExecutor = null; + + // Fields that are accessed from background threads must be volatile + @Inject private volatile DatabaseComponent db = null; @Override public void onCreate(Bundle state) { super.onCreate(null); - if(LOG.isLoggable(INFO)) LOG.info("Created"); - - // If this activity was launched from the notification bar, quit - if(getIntent().getBooleanExtra("net.sf.briar.QUIT", false)) { + Intent i = getIntent(); + boolean quit = i.getBooleanExtra("net.sf.briar.QUIT", false); + long handle = i.getLongExtra("net.sf.briar.LOCAL_AUTHOR_HANDLE", -1); + if(quit) { + // The activity was launched from the notification bar + showSpinner(); quit(); + } else if(handle != -1) { + // The activity was launched from the setup wizard + showSpinner(); + storeLocalAuthor(referenceManager.removeReference(handle, + LocalAuthor.class)); } else { - ListView.LayoutParams matchParent = - new ListView.LayoutParams(MATCH_PARENT, MATCH_PARENT); - - Button contactsButton = new Button(this); - contactsButton.setLayoutParams(matchParent); - contactsButton.setBackgroundResource(0); - contactsButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.social_person, 0, 0); - contactsButton.setText(R.string.contact_list_button); - contactsButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - startActivity(new Intent(HomeScreenActivity.this, - ContactListActivity.class)); - } - }); - buttons.add(contactsButton); - - Button messagesButton = new Button(this); - messagesButton.setLayoutParams(matchParent); - messagesButton.setBackgroundResource(0); - messagesButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.content_email, 0, 0); - messagesButton.setText(R.string.messages_button); - messagesButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - startActivity(new Intent(HomeScreenActivity.this, - ConversationListActivity.class)); - } - }); - buttons.add(messagesButton); - - Button groupsButton = new Button(this); - groupsButton.setLayoutParams(matchParent); - groupsButton.setBackgroundResource(0); - groupsButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.social_chat, 0, 0); - groupsButton.setText(R.string.groups_button); - groupsButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - Intent i = new Intent(HomeScreenActivity.this, - GroupListActivity.class); - i.putExtra("net.sf.briar.RESTRICTED", false); - i.putExtra("net.sf.briar.TITLE", - getResources().getString(R.string.groups_title)); - startActivity(i); - } - }); - buttons.add(groupsButton); - - Button blogsButton = new Button(this); - blogsButton.setLayoutParams(matchParent); - blogsButton.setBackgroundResource(0); - blogsButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.social_blog, 0, 0); - blogsButton.setText(R.string.blogs_button); - blogsButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - Intent i = new Intent(HomeScreenActivity.this, - GroupListActivity.class); - i.putExtra("net.sf.briar.RESTRICTED", true); - i.putExtra("net.sf.briar.TITLE", - getResources().getString(R.string.blogs_title)); - startActivity(i); - } - }); - buttons.add(blogsButton); - - Button syncButton = new Button(this); - syncButton.setLayoutParams(matchParent); - syncButton.setBackgroundResource(0); - syncButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.navigation_refresh, 0, 0); - syncButton.setText(R.string.synchronize_button); - syncButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - // FIXME: Hook this button up to an activity - } - }); - buttons.add(syncButton); - - Button quitButton = new Button(this); - quitButton.setLayoutParams(matchParent); - quitButton.setBackgroundResource(0); - quitButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.device_access_accounts, 0, 0); - quitButton.setText(R.string.quit_button); - quitButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - quit(); - } - }); - buttons.add(quitButton); - - GridView grid = new GridView(this); - grid.setLayoutParams(matchParent); - grid.setGravity(CENTER); - grid.setPadding(5, 5, 5, 5); - grid.setBackgroundColor(getResources().getColor( - R.color.home_screen_background)); - grid.setNumColumns(2); - grid.setAdapter(new BaseAdapter() { - - public int getCount() { - return buttons.size(); - } - - public Object getItem(int position) { - return buttons.get(position); - } - - public long getItemId(int position) { - return 0; - } - - public View getView(int position, View convertView, - ViewGroup parent) { - return buttons.get(position); - } - }); - setContentView(grid); + // The activity was launched from the splash screen + showButtons(); } - // 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); - } - - private void quit() { + private void showSpinner() { LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_MATCH); + layout.setLayoutParams(MATCH_MATCH); layout.setGravity(CENTER); - ProgressBar spinner = new ProgressBar(this); - spinner.setIndeterminate(true); - layout.addView(spinner); + ProgressBar progress = new ProgressBar(this); + progress.setIndeterminate(true); + layout.addView(progress); setContentView(layout); + } + + private void quit() { new Thread() { @Override public void run() { @@ -204,19 +99,172 @@ public class HomeScreenActivity extends BriarActivity { if(LOG.isLoggable(INFO)) LOG.info("Shutting down service"); service.shutdown(); service.waitForShutdown(); - // Finish the activity and kill the JVM + } catch(InterruptedException e) { + if(LOG.isLoggable(INFO)) + LOG.info("Interrupted while waiting for service"); + } + // Finish the activity and kill the JVM + runOnUiThread(new Runnable() { + public void run() { + finish(); + if(LOG.isLoggable(INFO)) LOG.info("Exiting"); + System.exit(0); + } + }); + } + }.start(); + } + + private void storeLocalAuthor(final LocalAuthor a) { + dbUiExecutor.execute(new Runnable() { + public void run() { + try { + serviceConnection.waitForStartup(); + db.addLocalAuthor(a); runOnUiThread(new Runnable() { public void run() { - finish(); - if(LOG.isLoggable(INFO)) LOG.info("Exiting"); - System.exit(0); + showButtons(); } }); + } catch(DbException e) { + if(LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); } catch(InterruptedException e) { if(LOG.isLoggable(INFO)) LOG.info("Interrupted while waiting for service"); + Thread.currentThread().interrupt(); } } - }.start(); + }); + } + + private void showButtons() { + ListView.LayoutParams matchMatch = + new ListView.LayoutParams(MATCH_PARENT, MATCH_PARENT); + final List<Button> buttons = new ArrayList<Button>(); + + Button contactsButton = new Button(this); + contactsButton.setLayoutParams(matchMatch); + contactsButton.setBackgroundResource(0); + contactsButton.setCompoundDrawablesWithIntrinsicBounds(0, + R.drawable.social_person, 0, 0); + contactsButton.setText(R.string.contact_list_button); + contactsButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + startActivity(new Intent(HomeScreenActivity.this, + ContactListActivity.class)); + } + }); + buttons.add(contactsButton); + + Button messagesButton = new Button(this); + messagesButton.setLayoutParams(matchMatch); + messagesButton.setBackgroundResource(0); + messagesButton.setCompoundDrawablesWithIntrinsicBounds(0, + R.drawable.content_email, 0, 0); + messagesButton.setText(R.string.messages_button); + messagesButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + startActivity(new Intent(HomeScreenActivity.this, + ConversationListActivity.class)); + } + }); + buttons.add(messagesButton); + + Button groupsButton = new Button(this); + groupsButton.setLayoutParams(matchMatch); + groupsButton.setBackgroundResource(0); + groupsButton.setCompoundDrawablesWithIntrinsicBounds(0, + R.drawable.social_chat, 0, 0); + groupsButton.setText(R.string.groups_button); + groupsButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + Intent i = new Intent(HomeScreenActivity.this, + GroupListActivity.class); + i.putExtra("net.sf.briar.RESTRICTED", false); + i.putExtra("net.sf.briar.TITLE", + getResources().getString(R.string.groups_title)); + startActivity(i); + } + }); + buttons.add(groupsButton); + + Button blogsButton = new Button(this); + blogsButton.setLayoutParams(matchMatch); + blogsButton.setBackgroundResource(0); + blogsButton.setCompoundDrawablesWithIntrinsicBounds(0, + R.drawable.social_blog, 0, 0); + blogsButton.setText(R.string.blogs_button); + blogsButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + Intent i = new Intent(HomeScreenActivity.this, + GroupListActivity.class); + i.putExtra("net.sf.briar.RESTRICTED", true); + i.putExtra("net.sf.briar.TITLE", + getResources().getString(R.string.blogs_title)); + startActivity(i); + } + }); + buttons.add(blogsButton); + + Button syncButton = new Button(this); + syncButton.setLayoutParams(matchMatch); + syncButton.setBackgroundResource(0); + syncButton.setCompoundDrawablesWithIntrinsicBounds(0, + R.drawable.navigation_refresh, 0, 0); + syncButton.setText(R.string.synchronize_button); + syncButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + // FIXME: Hook this button up to an activity + } + }); + buttons.add(syncButton); + + Button quitButton = new Button(this); + quitButton.setLayoutParams(matchMatch); + quitButton.setBackgroundResource(0); + quitButton.setCompoundDrawablesWithIntrinsicBounds(0, + R.drawable.device_access_accounts, 0, 0); + quitButton.setText(R.string.quit_button); + quitButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + quit(); + } + }); + buttons.add(quitButton); + + GridView grid = new GridView(this); + grid.setLayoutParams(matchMatch); + grid.setGravity(CENTER); + grid.setPadding(5, 5, 5, 5); + grid.setBackgroundColor(getResources().getColor( + R.color.home_screen_background)); + grid.setNumColumns(2); + grid.setAdapter(new BaseAdapter() { + + public int getCount() { + return buttons.size(); + } + + public Object getItem(int position) { + return buttons.get(position); + } + + public long getItemId(int position) { + return 0; + } + + public View getView(int position, View convertView, + ViewGroup parent) { + return buttons.get(position); + } + }); + setContentView(grid); + } + + @Override + public void onDestroy() { + super.onDestroy(); + unbindService(serviceConnection); } } diff --git a/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java index 589c60efb2..7a65c92fc1 100644 --- a/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java +++ b/briar-android/src/net/sf/briar/android/LocalAuthorSpinnerAdapter.java @@ -1,36 +1,76 @@ package net.sf.briar.android; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import net.sf.briar.R; +import net.sf.briar.api.Author; import net.sf.briar.api.LocalAuthor; import android.content.Context; +import android.content.res.Resources; +import android.util.Log; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; import android.widget.SpinnerAdapter; import android.widget.TextView; -public class LocalAuthorSpinnerAdapter extends ArrayAdapter<LocalAuthor> +public class LocalAuthorSpinnerAdapter extends BaseAdapter implements SpinnerAdapter { - public LocalAuthorSpinnerAdapter(Context context) { - super(context, android.R.layout.simple_spinner_item, - new ArrayList<LocalAuthor>()); + private final Context ctx; + private final List<LocalAuthor> list = new ArrayList<LocalAuthor>(); + + public LocalAuthorSpinnerAdapter(Context ctx) { + this.ctx = ctx; + } + + public void add(LocalAuthor a) { + list.add(a); + notifyDataSetChanged(); + } + + public void clear() { + list.clear(); + notifyDataSetChanged(); + } + + public int getCount() { + return list.size() + 1; + } + + public LocalAuthor getItem(int position) { + if(position == list.size()) return null; + return list.get(position); + } + + public long getItemId(int position) { + return android.R.layout.simple_spinner_item; + } + + public void sort(Comparator<Author> comparator) { + Collections.sort(list, comparator); } - @Override public View getView(int position, View convertView, ViewGroup parent) { - TextView name = new TextView(getContext()); + Log.i("Briar", "getView: " + position); + TextView name = new TextView(ctx); name.setTextSize(18); name.setMaxLines(1); - name.setPadding(10, 10, 10, 10); - name.setText(getItem(position).getName()); + Resources res = ctx.getResources(); + int pad = res.getInteger(R.integer.spinner_padding); + name.setPadding(pad, pad, pad, pad); + if(position == list.size()) name.setText(R.string.create_identity_item); + else name.setText(list.get(position).getName()); return name; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { + Log.i("Briar", "getDropDownView: " + position); return getView(position, convertView, parent); } } diff --git a/briar-android/src/net/sf/briar/android/SetupActivity.java b/briar-android/src/net/sf/briar/android/SetupActivity.java new file mode 100644 index 0000000000..b4dfda23c5 --- /dev/null +++ b/briar-android/src/net/sf/briar/android/SetupActivity.java @@ -0,0 +1,138 @@ +package net.sf.briar.android; + +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; +import static android.widget.LinearLayout.VERTICAL; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP; + +import java.io.IOException; +import java.security.KeyPair; +import java.util.concurrent.Executor; + +import net.sf.briar.R; +import net.sf.briar.api.AuthorFactory; +import net.sf.briar.api.LocalAuthor; +import net.sf.briar.api.android.ReferenceManager; +import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.crypto.CryptoExecutor; +import android.content.Intent; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; + +import com.google.inject.Inject; + +public class SetupActivity extends BriarActivity +implements OnEditorActionListener, OnClickListener { + + @Inject @CryptoExecutor private Executor cryptoExecutor; + private EditText nicknameEntry = null; + private Button createButton = null; + private ProgressBar progress = null; + + // Fields that are accessed from background threads must be volatile + @Inject private volatile CryptoComponent crypto; + @Inject private volatile AuthorFactory authorFactory; + @Inject private volatile ReferenceManager referenceManager; + + @Override + public void onCreate(Bundle state) { + super.onCreate(null); + LinearLayout layout = new LinearLayout(this); + layout.setLayoutParams(MATCH_MATCH); + layout.setOrientation(VERTICAL); + layout.setGravity(CENTER_HORIZONTAL); + + TextView chooseNickname = new TextView(this); + chooseNickname.setGravity(CENTER); + chooseNickname.setTextSize(18); + chooseNickname.setPadding(10, 10, 10, 10); + chooseNickname.setText(R.string.choose_nickname); + layout.addView(chooseNickname); + + nicknameEntry = new EditText(this); + nicknameEntry.setTextSize(18); + nicknameEntry.setMaxLines(1); + nicknameEntry.setPadding(10, 10, 10, 10); + nicknameEntry.setOnEditorActionListener(this); + layout.addView(nicknameEntry); + + createButton = new Button(this); + createButton.setLayoutParams(WRAP_WRAP); + createButton.setText(R.string.create_button); + createButton.setOnClickListener(this); + layout.addView(createButton); + + progress = new ProgressBar(this); + progress.setLayoutParams(WRAP_WRAP); + progress.setIndeterminate(true); + progress.setVisibility(GONE); + layout.addView(progress); + + setContentView(layout); + } + + public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { + validateNickname(); + return true; + } + + public void onClick(View view) { + if(!validateNickname()) return; + final String nickname = nicknameEntry.getText().toString(); + // Replace the button with a progress bar + createButton.setVisibility(GONE); + progress.setVisibility(VISIBLE); + // Create the identity in a background thread + cryptoExecutor.execute(new Runnable() { + public void run() { + KeyPair keyPair = crypto.generateSignatureKeyPair(); + final byte[] publicKey = keyPair.getPublic().getEncoded(); + final byte[] privateKey = keyPair.getPrivate().getEncoded(); + LocalAuthor a; + try { + a = authorFactory.createLocalAuthor(nickname, publicKey, + privateKey); + } catch(IOException e) { + throw new RuntimeException(e); + } + showHomeScreen(referenceManager.putReference(a, + LocalAuthor.class)); + } + }); + } + + private void showHomeScreen(final long handle) { + runOnUiThread(new Runnable() { + public void run() { + Intent i = new Intent(SetupActivity.this, + HomeScreenActivity.class); + i.putExtra("net.sf.briar.LOCAL_AUTHOR_HANDLE", handle); + i.setFlags(FLAG_ACTIVITY_NEW_TASK); + startActivity(i); + finish(); + } + }); + } + + private boolean validateNickname() { + if(nicknameEntry.getText().toString().equals("")) return false; + // Hide the soft keyboard + Object o = getSystemService(INPUT_METHOD_SERVICE); + ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0); + return true; + } +} diff --git a/briar-android/src/net/sf/briar/android/SplashScreenActivity.java b/briar-android/src/net/sf/briar/android/SplashScreenActivity.java index 70821a537a..54d529c8c9 100644 --- a/briar-android/src/net/sf/briar/android/SplashScreenActivity.java +++ b/briar-android/src/net/sf/briar/android/SplashScreenActivity.java @@ -1,15 +1,18 @@ package net.sf.briar.android; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME; import static android.view.Gravity.CENTER; import net.sf.briar.android.widgets.CommonLayoutParams; +import net.sf.briar.api.db.DatabaseConfig; +import roboguice.RoboGuice; import roboguice.activity.RoboSplashActivity; import android.content.Intent; import android.os.Bundle; import android.widget.LinearLayout; import android.widget.ProgressBar; +import com.google.inject.Injector; + public class SplashScreenActivity extends RoboSplashActivity { public SplashScreenActivity() { @@ -30,8 +33,15 @@ public class SplashScreenActivity extends RoboSplashActivity { } protected void startNextActivity() { - Intent i = new Intent(this, HomeScreenActivity.class); - i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME); - startActivity(i); + Injector guice = RoboGuice.getBaseApplicationInjector(getApplication()); + if(guice.getInstance(DatabaseConfig.class).databaseExists()) { + Intent i = new Intent(this, HomeScreenActivity.class); + i.setFlags(FLAG_ACTIVITY_NEW_TASK); + startActivity(i); + } else { + Intent i = new Intent(this, SetupActivity.class); + i.setFlags(FLAG_ACTIVITY_NEW_TASK); + startActivity(i); + } } } diff --git a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java index 784233dd36..1c1af5c8e3 100644 --- a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java +++ b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java @@ -1,9 +1,14 @@ package net.sf.briar.android.contact; +import static android.view.Gravity.CENTER; import static android.view.Gravity.CENTER_HORIZONTAL; +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; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1; import java.util.Collection; import java.util.Comparator; @@ -15,8 +20,8 @@ import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; import net.sf.briar.android.invitation.AddContactActivity; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; +import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.Contact; import net.sf.briar.api.ContactId; import net.sf.briar.api.android.DatabaseUiExecutor; @@ -50,7 +55,7 @@ implements OnClickListener, DatabaseListener, ConnectionListener { @Inject private ConnectionRegistry connectionRegistry; private ContactListAdapter adapter = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; @@ -58,33 +63,37 @@ implements OnClickListener, DatabaseListener, ConnectionListener { public void onCreate(Bundle state) { super.onCreate(null); LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_MATCH); + layout.setLayoutParams(MATCH_MATCH); layout.setOrientation(VERTICAL); layout.setGravity(CENTER_HORIZONTAL); adapter = new ContactListAdapter(this); ListView list = new ListView(this); // Give me all the width and all the unused height - list.setLayoutParams(CommonLayoutParams.MATCH_WRAP_1); + list.setLayoutParams(MATCH_WRAP_1); list.setAdapter(adapter); list.setOnItemClickListener(adapter); layout.addView(list); layout.addView(new HorizontalBorder(this)); + LinearLayout footer = new LinearLayout(this); + footer.setLayoutParams(MATCH_WRAP); + footer.setOrientation(HORIZONTAL); + footer.setGravity(CENTER); + footer.addView(new HorizontalSpace(this)); + ImageButton addContactButton = new ImageButton(this); addContactButton.setBackgroundResource(0); addContactButton.setImageResource(R.drawable.social_add_person); addContactButton.setOnClickListener(this); - layout.addView(addContactButton); + footer.addView(addContactButton); + footer.addView(new HorizontalSpace(this)); + layout.addView(footer); setContentView(layout); - // Listen for contacts being added or removed - db.addListener(this); - // Listen for contacts connecting or disconnecting - connectionRegistry.addListener(this); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } @@ -92,6 +101,8 @@ implements OnClickListener, DatabaseListener, ConnectionListener { @Override public void onResume() { super.onResume(); + db.addListener(this); + connectionRegistry.addListener(this); loadContacts(); } @@ -133,10 +144,15 @@ implements OnClickListener, DatabaseListener, ConnectionListener { } @Override - public void onDestroy() { - super.onDestroy(); + public void onPause() { + super.onPause(); db.removeListener(this); connectionRegistry.removeListener(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); unbindService(serviceConnection); } @@ -145,7 +161,6 @@ implements OnClickListener, DatabaseListener, ConnectionListener { } public void eventOccurred(DatabaseEvent e) { - // These events should be rare, so just reload the list if(e instanceof ContactAddedEvent) loadContacts(); else if(e instanceof ContactRemovedEvent) loadContacts(); } diff --git a/briar-android/src/net/sf/briar/android/contact/ContactListAdapter.java b/briar-android/src/net/sf/briar/android/contact/ContactListAdapter.java index 1acf42a1ce..8e7a60d24f 100644 --- a/briar-android/src/net/sf/briar/android/contact/ContactListAdapter.java +++ b/briar-android/src/net/sf/briar/android/contact/ContactListAdapter.java @@ -2,11 +2,11 @@ package net.sf.briar.android.contact; import static android.view.Gravity.CENTER_VERTICAL; import static android.widget.LinearLayout.HORIZONTAL; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import java.util.ArrayList; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import android.content.Context; import android.text.Html; import android.text.format.DateUtils; @@ -44,7 +44,7 @@ implements OnItemClickListener { TextView name = new TextView(ctx); // Give me all the unused width - name.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + name.setLayoutParams(WRAP_WRAP_1); name.setTextSize(18); name.setMaxLines(1); name.setPadding(0, 10, 10, 10); diff --git a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java index 75ed4167c0..c576e748fa 100644 --- a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java @@ -4,6 +4,8 @@ import static android.view.Gravity.CENTER_HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1; import java.util.Collection; import java.util.concurrent.Executor; @@ -14,7 +16,6 @@ import net.sf.briar.android.AscendingHeaderComparator; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; import net.sf.briar.api.Author; import net.sf.briar.api.android.DatabaseUiExecutor; @@ -55,7 +56,7 @@ OnClickListener, OnItemClickListener { private GroupAdapter adapter = null; private ListView list = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; private volatile GroupId groupId = null; @@ -66,22 +67,22 @@ OnClickListener, OnItemClickListener { Intent i = getIntent(); restricted = i.getBooleanExtra("net.sf.briar.RESTRICTED", false); - byte[] id = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); - if(id == null) throw new IllegalStateException(); - groupId = new GroupId(id); + byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); + if(b == null) throw new IllegalStateException(); + groupId = new GroupId(b); groupName = i.getStringExtra("net.sf.briar.GROUP_NAME"); if(groupName == null) throw new IllegalStateException(); setTitle(groupName); LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_MATCH); + layout.setLayoutParams(MATCH_MATCH); layout.setOrientation(VERTICAL); layout.setGravity(CENTER_HORIZONTAL); adapter = new GroupAdapter(this); list = new ListView(this); // Give me all the width and all the unused height - list.setLayoutParams(CommonLayoutParams.MATCH_WRAP_1); + list.setLayoutParams(MATCH_WRAP_1); list.setAdapter(adapter); list.setOnItemClickListener(this); layout.addView(list); @@ -96,7 +97,7 @@ OnClickListener, OnItemClickListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } @@ -234,8 +235,6 @@ OnClickListener, OnItemClickListener { } i.putExtra("net.sf.briar.CONTENT_TYPE", item.getContentType()); i.putExtra("net.sf.briar.TIMESTAMP", item.getTimestamp()); - i.putExtra("net.sf.briar.FIRST", position == 0); - i.putExtra("net.sf.briar.LAST", position == adapter.getCount() - 1); startActivityForResult(i, position); } } diff --git a/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java b/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java index 87930d39d3..048f622564 100644 --- a/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java +++ b/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java @@ -6,13 +6,13 @@ import static android.view.View.INVISIBLE; import static android.widget.LinearLayout.HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import static net.sf.briar.api.messaging.Rating.GOOD; import static net.sf.briar.api.messaging.Rating.UNRATED; import java.util.ArrayList; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.Author; import net.sf.briar.api.db.GroupMessageHeader; @@ -39,6 +39,7 @@ class GroupAdapter extends ArrayAdapter<GroupMessageHeader> { public View getView(int position, View convertView, ViewGroup parent) { GroupMessageHeader item = getItem(position); Context ctx = getContext(); + // FIXME: Use a RelativeLayout LinearLayout layout = new LinearLayout(ctx); layout.setOrientation(HORIZONTAL); @@ -49,7 +50,7 @@ class GroupAdapter extends ArrayAdapter<GroupMessageHeader> { LinearLayout innerLayout = new LinearLayout(ctx); // Give me all the unused width - innerLayout.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + innerLayout.setLayoutParams(WRAP_WRAP_1); innerLayout.setOrientation(VERTICAL); LinearLayout authorLayout = new LinearLayout(ctx); @@ -66,7 +67,7 @@ class GroupAdapter extends ArrayAdapter<GroupMessageHeader> { TextView name = new TextView(ctx); // Give me all the unused width - name.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + name.setLayoutParams(WRAP_WRAP_1); name.setTextSize(18); name.setMaxLines(1); name.setPadding(0, 10, 10, 10); diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java index baa57973b4..0d7b970145 100644 --- a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java @@ -6,6 +6,9 @@ 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; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1; import java.util.ArrayList; import java.util.Collection; @@ -18,7 +21,6 @@ import net.sf.briar.R; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.android.DatabaseUiExecutor; @@ -56,7 +58,7 @@ implements OnClickListener, DatabaseListener { private ListView list = null; private ImageButton newGroupButton = null, composeButton = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; private volatile boolean restricted = false; @@ -65,7 +67,7 @@ implements OnClickListener, DatabaseListener { public void onCreate(Bundle state) { super.onCreate(null); LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_MATCH); + layout.setLayoutParams(MATCH_MATCH); layout.setOrientation(VERTICAL); layout.setGravity(CENTER_HORIZONTAL); @@ -78,7 +80,7 @@ implements OnClickListener, DatabaseListener { adapter = new GroupListAdapter(this); list = new ListView(this); // Give me all the width and all the unused height - list.setLayoutParams(CommonLayoutParams.MATCH_WRAP_1); + list.setLayoutParams(MATCH_WRAP_1); list.setAdapter(adapter); list.setOnItemClickListener(adapter); layout.addView(list); @@ -86,7 +88,7 @@ implements OnClickListener, DatabaseListener { layout.addView(new HorizontalBorder(this)); LinearLayout footer = new LinearLayout(this); - footer.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + footer.setLayoutParams(MATCH_WRAP); footer.setOrientation(HORIZONTAL); footer.setGravity(CENTER); footer.addView(new HorizontalSpace(this)); @@ -110,7 +112,7 @@ implements OnClickListener, DatabaseListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java b/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java index 2337702ea5..87b36a1e6c 100644 --- a/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java +++ b/briar-android/src/net/sf/briar/android/groups/GroupListAdapter.java @@ -4,11 +4,11 @@ import static android.graphics.Typeface.BOLD; import static android.widget.LinearLayout.HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import java.util.ArrayList; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.util.StringUtils; import android.content.Context; @@ -45,7 +45,7 @@ implements OnItemClickListener { LinearLayout innerLayout = new LinearLayout(ctx); // Give me all the unused width - innerLayout.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + innerLayout.setLayoutParams(WRAP_WRAP_1); innerLayout.setOrientation(VERTICAL); TextView name = new TextView(ctx); diff --git a/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java b/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java index 48b925723c..145dcf6700 100644 --- a/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java @@ -9,6 +9,9 @@ import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import static net.sf.briar.api.messaging.Rating.BAD; import static net.sf.briar.api.messaging.Rating.GOOD; import static net.sf.briar.api.messaging.Rating.UNRATED; @@ -21,7 +24,6 @@ import net.sf.briar.R; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.AuthorId; @@ -70,7 +72,7 @@ implements OnClickListener { private ImageButton replyButton = null; private TextView content = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; private volatile MessageId messageId = null; @@ -81,19 +83,19 @@ implements OnClickListener { super.onCreate(null); Intent i = getIntent(); - byte[] id = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); - if(id == null) throw new IllegalStateException(); - groupId = new GroupId(id); + byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); + if(b == null) throw new IllegalStateException(); + groupId = new GroupId(b); String groupName = i.getStringExtra("net.sf.briar.GROUP_NAME"); if(groupName == null) throw new IllegalStateException(); setTitle(groupName); - id = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID"); - if(id == null) throw new IllegalStateException(); - messageId = new MessageId(id); + b = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID"); + if(b == null) throw new IllegalStateException(); + messageId = new MessageId(b); String authorName = null; - id = i.getByteArrayExtra("net.sf.briar.AUTHOR_ID"); - if(id != null) { - authorId = new AuthorId(id); + b = i.getByteArrayExtra("net.sf.briar.AUTHOR_ID"); + if(b != null) { + authorId = new AuthorId(b); authorName = i.getStringExtra("net.sf.briar.AUTHOR_NAME"); if(authorName == null) throw new IllegalStateException(); String r = i.getStringExtra("net.sf.briar.RATING"); @@ -103,8 +105,6 @@ implements OnClickListener { if(contentType == null) throw new IllegalStateException(); long timestamp = i.getLongExtra("net.sf.briar.TIMESTAMP", -1); if(timestamp == -1) throw new IllegalStateException(); - boolean first = i.getBooleanExtra("net.sf.briar.FIRST", false); - boolean last = i.getBooleanExtra("net.sf.briar.LAST", false); if(state != null && bundleEncrypter.decrypt(state)) { read = state.getBoolean("net.sf.briar.READ"); @@ -114,12 +114,12 @@ implements OnClickListener { } LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + layout.setLayoutParams(MATCH_WRAP); layout.setOrientation(VERTICAL); ScrollView scrollView = new ScrollView(this); // Give me all the width and all the unused height - scrollView.setLayoutParams(CommonLayoutParams.MATCH_WRAP_1); + scrollView.setLayoutParams(MATCH_WRAP_1); LinearLayout message = new LinearLayout(this); message.setOrientation(VERTICAL); @@ -127,7 +127,7 @@ implements OnClickListener { message.setBackgroundColor(res.getColor(R.color.content_background)); LinearLayout header = new LinearLayout(this); - header.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + header.setLayoutParams(MATCH_WRAP); header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); @@ -140,7 +140,7 @@ implements OnClickListener { TextView author = new TextView(this); // Give me all the unused width - author.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + author.setLayoutParams(WRAP_WRAP_1); author.setTextSize(18); author.setMaxLines(1); author.setPadding(10, 10, 10, 10); @@ -174,7 +174,7 @@ implements OnClickListener { layout.addView(new HorizontalBorder(this)); LinearLayout footer = new LinearLayout(this); - footer.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + footer.setLayoutParams(MATCH_WRAP); footer.setOrientation(HORIZONTAL); footer.setGravity(CENTER); @@ -207,7 +207,6 @@ implements OnClickListener { prevButton.setBackgroundResource(0); prevButton.setImageResource(R.drawable.navigation_previous_item); prevButton.setOnClickListener(this); - prevButton.setEnabled(!first); footer.addView(prevButton); footer.addView(new HorizontalSpace(this)); @@ -215,7 +214,6 @@ implements OnClickListener { nextButton.setBackgroundResource(0); nextButton.setImageResource(R.drawable.navigation_next_item); nextButton.setOnClickListener(this); - nextButton.setEnabled(!last); footer.addView(nextButton); footer.addView(new HorizontalSpace(this)); @@ -228,7 +226,7 @@ implements OnClickListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } diff --git a/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java b/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java index c83c1d981a..e887fc6561 100644 --- a/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/WriteGroupMessageActivity.java @@ -5,6 +5,7 @@ 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; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -22,7 +23,6 @@ import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; import net.sf.briar.android.LocalAuthorSpinnerAdapter; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.BundleEncrypter; @@ -65,7 +65,7 @@ implements OnItemSelectedListener, OnClickListener { private ImageButton sendButton = null; private EditText content = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; @Inject private volatile MessageFactory messageFactory; @@ -81,17 +81,17 @@ implements OnItemSelectedListener, OnClickListener { Intent i = getIntent(); restricted = i.getBooleanExtra("net.sf.briar.RESTRICTED", false); - byte[] id = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); - if(id != null) groupId = new GroupId(id); - id = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); - if(id != null) parentId = new MessageId(id); + byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); + if(b != null) groupId = new GroupId(b); + b = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); + if(b != null) parentId = new MessageId(b); LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + layout.setLayoutParams(MATCH_WRAP); layout.setOrientation(VERTICAL); LinearLayout header = new LinearLayout(this); - header.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + header.setLayoutParams(MATCH_WRAP); header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); @@ -103,8 +103,8 @@ implements OnItemSelectedListener, OnClickListener { fromAdapter = new LocalAuthorSpinnerAdapter(this); fromSpinner = new Spinner(this); + fromSpinner.setAdapter(fromAdapter); fromSpinner.setOnItemSelectedListener(this); - loadLocalAuthorList(); header.addView(fromSpinner); header.addView(new HorizontalSpace(this)); @@ -118,7 +118,7 @@ implements OnItemSelectedListener, OnClickListener { layout.addView(header); header = new LinearLayout(this); - header.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + header.setLayoutParams(MATCH_WRAP); header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); @@ -132,7 +132,6 @@ implements OnItemSelectedListener, OnClickListener { toSpinner = new Spinner(this); toSpinner.setAdapter(toAdapter); toSpinner.setOnItemSelectedListener(this); - loadGroupList(); header.addView(toSpinner); layout.addView(header); @@ -146,17 +145,24 @@ implements OnItemSelectedListener, OnClickListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } - private void loadLocalAuthorList() { + @Override + public void onResume() { + super.onResume(); + loadLocalAuthors(); + loadGroups(); + } + + private void loadLocalAuthors() { dbUiExecutor.execute(new Runnable() { public void run() { try { serviceConnection.waitForStartup(); - displayLocalAuthorList(db.getLocalAuthors()); + displayLocalAuthors(db.getLocalAuthors()); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -168,7 +174,7 @@ implements OnItemSelectedListener, OnClickListener { }); } - private void displayLocalAuthorList( + private void displayLocalAuthors( final Collection<LocalAuthor> localAuthors) { runOnUiThread(new Runnable() { public void run() { @@ -179,7 +185,7 @@ implements OnItemSelectedListener, OnClickListener { }); } - private void loadGroupList() { + private void loadGroups() { dbUiExecutor.execute(new Runnable() { public void run() { try { @@ -192,7 +198,7 @@ implements OnItemSelectedListener, OnClickListener { if(!g.isRestricted()) groups.add(g); } groups = Collections.unmodifiableList(groups); - displayGroupList(groups); + displayGroups(groups); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -204,7 +210,7 @@ implements OnItemSelectedListener, OnClickListener { }); } - private void displayGroupList(final Collection<Group> groups) { + private void displayGroups(final Collection<Group> groups) { runOnUiThread(new Runnable() { public void run() { int index = -1; @@ -257,8 +263,8 @@ implements OnItemSelectedListener, OnClickListener { public void onClick(View view) { if(group == null) throw new IllegalStateException(); try { - storeMessage(localAuthor, group, - content.getText().toString().getBytes("UTF-8")); + byte[] b = content.getText().toString().getBytes("UTF-8"); + storeMessage(localAuthor, group, b); } catch(UnsupportedEncodingException e) { throw new RuntimeException(e); } diff --git a/briar-android/src/net/sf/briar/android/helloworld/HelloWorldModule.java b/briar-android/src/net/sf/briar/android/helloworld/HelloWorldModule.java index 74234a1a74..b95de675f1 100644 --- a/briar-android/src/net/sf/briar/android/helloworld/HelloWorldModule.java +++ b/briar-android/src/net/sf/briar/android/helloworld/HelloWorldModule.java @@ -32,10 +32,15 @@ public class HelloWorldModule extends AbstractModule { @Provides @Singleton DatabaseConfig getDatabaseConfig(final Application app) { + final File dir = app.getApplicationContext().getDir("db", MODE_PRIVATE); return new DatabaseConfig() { - public File getDataDirectory() { - return app.getApplicationContext().getDir("db", MODE_PRIVATE); + public boolean databaseExists() { + return dir.isDirectory() && dir.listFiles().length > 0; + } + + public File getDatabaseDirectory() { + return dir; } public char[] getPassword() { diff --git a/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java new file mode 100644 index 0000000000..fb08874a17 --- /dev/null +++ b/briar-android/src/net/sf/briar/android/identity/CreateIdentityActivity.java @@ -0,0 +1,165 @@ +package net.sf.briar.android.identity; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; +import static android.widget.LinearLayout.VERTICAL; +import static java.util.logging.Level.WARNING; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP; + +import java.io.IOException; +import java.security.KeyPair; +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +import net.sf.briar.R; +import net.sf.briar.android.BriarActivity; +import net.sf.briar.android.BriarService; +import net.sf.briar.android.BriarService.BriarServiceConnection; +import net.sf.briar.api.AuthorFactory; +import net.sf.briar.api.LocalAuthor; +import net.sf.briar.api.android.DatabaseUiExecutor; +import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.crypto.CryptoExecutor; +import net.sf.briar.api.db.DatabaseComponent; +import net.sf.briar.api.db.DbException; +import android.content.Intent; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; + +import com.google.inject.Inject; + +public class CreateIdentityActivity extends BriarActivity +implements OnEditorActionListener, OnClickListener { + + private static final Logger LOG = + Logger.getLogger(CreateIdentityActivity.class.getName()); + + private final BriarServiceConnection serviceConnection = + new BriarServiceConnection(); + + @Inject @CryptoExecutor private Executor cryptoExecutor; + private EditText nicknameEntry = null; + private Button createButton = null; + private ProgressBar progress = null; + + // Fields that are accessed from background threads must be volatile + @Inject private volatile CryptoComponent crypto; + @Inject private volatile AuthorFactory authorFactory; + @Inject private volatile DatabaseComponent db; + @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; + + @Override + public void onCreate(Bundle state) { + super.onCreate(null); + LinearLayout layout = new LinearLayout(this); + layout.setLayoutParams(MATCH_MATCH); + layout.setOrientation(VERTICAL); + layout.setGravity(CENTER_HORIZONTAL); + + TextView chooseNickname = new TextView(this); + chooseNickname.setGravity(CENTER); + chooseNickname.setTextSize(18); + chooseNickname.setPadding(10, 10, 10, 10); + chooseNickname.setText(R.string.choose_nickname); + layout.addView(chooseNickname); + + nicknameEntry = new EditText(this); + nicknameEntry.setTextSize(18); + nicknameEntry.setMaxLines(1); + nicknameEntry.setPadding(10, 10, 10, 10); + nicknameEntry.setOnEditorActionListener(this); + layout.addView(nicknameEntry); + + createButton = new Button(this); + createButton.setLayoutParams(WRAP_WRAP); + createButton.setText(R.string.create_button); + createButton.setOnClickListener(this); + layout.addView(createButton); + + progress = new ProgressBar(this); + progress.setLayoutParams(WRAP_WRAP); + progress.setIndeterminate(true); + progress.setVisibility(GONE); + layout.addView(progress); + + setContentView(layout); + + // Bind to the service so we can wait for it to start + bindService(new Intent(BriarService.class.getName()), + serviceConnection, 0); + } + + @Override + public void onDestroy() { + super.onDestroy(); + unbindService(serviceConnection); + } + + public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { + validateNickname(); + return true; + } + + public void onClick(View view) { + if(!validateNickname()) return; + final String nickname = nicknameEntry.getText().toString(); + // Replace the button with a progress bar + createButton.setVisibility(GONE); + progress.setVisibility(VISIBLE); + // Create the identity in a background thread + cryptoExecutor.execute(new Runnable() { + public void run() { + KeyPair keyPair = crypto.generateSignatureKeyPair(); + final byte[] publicKey = keyPair.getPublic().getEncoded(); + final byte[] privateKey = keyPair.getPrivate().getEncoded(); + LocalAuthor a; + try { + a = authorFactory.createLocalAuthor(nickname, publicKey, + privateKey); + } catch(IOException e) { + throw new RuntimeException(e); + } + storeLocalAuthor(a); + } + }); + } + + private void storeLocalAuthor(final LocalAuthor a) { + dbUiExecutor.execute(new Runnable() { + public void run() { + try { + db.addLocalAuthor(a); + } catch(DbException e) { + if(LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } + runOnUiThread(new Runnable() { + public void run() { + finish(); + } + }); + } + }); + } + + private boolean validateNickname() { + if(nicknameEntry.getText().toString().equals("")) return false; + // Hide the soft keyboard + Object o = getSystemService(INPUT_METHOD_SERVICE); + ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0); + return true; + } +} diff --git a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java index efc7251aa6..9a5ed666e8 100644 --- a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java +++ b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java @@ -10,6 +10,7 @@ import net.sf.briar.android.AuthorNameComparator; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; +import net.sf.briar.android.LocalAuthorSpinnerAdapter; import net.sf.briar.api.AuthorId; import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.BundleEncrypter; @@ -24,7 +25,6 @@ import net.sf.briar.api.invitation.InvitationTask; import net.sf.briar.api.invitation.InvitationTaskFactory; import android.content.Intent; import android.os.Bundle; -import android.widget.ArrayAdapter; import com.google.inject.Inject; @@ -54,7 +54,7 @@ implements InvitationListener { private boolean localMatched = false, remoteMatched = false; private String contactName = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; @@ -66,8 +66,8 @@ implements InvitationListener { setView(new NetworkSetupView(this)); } else { // Restore the activity's state - byte[] id = state.getByteArray("net.sf.briar.LOCAL_AUTHOR_ID"); - if(id != null) localAuthorId = new AuthorId(id); + byte[] b = state.getByteArray("net.sf.briar.LOCAL_AUTHOR_ID"); + 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); @@ -131,7 +131,7 @@ implements InvitationListener { } } - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } @@ -162,6 +162,7 @@ implements InvitationListener { public void onDestroy() { super.onDestroy(); if(task != null) task.removeListener(this); + unbindService(serviceConnection); } void setView(AddContactView view) { @@ -171,9 +172,9 @@ implements InvitationListener { } void reset(AddContactView view) { + // Note: localAuthorId is not reset task = null; taskHandle = -1; - localAuthorId = null; networkName = null; useBluetooth = false; localInvitationCode = -1; @@ -185,12 +186,12 @@ implements InvitationListener { setView(view); } - void loadLocalAuthorList(final ArrayAdapter<LocalAuthor> adapter) { + void loadLocalAuthorList(final LocalAuthorSpinnerAdapter adapter) { dbUiExecutor.execute(new Runnable() { public void run() { try { serviceConnection.waitForStartup(); - updateLocalAuthorList(adapter, db.getLocalAuthors()); + displayLocalAuthorList(adapter, db.getLocalAuthors()); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -202,7 +203,7 @@ implements InvitationListener { }); } - private void updateLocalAuthorList(final ArrayAdapter<LocalAuthor> adapter, + private void displayLocalAuthorList(final LocalAuthorSpinnerAdapter adapter, final Collection<LocalAuthor> localAuthors) { runOnUiThread(new Runnable() { public void run() { diff --git a/briar-android/src/net/sf/briar/android/invitation/AddContactView.java b/briar-android/src/net/sf/briar/android/invitation/AddContactView.java index 221998aab1..1f84c0e620 100644 --- a/briar-android/src/net/sf/briar/android/invitation/AddContactView.java +++ b/briar-android/src/net/sf/briar/android/invitation/AddContactView.java @@ -1,7 +1,7 @@ package net.sf.briar.android.invitation; import static android.view.Gravity.CENTER_HORIZONTAL; -import net.sf.briar.android.widgets.CommonLayoutParams; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; import android.content.Context; import android.widget.LinearLayout; @@ -15,7 +15,7 @@ abstract class AddContactView extends LinearLayout { void init(AddContactActivity container) { this.container = container; - setLayoutParams(CommonLayoutParams.MATCH_MATCH); + setLayoutParams(MATCH_MATCH); setOrientation(VERTICAL); setGravity(CENTER_HORIZONTAL); populate(); diff --git a/briar-android/src/net/sf/briar/android/invitation/BluetoothWidget.java b/briar-android/src/net/sf/briar/android/invitation/BluetoothWidget.java index 6f903e552a..861e7f230c 100644 --- a/briar-android/src/net/sf/briar/android/invitation/BluetoothWidget.java +++ b/briar-android/src/net/sf/briar/android/invitation/BluetoothWidget.java @@ -3,8 +3,8 @@ 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; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.content.Intent; @@ -34,7 +34,7 @@ public class BluetoothWidget extends LinearLayout implements OnClickListener { removeAllViews(); Context ctx = getContext(); TextView status = new TextView(ctx); - status.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + status.setLayoutParams(WRAP_WRAP_1); status.setTextSize(14); status.setPadding(10, 10, 10, 10); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java b/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java index a9fe98485f..1cc1f16e2b 100644 --- a/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java +++ b/briar-android/src/net/sf/briar/android/invitation/CodeEntryWidget.java @@ -5,8 +5,8 @@ import static android.text.InputType.TYPE_CLASS_NUMBER; import static android.view.Gravity.CENTER; import static android.view.Gravity.CENTER_HORIZONTAL; import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import android.content.Context; import android.view.KeyEvent; import android.view.View; @@ -18,8 +18,8 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; -public class CodeEntryWidget extends LinearLayout implements -OnEditorActionListener, OnClickListener { +public class CodeEntryWidget extends LinearLayout +implements OnEditorActionListener, OnClickListener { private CodeEntryListener listener = null; private EditText codeEntry = null; @@ -46,7 +46,7 @@ OnEditorActionListener, OnClickListener { innerLayout.setGravity(CENTER); final Button continueButton = new Button(ctx); - continueButton.setLayoutParams(CommonLayoutParams.WRAP_WRAP); + continueButton.setLayoutParams(WRAP_WRAP); continueButton.setText(R.string.continue_button); continueButton.setEnabled(false); continueButton.setOnClickListener(this); diff --git a/briar-android/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java b/briar-android/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java index 0ee709c750..f74854b7a1 100644 --- a/briar-android/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java +++ b/briar-android/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java @@ -1,8 +1,8 @@ package net.sf.briar.android.invitation; import static android.view.Gravity.CENTER; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import android.content.Context; import android.view.View; import android.view.View.OnClickListener; @@ -44,7 +44,7 @@ implements OnClickListener { addView(interfering); Button tryAgainButton = new Button(ctx); - tryAgainButton.setLayoutParams(CommonLayoutParams.WRAP_WRAP); + tryAgainButton.setLayoutParams(WRAP_WRAP); tryAgainButton.setText(R.string.try_again_button); tryAgainButton.setOnClickListener(this); addView(tryAgainButton); diff --git a/briar-android/src/net/sf/briar/android/invitation/ConnectionFailedView.java b/briar-android/src/net/sf/briar/android/invitation/ConnectionFailedView.java index 2d2f4c8b53..5ae9e9fd1f 100644 --- a/briar-android/src/net/sf/briar/android/invitation/ConnectionFailedView.java +++ b/briar-android/src/net/sf/briar/android/invitation/ConnectionFailedView.java @@ -1,8 +1,8 @@ package net.sf.briar.android.invitation; import static android.view.Gravity.CENTER; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import android.content.Context; import android.view.View; import android.view.View.OnClickListener; @@ -54,7 +54,7 @@ implements WifiStateListener, BluetoothStateListener, OnClickListener { addView(bluetooth); tryAgainButton = new Button(ctx); - tryAgainButton.setLayoutParams(CommonLayoutParams.WRAP_WRAP); + tryAgainButton.setLayoutParams(WRAP_WRAP); tryAgainButton.setText(R.string.try_again_button); tryAgainButton.setOnClickListener(this); enabledOrDisableTryAgainButton(); diff --git a/briar-android/src/net/sf/briar/android/invitation/ContactAddedView.java b/briar-android/src/net/sf/briar/android/invitation/ContactAddedView.java index a2b297aa49..2cafa41eff 100644 --- a/briar-android/src/net/sf/briar/android/invitation/ContactAddedView.java +++ b/briar-android/src/net/sf/briar/android/invitation/ContactAddedView.java @@ -1,8 +1,8 @@ package net.sf.briar.android.invitation; import static android.view.Gravity.CENTER; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import android.content.Context; import android.view.View; import android.view.View.OnClickListener; @@ -38,15 +38,15 @@ implements OnClickListener { addView(innerLayout); TextView contactName = new TextView(ctx); + contactName.setGravity(CENTER); contactName.setTextSize(22); contactName.setPadding(10, 0, 10, 10); contactName.setText(container.getContactName()); addView(contactName); Button doneButton = new Button(ctx); - doneButton.setLayoutParams(CommonLayoutParams.WRAP_WRAP); + doneButton.setLayoutParams(WRAP_WRAP); doneButton.setText(R.string.done_button); - doneButton.setEnabled(false); doneButton.setOnClickListener(this); addView(doneButton); } diff --git a/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java b/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java index c31811889c..47ed086046 100644 --- a/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java +++ b/briar-android/src/net/sf/briar/android/invitation/NetworkSetupView.java @@ -1,10 +1,14 @@ package net.sf.briar.android.invitation; import static android.view.Gravity.CENTER; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP; import net.sf.briar.R; import net.sf.briar.android.LocalAuthorSpinnerAdapter; -import net.sf.briar.android.widgets.CommonLayoutParams; +import net.sf.briar.android.identity.CreateIdentityActivity; +import net.sf.briar.api.LocalAuthor; import android.content.Context; +import android.content.Intent; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; @@ -31,7 +35,7 @@ OnClickListener { Context ctx = getContext(); LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + innerLayout.setLayoutParams(MATCH_WRAP); innerLayout.setOrientation(HORIZONTAL); innerLayout.setGravity(CENTER); @@ -58,7 +62,7 @@ OnClickListener { addView(bluetooth); continueButton = new Button(ctx); - continueButton.setLayoutParams(CommonLayoutParams.WRAP_WRAP); + continueButton.setLayoutParams(WRAP_WRAP); continueButton.setText(R.string.continue_button); continueButton.setOnClickListener(this); enableOrDisableContinueButton(); @@ -93,7 +97,13 @@ OnClickListener { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - container.setLocalAuthorId(adapter.getItem(position).getId()); + LocalAuthor item = adapter.getItem(position); + if(item == null) { + Intent i = new Intent(container, CreateIdentityActivity.class); + container.startActivity(i); + } else { + container.setLocalAuthorId(item.getId()); + } } public void onNothingSelected(AdapterView<?> parent) { diff --git a/briar-android/src/net/sf/briar/android/invitation/WifiWidget.java b/briar-android/src/net/sf/briar/android/invitation/WifiWidget.java index 8cb63950fe..0f2820e9da 100644 --- a/briar-android/src/net/sf/briar/android/invitation/WifiWidget.java +++ b/briar-android/src/net/sf/briar/android/invitation/WifiWidget.java @@ -3,8 +3,8 @@ 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; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import android.content.Context; import android.content.Intent; import android.net.wifi.WifiInfo; @@ -37,7 +37,7 @@ public class WifiWidget extends LinearLayout implements OnClickListener { TextView status = new TextView(ctx); status.setTextSize(14); status.setPadding(10, 10, 10, 10); - status.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + status.setLayoutParams(WRAP_WRAP_1); WifiManager wifi = (WifiManager) ctx.getSystemService(WIFI_SERVICE); if(wifi == null) { wifiStateChanged(null); diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java index f75de5127f..effa869bc2 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java @@ -4,6 +4,8 @@ import static android.view.Gravity.CENTER_HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1; import java.util.Collection; import java.util.concurrent.Executor; @@ -14,9 +16,10 @@ import net.sf.briar.android.AscendingHeaderComparator; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; +import net.sf.briar.api.AuthorId; import net.sf.briar.api.ContactId; +import net.sf.briar.api.LocalAuthor; import net.sf.briar.api.android.DatabaseUiExecutor; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; @@ -52,10 +55,12 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { private ConversationAdapter adapter = null; private ListView list = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; private volatile ContactId contactId = null; + private volatile AuthorId localAuthorId = null; + private volatile String localAuthorName = null; @Override public void onCreate(Bundle state) { @@ -68,16 +73,19 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { contactName = i.getStringExtra("net.sf.briar.CONTACT_NAME"); if(contactName == null) throw new IllegalStateException(); setTitle(contactName); + byte[] b = i.getByteArrayExtra("net.sf.briar.LOCAL_AUTHOR_ID"); + if(b == null) throw new IllegalStateException(); + localAuthorId = new AuthorId(b); LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_MATCH); + layout.setLayoutParams(MATCH_MATCH); layout.setOrientation(VERTICAL); layout.setGravity(CENTER_HORIZONTAL); - adapter = new ConversationAdapter(this); + adapter = new ConversationAdapter(this, contactName); list = new ListView(this); // Give me all the width and all the unused height - list.setLayoutParams(CommonLayoutParams.MATCH_WRAP_1); + list.setLayoutParams(MATCH_WRAP_1); list.setAdapter(adapter); list.setOnItemClickListener(this); layout.addView(list); @@ -92,7 +100,7 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } @@ -108,17 +116,16 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { dbUiExecutor.execute(new Runnable() { public void run() { try { - // Wait for the service to be bound and started serviceConnection.waitForStartup(); - // Load the headers from the database long now = System.currentTimeMillis(); + LocalAuthor localAuthor = db.getLocalAuthor(localAuthorId); + localAuthorName = localAuthor.getName(); Collection<PrivateMessageHeader> headers = db.getPrivateMessageHeaders(contactId); long duration = System.currentTimeMillis() - now; if(LOG.isLoggable(INFO)) LOG.info("Load took " + duration + " ms"); - // Display the headers in the UI - displayHeaders(headers); + displayHeaders(localAuthor, headers); } catch(NoSuchContactException e) { if(LOG.isLoggable(INFO)) LOG.info("Contact removed"); finishOnUiThread(); @@ -134,10 +141,11 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { }); } - private void displayHeaders( + private void displayHeaders(final LocalAuthor localAuthor, final Collection<PrivateMessageHeader> headers) { runOnUiThread(new Runnable() { public void run() { + adapter.setLocalAuthorName(localAuthor.getName()); adapter.clear(); for(PrivateMessageHeader h : headers) adapter.add(h); adapter.sort(AscendingHeaderComparator.INSTANCE); @@ -205,6 +213,7 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { public void onClick(View view) { Intent i = new Intent(this, WritePrivateMessageActivity.class); i.putExtra("net.sf.briar.CONTACT_ID", contactId.getInt()); + i.putExtra("net.sf.briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes()); startActivity(i); } @@ -218,12 +227,11 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { Intent i = new Intent(this, ReadPrivateMessageActivity.class); i.putExtra("net.sf.briar.CONTACT_ID", contactId.getInt()); i.putExtra("net.sf.briar.CONTACT_NAME", contactName); + i.putExtra("net.sf.briar.LOCAL_AUTHOR_NAME", localAuthorName); i.putExtra("net.sf.briar.MESSAGE_ID", item.getId().getBytes()); i.putExtra("net.sf.briar.CONTENT_TYPE", item.getContentType()); i.putExtra("net.sf.briar.TIMESTAMP", item.getTimestamp()); i.putExtra("net.sf.briar.INCOMING", item.isIncoming()); - i.putExtra("net.sf.briar.FIRST", position == 0); - i.putExtra("net.sf.briar.LAST", position == adapter.getCount() - 1); startActivityForResult(i, position); } } diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java b/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java index bf105d50ca..92e98c1436 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java @@ -2,14 +2,16 @@ package net.sf.briar.android.messages; import static android.graphics.Typeface.BOLD; import static android.widget.LinearLayout.HORIZONTAL; +import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import java.util.ArrayList; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.db.PrivateMessageHeader; +import net.sf.briar.util.StringUtils; import android.content.Context; import android.content.res.Resources; import android.text.format.DateUtils; @@ -22,15 +24,26 @@ import android.widget.TextView; class ConversationAdapter extends ArrayAdapter<PrivateMessageHeader> { - ConversationAdapter(Context ctx) { + private final String contactName; + + private String localAuthorName = null; + + ConversationAdapter(Context ctx, String contactName) { super(ctx, android.R.layout.simple_expandable_list_item_1, new ArrayList<PrivateMessageHeader>()); + this.contactName = contactName; + } + + void setLocalAuthorName(String localAuthorName) { + this.localAuthorName = localAuthorName; } @Override public View getView(int position, View convertView, ViewGroup parent) { + if(localAuthorName == null) throw new IllegalStateException(); PrivateMessageHeader item = getItem(position); Context ctx = getContext(); + LinearLayout layout = new LinearLayout(ctx); layout.setOrientation(HORIZONTAL); if(!item.isRead()) { @@ -38,23 +51,40 @@ class ConversationAdapter extends ArrayAdapter<PrivateMessageHeader> { layout.setBackgroundColor(res.getColor(R.color.unread_background)); } + LinearLayout innerLayout = new LinearLayout(ctx); + // Give me all the unused width + innerLayout.setLayoutParams(WRAP_WRAP_1); + innerLayout.setOrientation(VERTICAL); + + TextView name = new TextView(ctx); + name.setTextSize(18); + name.setMaxLines(1); + name.setPadding(10, 10, 10, 10); + if(item.isIncoming()) name.setText(contactName); + else name.setText(localAuthorName); + innerLayout.addView(name); + if(item.getContentType().equals("text/plain")) { - TextView subject = new TextView(ctx); - // Give me all the unused width - subject.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); - subject.setTextSize(14); - subject.setMaxLines(2); - subject.setPadding(10, 10, 10, 10); - if(!item.isRead()) subject.setTypeface(null, BOLD); - subject.setText(item.getSubject()); - layout.addView(subject); + if(!StringUtils.isNullOrEmpty(item.getSubject())) { + TextView subject = new TextView(ctx); + subject.setTextSize(14); + subject.setMaxLines(2); + subject.setPadding(10, 0, 10, 10); + if(!item.isRead()) subject.setTypeface(null, BOLD); + subject.setText(item.getSubject()); + innerLayout.addView(subject); + } } else { + LinearLayout attachmentLayout = new LinearLayout(ctx); + attachmentLayout.setOrientation(HORIZONTAL); ImageView attachment = new ImageView(ctx); - attachment.setPadding(10, 10, 10, 10); + attachment.setPadding(10, 0, 10, 10); attachment.setImageResource(R.drawable.content_attachment); - layout.addView(attachment); - layout.addView(new HorizontalSpace(ctx)); + attachmentLayout.addView(attachment); + attachmentLayout.addView(new HorizontalSpace(ctx)); + innerLayout.addView(attachmentLayout); } + layout.addView(innerLayout); TextView date = new TextView(ctx); date.setTextSize(14); diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java index dfb5f76064..8fdc82aa33 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java @@ -4,6 +4,8 @@ import static android.view.Gravity.CENTER_HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1; import java.util.ArrayList; import java.util.Collection; @@ -16,7 +18,6 @@ import net.sf.briar.R; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; import net.sf.briar.api.Contact; import net.sf.briar.api.ContactId; @@ -52,7 +53,7 @@ implements OnClickListener, DatabaseListener { private ConversationListAdapter adapter = null; private ListView list = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; @@ -60,14 +61,14 @@ implements OnClickListener, DatabaseListener { public void onCreate(Bundle state) { super.onCreate(null); LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_MATCH); + layout.setLayoutParams(MATCH_MATCH); layout.setOrientation(VERTICAL); layout.setGravity(CENTER_HORIZONTAL); adapter = new ConversationListAdapter(this); list = new ListView(this); // Give me all the width and all the unused height - list.setLayoutParams(CommonLayoutParams.MATCH_WRAP_1); + list.setLayoutParams(MATCH_WRAP_1); list.setAdapter(adapter); list.setOnItemClickListener(adapter); layout.addView(list); @@ -82,7 +83,7 @@ implements OnClickListener, DatabaseListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java b/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java index 757884ac5b..442c4a293a 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationListAdapter.java @@ -5,11 +5,11 @@ import static android.view.Gravity.LEFT; import static android.widget.LinearLayout.HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import java.util.ArrayList; import net.sf.briar.R; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.util.StringUtils; import android.content.Context; import android.content.Intent; @@ -44,7 +44,7 @@ implements OnItemClickListener { LinearLayout innerLayout = new LinearLayout(ctx); // Give me all the unused width - innerLayout.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + innerLayout.setLayoutParams(WRAP_WRAP_1); innerLayout.setOrientation(VERTICAL); innerLayout.setGravity(LEFT); @@ -85,6 +85,8 @@ implements OnItemClickListener { Intent i = new Intent(getContext(), ConversationActivity.class); i.putExtra("net.sf.briar.CONTACT_ID", item.getContactId().getInt()); i.putExtra("net.sf.briar.CONTACT_NAME", item.getContactName()); + i.putExtra("net.sf.briar.LOCAL_AUTHOR_ID", + item.getLocalAuthorId().getBytes()); getContext().startActivity(i); } } diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java b/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java index 7dd10c32b7..f7ffc36f84 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationListItem.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.List; import net.sf.briar.android.DescendingHeaderComparator; +import net.sf.briar.api.AuthorId; import net.sf.briar.api.Contact; import net.sf.briar.api.ContactId; import net.sf.briar.api.db.PrivateMessageHeader; @@ -34,6 +35,10 @@ class ConversationListItem { return contact.getAuthor().getName(); } + AuthorId getLocalAuthorId() { + return contact.getLocalAuthorId(); + } + String getSubject() { return subject; } diff --git a/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java b/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java index 52c01ee4fb..ef48f28147 100644 --- a/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java @@ -7,6 +7,9 @@ import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1; +import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1; import java.io.UnsupportedEncodingException; import java.util.concurrent.Executor; @@ -16,7 +19,6 @@ import net.sf.briar.R; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.ContactId; @@ -59,7 +61,7 @@ implements OnClickListener { private ImageButton replyButton = null; private TextView content = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; private volatile MessageId messageId = null; @@ -69,22 +71,20 @@ implements OnClickListener { super.onCreate(null); Intent i = getIntent(); - int cid = i.getIntExtra("net.sf.briar.CONTACT_ID", -1); - if(cid == -1) throw new IllegalStateException(); - contactId = new ContactId(cid); + int id = i.getIntExtra("net.sf.briar.CONTACT_ID", -1); + if(id == -1) throw new IllegalStateException(); + contactId = new ContactId(id); String contactName = i.getStringExtra("net.sf.briar.CONTACT_NAME"); if(contactName == null) throw new IllegalStateException(); setTitle(contactName); - byte[] mid = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID"); - if(mid == null) throw new IllegalStateException(); - messageId = new MessageId(mid); + byte[] b = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID"); + if(b == null) throw new IllegalStateException(); + messageId = new MessageId(b); String contentType = i.getStringExtra("net.sf.briar.CONTENT_TYPE"); if(contentType == null) throw new IllegalStateException(); long timestamp = i.getLongExtra("net.sf.briar.TIMESTAMP", -1); if(timestamp == -1) throw new IllegalStateException(); boolean incoming = i.getBooleanExtra("net.sf.briar.INCOMING", false); - boolean first = i.getBooleanExtra("net.sf.briar.FIRST", false); - boolean last = i.getBooleanExtra("net.sf.briar.LAST", false); if(state != null && bundleEncrypter.decrypt(state)) { read = state.getBoolean("net.sf.briar.READ"); @@ -94,12 +94,12 @@ implements OnClickListener { } LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + layout.setLayoutParams(MATCH_WRAP); layout.setOrientation(VERTICAL); ScrollView scrollView = new ScrollView(this); // Give me all the width and all the unused height - scrollView.setLayoutParams(CommonLayoutParams.MATCH_WRAP_1); + scrollView.setLayoutParams(MATCH_WRAP_1); LinearLayout message = new LinearLayout(this); message.setOrientation(VERTICAL); @@ -107,13 +107,13 @@ implements OnClickListener { message.setBackgroundColor(res.getColor(R.color.content_background)); LinearLayout header = new LinearLayout(this); - header.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + header.setLayoutParams(MATCH_WRAP); header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); TextView name = new TextView(this); // Give me all the unused width - name.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); + name.setLayoutParams(WRAP_WRAP_1); name.setTextSize(18); name.setMaxLines(1); name.setPadding(10, 10, 10, 10); @@ -144,7 +144,7 @@ implements OnClickListener { layout.addView(new HorizontalBorder(this)); LinearLayout footer = new LinearLayout(this); - footer.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + footer.setLayoutParams(MATCH_WRAP); footer.setOrientation(HORIZONTAL); footer.setGravity(CENTER); @@ -160,7 +160,6 @@ implements OnClickListener { prevButton.setBackgroundResource(0); prevButton.setImageResource(R.drawable.navigation_previous_item); prevButton.setOnClickListener(this); - prevButton.setEnabled(!first); footer.addView(prevButton); footer.addView(new HorizontalSpace(this)); @@ -168,7 +167,6 @@ implements OnClickListener { nextButton.setBackgroundResource(0); nextButton.setImageResource(R.drawable.navigation_next_item); nextButton.setOnClickListener(this); - nextButton.setEnabled(!last); footer.addView(nextButton); footer.addView(new HorizontalSpace(this)); @@ -181,7 +179,7 @@ implements OnClickListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } diff --git a/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java b/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java index 312a9f5bff..c6480e0ac4 100644 --- a/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/WritePrivateMessageActivity.java @@ -5,6 +5,7 @@ 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; +import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -17,7 +18,6 @@ import net.sf.briar.R; import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; -import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalSpace; import net.sf.briar.api.AuthorId; import net.sf.briar.api.Contact; @@ -61,7 +61,7 @@ implements OnItemSelectedListener, OnClickListener { private ImageButton sendButton = null; private EditText content = null; - // Fields that are accessed from DB threads must be volatile + // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; @Inject private volatile MessageFactory messageFactory; @@ -74,17 +74,17 @@ implements OnItemSelectedListener, OnClickListener { super.onCreate(null); Intent i = getIntent(); - int cid = i.getIntExtra("net.sf.briar.CONTACT_ID", -1); - if(cid != -1) contactId = new ContactId(cid); - byte[] pid = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); - if(pid != null) parentId = new MessageId(pid); + int id = i.getIntExtra("net.sf.briar.CONTACT_ID", -1); + if(id != -1) contactId = new ContactId(id); + byte[] b = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); + if(b != null) parentId = new MessageId(b); LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + layout.setLayoutParams(MATCH_WRAP); layout.setOrientation(VERTICAL); LinearLayout header = new LinearLayout(this); - header.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + header.setLayoutParams(MATCH_WRAP); header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); @@ -106,7 +106,7 @@ implements OnItemSelectedListener, OnClickListener { layout.addView(header); header = new LinearLayout(this); - header.setLayoutParams(CommonLayoutParams.MATCH_WRAP); + header.setLayoutParams(MATCH_WRAP); header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); @@ -120,7 +120,6 @@ implements OnItemSelectedListener, OnClickListener { spinner = new Spinner(this); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); - loadContactList(); header.addView(spinner); layout.addView(header); @@ -134,17 +133,23 @@ implements OnItemSelectedListener, OnClickListener { setContentView(layout); - // Bind to the service so we can wait for the DB to be opened + // Bind to the service so we can wait for it to start bindService(new Intent(BriarService.class.getName()), serviceConnection, 0); } - private void loadContactList() { + @Override + public void onResume() { + super.onResume(); + loadContacts(); + } + + private void loadContacts() { dbUiExecutor.execute(new Runnable() { public void run() { try { serviceConnection.waitForStartup(); - displayContactList(db.getContacts()); + displayContacts(db.getContacts()); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -156,7 +161,7 @@ implements OnItemSelectedListener, OnClickListener { }); } - private void displayContactList(final Collection<Contact> contacts) { + private void displayContacts(final Collection<Contact> contacts) { runOnUiThread(new Runnable() { public void run() { int index = -1; @@ -189,11 +194,6 @@ implements OnItemSelectedListener, OnClickListener { contactId = c.getId(); } - public void onNothingSelected(AdapterView<?> parent) { - contactId = null; - sendButton.setEnabled(false); - } - private void loadLocalAuthor(final AuthorId a) { dbUiExecutor.execute(new Runnable() { public void run() { @@ -215,13 +215,18 @@ implements OnItemSelectedListener, OnClickListener { } }); } - + + public void onNothingSelected(AdapterView<?> parent) { + contactId = null; + sendButton.setEnabled(false); + } + public void onClick(View view) { if(localAuthor == null || contactId == null) throw new IllegalStateException(); try { - storeMessage(localAuthor, contactId, - content.getText().toString().getBytes("UTF-8")); + byte[] b = content.getText().toString().getBytes("UTF-8"); + storeMessage(localAuthor, contactId, b); } catch(UnsupportedEncodingException e) { throw new RuntimeException(e); } diff --git a/briar-android/src/net/sf/briar/android/widgets/HorizontalBorder.java b/briar-android/src/net/sf/briar/android/widgets/HorizontalBorder.java index c708f335ca..9b462f0fcd 100644 --- a/briar-android/src/net/sf/briar/android/widgets/HorizontalBorder.java +++ b/briar-android/src/net/sf/briar/android/widgets/HorizontalBorder.java @@ -3,16 +3,17 @@ package net.sf.briar.android.widgets; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import net.sf.briar.R; import android.content.Context; +import android.content.res.Resources; import android.view.View; import android.widget.LinearLayout.LayoutParams; public class HorizontalBorder extends View { - private static final int LINE_WIDTH = 5; - public HorizontalBorder(Context ctx) { super(ctx); - setLayoutParams(new LayoutParams(MATCH_PARENT, LINE_WIDTH)); + Resources res = ctx.getResources(); + int width = res.getInteger(R.integer.horizontal_border_width); + setLayoutParams(new LayoutParams(MATCH_PARENT, width)); setBackgroundColor(getResources().getColor(R.color.horizontal_border)); } } diff --git a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java index f261eac0aa..1ce45bc8de 100644 --- a/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java +++ b/briar-api/src/net/sf/briar/api/db/DatabaseComponent.java @@ -37,12 +37,8 @@ import net.sf.briar.api.transport.TemporarySecret; */ public interface DatabaseComponent { - /** - * Opens the database. - * @param resume true to reopen an existing database or false to create a - * new one. - */ - void open(boolean resume) throws DbException, IOException; + /** Opens the database and returns true if the database already existed. */ + boolean open() throws DbException, IOException; /** Waits for any open transactions to finish and closes the database. */ void close() throws DbException, IOException; diff --git a/briar-api/src/net/sf/briar/api/db/DatabaseConfig.java b/briar-api/src/net/sf/briar/api/db/DatabaseConfig.java index 64a9927599..15f27b645e 100644 --- a/briar-api/src/net/sf/briar/api/db/DatabaseConfig.java +++ b/briar-api/src/net/sf/briar/api/db/DatabaseConfig.java @@ -4,7 +4,9 @@ import java.io.File; public interface DatabaseConfig { - File getDataDirectory(); + boolean databaseExists(); + + File getDatabaseDirectory(); char[] getPassword(); diff --git a/briar-core/src/net/sf/briar/db/Database.java b/briar-core/src/net/sf/briar/db/Database.java index c76e925507..5aa63ee7e5 100644 --- a/briar-core/src/net/sf/briar/db/Database.java +++ b/briar-core/src/net/sf/briar/db/Database.java @@ -54,12 +54,8 @@ import net.sf.briar.api.transport.TemporarySecret; */ interface Database<T> { - /** - * Opens the database. - * @param resume true to reopen an existing database, false to create a - * new one. - */ - void open(boolean resume) throws DbException, IOException; + /** Opens the database and returns true if the database already existed. */ + boolean open() throws DbException, IOException; /** * Prevents new transactions from starting, waits for all current diff --git a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java index d65eb6f001..ea68dd7f10 100644 --- a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java +++ b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java @@ -140,11 +140,11 @@ DatabaseCleaner.Callback { this.clock = clock; } - public void open(boolean resume) throws DbException, IOException { + public boolean open() throws DbException, IOException { synchronized(openCloseLock) { if(open) throw new IllegalStateException(); open = true; - db.open(resume); + boolean reopened = db.open(); cleaner.startCleaning(this, MS_BETWEEN_SWEEPS); shutdownHandle = shutdown.addShutdownHook(new Runnable() { public void run() { @@ -162,6 +162,7 @@ DatabaseCleaner.Callback { } } }); + return reopened; } } diff --git a/briar-core/src/net/sf/briar/db/H2Database.java b/briar-core/src/net/sf/briar/db/H2Database.java index 1727ee9dd8..18fe2bdd76 100644 --- a/briar-core/src/net/sf/briar/db/H2Database.java +++ b/briar-core/src/net/sf/briar/db/H2Database.java @@ -23,23 +23,23 @@ class H2Database extends JdbcDatabase { private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT"; private static final String SECRET_TYPE = "BINARY(32)"; - private final File home; + private final File dir; private final String url; private final char[] password; private final long maxSize; @Inject H2Database(DatabaseConfig config, Clock clock) { - super(HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE, clock); - home = new File(config.getDataDirectory(), "db"); - url = "jdbc:h2:split:" + home.getPath() + super(HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE, config, clock); + dir = config.getDatabaseDirectory(); + url = "jdbc:h2:split:" + new File(dir, "db").getPath() + ";CIPHER=AES;MULTI_THREADED=1;DB_CLOSE_ON_EXIT=false"; password = config.getPassword(); maxSize = config.getMaxSize(); } - public void open(boolean resume) throws DbException, IOException { - super.open(resume, home.getParentFile(), "org.h2.Driver"); + public boolean open() throws DbException, IOException { + return super.open("org.h2.Driver"); } public void close() throws DbException { @@ -53,7 +53,6 @@ class H2Database extends JdbcDatabase { public long getFreeSpace() throws DbException { try { - File dir = home.getParentFile(); long free = FileUtils.getFreeSpace(dir); long used = getDiskSpace(dir); long quota = maxSize - used; diff --git a/briar-core/src/net/sf/briar/db/JdbcDatabase.java b/briar-core/src/net/sf/briar/db/JdbcDatabase.java index 98621e4e0d..62c792be0b 100644 --- a/briar-core/src/net/sf/briar/db/JdbcDatabase.java +++ b/briar-core/src/net/sf/briar/db/JdbcDatabase.java @@ -10,7 +10,6 @@ import static net.sf.briar.api.messaging.Rating.UNRATED; import static net.sf.briar.db.ExponentialBackoff.calculateExpiry; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; @@ -36,6 +35,7 @@ import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportId; import net.sf.briar.api.TransportProperties; import net.sf.briar.api.clock.Clock; +import net.sf.briar.api.db.DatabaseConfig; import net.sf.briar.api.db.DbClosedException; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.GroupMessageHeader; @@ -54,7 +54,6 @@ import net.sf.briar.api.messaging.TransportAck; import net.sf.briar.api.messaging.TransportUpdate; import net.sf.briar.api.transport.Endpoint; import net.sf.briar.api.transport.TemporarySecret; -import net.sf.briar.util.FileUtils; /** * A generic database implementation that can be used with any JDBC-compatible @@ -360,6 +359,7 @@ abstract class JdbcDatabase implements Database<Connection> { // Different database libraries use different names for certain types private final String hashType, binaryType, counterType, secretType; + private final DatabaseConfig config; private final Clock clock; private final LinkedList<Connection> connections = @@ -371,38 +371,39 @@ abstract class JdbcDatabase implements Database<Connection> { protected abstract Connection createConnection() throws SQLException; JdbcDatabase(String hashType, String binaryType, String counterType, - String secretType, Clock clock) { + String secretType, DatabaseConfig config, Clock clock) { this.hashType = hashType; this.binaryType = binaryType; this.counterType = counterType; this.secretType = secretType; + this.config = config; this.clock = clock; } - protected void open(boolean resume, File dir, String driverClass) - throws DbException, IOException { - if(resume) { - if(!dir.exists()) throw new FileNotFoundException(); - if(!dir.isDirectory()) throw new FileNotFoundException(); - } else { - if(dir.exists()) FileUtils.delete(dir); + protected boolean open(String driverClass) throws DbException, IOException { + boolean reopen = config.databaseExists(); + File dir = config.getDatabaseDirectory(); + if(LOG.isLoggable(INFO)) { + LOG.info("Database directory: " + dir.getPath()); + if(reopen) for(File f : dir.listFiles()) LOG.info(f.getPath()); } + if(!reopen) dir.mkdirs(); // Load the JDBC driver try { Class.forName(driverClass); } catch(ClassNotFoundException e) { throw new DbException(e); } - // Open the database + // Open the database and create the tables if necessary Connection txn = startTransaction(); try { - // If not resuming, create the tables - if(!resume) createTables(txn); + if(!reopen) createTables(txn); commitTransaction(txn); } catch(DbException e) { abortTransaction(txn); throw e; } + return reopen; } private void createTables(Connection txn) throws DbException { @@ -1246,11 +1247,12 @@ abstract class JdbcDatabase implements Database<Connection> { rs = ps.executeQuery(); List<Endpoint> endpoints = new ArrayList<Endpoint>(); while(rs.next()) { - ContactId c = new ContactId(rs.getInt(1)); - TransportId t = new TransportId(rs.getBytes(2)); + ContactId contactId = new ContactId(rs.getInt(1)); + TransportId transportId = new TransportId(rs.getBytes(2)); long epoch = rs.getLong(3); boolean alice = rs.getBoolean(4); - endpoints.add(new Endpoint(c, t, epoch, alice)); + endpoints.add(new Endpoint(contactId, transportId, epoch, + alice)); } return Collections.unmodifiableList(endpoints); } catch(SQLException e) { @@ -1367,9 +1369,12 @@ abstract class JdbcDatabase implements Database<Connection> { rs = ps.executeQuery(); List<LocalAuthor> authors = new ArrayList<LocalAuthor>(); while(rs.next()) { - AuthorId id = new AuthorId(rs.getBytes(1)); - authors.add(new LocalAuthor(id, rs.getString(2), rs.getBytes(3), - rs.getBytes(4))); + AuthorId authorId = new AuthorId(rs.getBytes(1)); + String name = rs.getString(2); + byte[] publicKey = rs.getBytes(3); + byte[] privateKey = rs.getBytes(4); + authors.add(new LocalAuthor(authorId, name, publicKey, + privateKey)); } rs.close(); ps.close(); @@ -1392,9 +1397,12 @@ abstract class JdbcDatabase implements Database<Connection> { rs = ps.executeQuery(); List<LocalGroup> groups = new ArrayList<LocalGroup>(); while(rs.next()) { - GroupId id = new GroupId(rs.getBytes(1)); - groups.add(new LocalGroup(id, rs.getString(2), rs.getBytes(3), - rs.getBytes(4))); + GroupId groupId = new GroupId(rs.getBytes(1)); + String name = rs.getString(2); + byte[] publicKey = rs.getBytes(3); + byte[] privateKey = rs.getBytes(4); + groups.add(new LocalGroup(groupId, name, publicKey, + privateKey)); } rs.close(); ps.close(); @@ -2048,8 +2056,8 @@ abstract class JdbcDatabase implements Database<Connection> { rs = ps.executeQuery(); List<TemporarySecret> secrets = new ArrayList<TemporarySecret>(); while(rs.next()) { - ContactId c = new ContactId(rs.getInt(1)); - TransportId t = new TransportId(rs.getBytes(2)); + ContactId contactId = new ContactId(rs.getInt(1)); + TransportId transportId = new TransportId(rs.getBytes(2)); long epoch = rs.getLong(3); boolean alice = rs.getBoolean(4); long period = rs.getLong(5); @@ -2057,8 +2065,8 @@ abstract class JdbcDatabase implements Database<Connection> { long outgoing = rs.getLong(7); long centre = rs.getLong(8); byte[] bitmap = rs.getBytes(9); - secrets.add(new TemporarySecret(c, t, epoch, alice, period, - secret, outgoing, centre, bitmap)); + secrets.add(new TemporarySecret(contactId, transportId, epoch, + alice, period, secret, outgoing, centre, bitmap)); } rs.close(); ps.close(); @@ -2186,10 +2194,10 @@ abstract class JdbcDatabase implements Database<Connection> { rs = ps.executeQuery(); List<Group> subs = new ArrayList<Group>(); while(rs.next()) { - GroupId id = new GroupId(rs.getBytes(1)); + GroupId groupId = new GroupId(rs.getBytes(1)); String name = rs.getString(2); byte[] publicKey = rs.getBytes(3); - subs.add(new Group(id, name, publicKey)); + subs.add(new Group(groupId, name, publicKey)); } rs.close(); ps.close(); @@ -2213,10 +2221,10 @@ abstract class JdbcDatabase implements Database<Connection> { rs = ps.executeQuery(); List<Group> subs = new ArrayList<Group>(); while(rs.next()) { - GroupId id = new GroupId(rs.getBytes(1)); + GroupId groupId = new GroupId(rs.getBytes(1)); String name = rs.getString(2); byte[] publicKey = rs.getBytes(3); - subs.add(new Group(id, name, publicKey)); + subs.add(new Group(groupId, name, publicKey)); } rs.close(); ps.close(); @@ -2286,10 +2294,10 @@ abstract class JdbcDatabase implements Database<Connection> { long version = 0; int txCount = 0; while(rs.next()) { - byte[] id = rs.getBytes(1); + GroupId groupId = new GroupId(rs.getBytes(1)); String name = rs.getString(2); byte[] key = rs.getBytes(3); - subs.add(new Group(new GroupId(id), name, key)); + subs.add(new Group(groupId, name, key)); version = rs.getLong(4); txCount = rs.getInt(5); } @@ -2483,8 +2491,8 @@ abstract class JdbcDatabase implements Database<Connection> { rs = ps.executeQuery(); Map<GroupId, Integer> counts = new HashMap<GroupId, Integer>(); while(rs.next()) { - GroupId g = new GroupId(rs.getBytes(1)); - counts.put(g, rs.getInt(2)); + GroupId groupId = new GroupId(rs.getBytes(1)); + counts.put(groupId, rs.getInt(2)); } rs.close(); ps.close(); diff --git a/briar-tests/src/net/sf/briar/TestDatabaseConfig.java b/briar-tests/src/net/sf/briar/TestDatabaseConfig.java index 614fadc863..e21336822f 100644 --- a/briar-tests/src/net/sf/briar/TestDatabaseConfig.java +++ b/briar-tests/src/net/sf/briar/TestDatabaseConfig.java @@ -14,7 +14,11 @@ public class TestDatabaseConfig implements DatabaseConfig { this.maxSize = maxSize; } - public File getDataDirectory() { + public boolean databaseExists() { + return dir.isDirectory() && dir.listFiles().length > 0; + } + + public File getDatabaseDirectory() { return dir; } diff --git a/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java b/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java index d0a7f7299d..349e48bdf8 100644 --- a/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java +++ b/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java @@ -125,8 +125,9 @@ public abstract class DatabaseComponentTest extends BriarTestCase { exactly(13).of(database).startTransaction(); will(returnValue(txn)); exactly(13).of(database).commitTransaction(txn); - // open(false) - oneOf(database).open(false); + // open() + oneOf(database).open(); + will(returnValue(false)); oneOf(cleaner).startCleaning( with(any(DatabaseCleaner.Callback.class)), with(any(long.class))); @@ -199,7 +200,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase { DatabaseComponent db = createDatabaseComponent(database, cleaner, shutdown); - db.open(false); + assertFalse(db.open()); db.addListener(listener); assertEquals(UNRATED, db.getRating(authorId)); db.setRating(authorId, GOOD); // First time - listeners called diff --git a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java index a42257acd4..87ec46004a 100644 --- a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java +++ b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java @@ -1832,7 +1832,8 @@ public class H2DatabaseTest extends BriarTestCase { private Database<Connection> open(boolean resume) throws Exception { Database<Connection> db = new H2Database(new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock()); - db.open(resume); + if(!resume) TestUtils.deleteTestDirectory(testDir); + db.open(); return db; } diff --git a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java index c996745f39..615c2e8069 100644 --- a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java @@ -102,7 +102,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase { private byte[] write() throws Exception { // Open Alice's database DatabaseComponent db = alice.getInstance(DatabaseComponent.class); - db.open(false); + assertFalse(db.open()); // Start Alice's key manager KeyManager km = alice.getInstance(KeyManager.class); km.start(); @@ -156,7 +156,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase { private void read(byte[] b) throws Exception { // Open Bob's database DatabaseComponent db = bob.getInstance(DatabaseComponent.class); - db.open(false); + assertFalse(db.open()); // Start Bob's key manager KeyManager km = bob.getInstance(KeyManager.class); km.start(); -- GitLab