mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Create an identity at startup if the database doesn't exist.
This commit is contained in:
@@ -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" >
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-16
|
||||
target=android-17
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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 showSpinner() {
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(MATCH_MATCH);
|
||||
layout.setGravity(CENTER);
|
||||
ProgressBar progress = new ProgressBar(this);
|
||||
progress.setIndeterminate(true);
|
||||
layout.addView(progress);
|
||||
setContentView(layout);
|
||||
}
|
||||
|
||||
private void quit() {
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(CommonLayoutParams.MATCH_MATCH);
|
||||
layout.setGravity(CENTER);
|
||||
ProgressBar spinner = new ProgressBar(this);
|
||||
spinner.setIndeterminate(true);
|
||||
layout.addView(spinner);
|
||||
setContentView(layout);
|
||||
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
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
finish();
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Exiting");
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
}
|
||||
// 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() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
138
briar-android/src/net/sf/briar/android/SetupActivity.java
Normal file
138
briar-android/src/net/sf/briar/android/SetupActivity.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -4,7 +4,9 @@ import java.io.File;
|
||||
|
||||
public interface DatabaseConfig {
|
||||
|
||||
File getDataDirectory();
|
||||
boolean databaseExists();
|
||||
|
||||
File getDatabaseDirectory();
|
||||
|
||||
char[] getPassword();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user