diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f635f00..577db59 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -102,6 +102,7 @@
+
extends ListFragment {
public void onItemSelected(Object plaintext) {
}
};
- protected BitmessageContext bmc;
/**
* The fragment's current callback object, which is notified of list item
* clicks.
@@ -59,13 +57,6 @@ public abstract class AbstractItemListFragment extends ListFragment {
abstract void updateList(Label label);
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- bmc = Singleton.getBitmessageContext(getActivity());
- }
-
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -89,15 +80,15 @@ public abstract class AbstractItemListFragment extends ListFragment {
}
@Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
+ public void onAttach(Context context) {
+ super.onAttach(context);
// Activities containing this fragment must implement its callbacks.
- if (!(activity instanceof ListSelectionListener)) {
+ if (!(context instanceof ListSelectionListener)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
- callbacks = (ListSelectionListener) activity;
+ callbacks = (ListSelectionListener) context;
}
@Override
diff --git a/app/src/main/java/ch/dissem/apps/abit/MessageDetailFragment.java b/app/src/main/java/ch/dissem/apps/abit/MessageDetailFragment.java
index 4652f6b..c43ae5f 100644
--- a/app/src/main/java/ch/dissem/apps/abit/MessageDetailFragment.java
+++ b/app/src/main/java/ch/dissem/apps/abit/MessageDetailFragment.java
@@ -6,12 +6,15 @@ import android.support.v4.app.Fragment;
import android.view.*;
import android.widget.ImageView;
import android.widget.TextView;
+
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.apps.abit.util.Drawables;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.valueobject.Label;
+import ch.dissem.bitmessage.ports.MessageRepository;
+
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import java.util.Iterator;
@@ -84,7 +87,7 @@ public class MessageDetailFragment extends Fragment {
}
}
if (removed) {
- Singleton.getBitmessageContext(inflater.getContext()).messages().save(item);
+ Singleton.getMessageRepository(inflater.getContext()).save(item);
}
return rootView;
}
@@ -103,7 +106,7 @@ public class MessageDetailFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
- BitmessageContext bmc = Singleton.getBitmessageContext(getActivity());
+ MessageRepository messageRepo = Singleton.getMessageRepository(getContext());
switch (menuItem.getItemId()) {
case R.id.reply:
Intent replyIntent = new Intent(getActivity().getApplicationContext(), ComposeMessageActivity.class);
@@ -113,21 +116,21 @@ public class MessageDetailFragment extends Fragment {
return true;
case R.id.delete:
if (isInTrash(item)) {
- bmc.messages().remove(item);
+ messageRepo.remove(item);
} else {
item.getLabels().clear();
- item.addLabels(bmc.messages().getLabels(Label.Type.TRASH));
- bmc.messages().save(item);
+ item.addLabels(messageRepo.getLabels(Label.Type.TRASH));
+ messageRepo.save(item);
}
getActivity().onBackPressed();
return true;
case R.id.mark_unread:
- item.addLabels(bmc.messages().getLabels(Label.Type.UNREAD));
- bmc.messages().save(item);
+ item.addLabels(messageRepo.getLabels(Label.Type.UNREAD));
+ messageRepo.save(item);
return true;
case R.id.archive:
item.getLabels().clear();
- bmc.messages().save(item);
+ messageRepo.save(item);
return true;
default:
return false;
diff --git a/app/src/main/java/ch/dissem/apps/abit/MessageListActivity.java b/app/src/main/java/ch/dissem/apps/abit/MessageListActivity.java
index f488cdf..3899a60 100644
--- a/app/src/main/java/ch/dissem/apps/abit/MessageListActivity.java
+++ b/app/src/main/java/ch/dissem/apps/abit/MessageListActivity.java
@@ -2,9 +2,17 @@ package ch.dissem.apps.abit;
import android.accounts.Account;
import android.accounts.AccountManager;
+import android.content.ComponentName;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
@@ -38,12 +46,17 @@ import ch.dissem.apps.abit.listener.ActionBarListener;
import ch.dissem.apps.abit.listener.ListSelectionListener;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.apps.abit.synchronization.Authenticator;
+import ch.dissem.apps.abit.synchronization.BitmessageService;
import ch.dissem.apps.abit.synchronization.SyncService;
-import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.valueobject.Label;
+import ch.dissem.bitmessage.ports.AddressRepository;
+import ch.dissem.bitmessage.ports.MessageRepository;
+import static ch.dissem.apps.abit.synchronization.BitmessageService.DATA_FIELD_ADDRESS;
+import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_START_NODE;
+import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_STOP_NODE;
import static ch.dissem.apps.abit.synchronization.StubProvider.AUTHORITY;
@@ -79,15 +92,36 @@ public class MessageListActivity extends AppCompatActivity
*/
private boolean twoPane;
+ private Messenger messenger = new Messenger(new IncomingHandler());
+ private Messenger service;
+ private boolean bound;
+ private ServiceConnection connection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ MessageListActivity.this.service = new Messenger(service);
+ MessageListActivity.this.bound = true;
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ service = null;
+ bound = false;
+ }
+ };
+
private AccountHeader accountHeader;
- private BitmessageContext bmc;
private Label selectedLabel;
+ private MessageRepository messageRepo;
+ private AddressRepository addressRepo;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- bmc = Singleton.getBitmessageContext(this);
- selectedLabel = bmc.messages().getLabels().get(0);
+ messageRepo = Singleton.getMessageRepository(this);
+ addressRepo = Singleton.getAddressRepository(this);
+
+ selectedLabel = messageRepo.getLabels().get(0);
setContentView(R.layout.activity_message_list);
@@ -152,7 +186,7 @@ public class MessageListActivity extends AppCompatActivity
private void createDrawer(Toolbar toolbar) {
final ArrayList profiles = new ArrayList<>();
- for (BitmessageAddress identity : bmc.addresses().getIdentities()) {
+ for (BitmessageAddress identity : addressRepo.getIdentities()) {
LOG.info("Adding identity " + identity.getAddress());
profiles.add(new ProfileDrawerItem()
.withIcon(new Identicon(identity))
@@ -183,16 +217,12 @@ public class MessageListActivity extends AppCompatActivity
@Override
public boolean onProfileChanged(View view, IProfile profile, boolean currentProfile) {
if (profile.getIdentifier() == ADD_IDENTITY) {
- BitmessageAddress identity = bmc.createIdentity(false);
- IProfile newProfile = new ProfileDrawerItem()
- .withName(identity.toString())
- .withEmail(identity.getAddress())
- .withTag(identity);
- if (accountHeader.getProfiles() != null) {
- //we know that there are 2 setting elements. set the new profile above them ;)
- accountHeader.addProfile(newProfile, accountHeader.getProfiles().size() - 2);
- } else {
- accountHeader.addProfiles(newProfile);
+ try {
+ Message message = Message.obtain(null, BitmessageService.MSG_CREATE_IDENTITY);
+ message.replyTo = messenger;
+ service.send(message);
+ } catch (RemoteException e) {
+ LOG.error(e.getMessage(), e);
}
}
// false if it should close the drawer
@@ -202,7 +232,7 @@ public class MessageListActivity extends AppCompatActivity
.build();
ArrayList drawerItems = new ArrayList<>();
- for (Label label : bmc.messages().getLabels()) {
+ for (Label label : messageRepo.getLabels()) {
PrimaryDrawerItem item = new PrimaryDrawerItem().withName(label.toString()).withTag(label);
switch (label.getType()) {
case INBOX:
@@ -254,13 +284,21 @@ public class MessageListActivity extends AppCompatActivity
@Override
public void onCheckedChanged(IDrawerItem drawerItem, CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
- startService(new Intent(MessageListActivity.this, SyncService.class));
+ try {
+ service.send(Message.obtain(null, MSG_START_NODE));
+ } catch (RemoteException e) {
+ LOG.error(e.getMessage(), e);
+ }
} else {
- stopService(new Intent(MessageListActivity.this, SyncService.class));
+ try {
+ service.send(Message.obtain(null, MSG_STOP_NODE));
+ } catch (RemoteException e) {
+ LOG.error(e.getMessage(), e);
+ }
}
}
})
- .withChecked(SyncService.isRunning())
+ .withChecked(BitmessageService.isRunning())
)
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
@Override
@@ -303,7 +341,7 @@ public class MessageListActivity extends AppCompatActivity
((MessageListFragment) getSupportFragmentManager()
.findFragmentById(R.id.item_list)).updateList(selectedLabel);
} else {
- MessageListFragment listFragment = new MessageListFragment(getApplicationContext());
+ MessageListFragment listFragment = new MessageListFragment();
changeList(listFragment);
listFragment.updateList(selectedLabel);
}
@@ -360,4 +398,41 @@ public class MessageListActivity extends AppCompatActivity
return selectedLabel;
}
+ @Override
+ protected void onStart() {
+ super.onStart();
+ bindService(new Intent(this, BitmessageService.class), connection, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onStop() {
+ if (bound) {
+ unbindService(connection);
+ bound = false;
+ }
+ super.onStop();
+ }
+
+ private class IncomingHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case BitmessageService.MSG_CREATE_IDENTITY:
+ BitmessageAddress identity = (BitmessageAddress) msg.getData().getSerializable(DATA_FIELD_ADDRESS);
+ IProfile newProfile = new ProfileDrawerItem()
+ .withName(identity.toString())
+ .withEmail(identity.getAddress())
+ .withTag(identity);
+ if (accountHeader.getProfiles() != null) {
+ //we know that there are 2 setting elements. set the new profile above them ;)
+ accountHeader.addProfile(newProfile, accountHeader.getProfiles().size() - 2);
+ } else {
+ accountHeader.addProfiles(newProfile);
+ }
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/MessageListFragment.java b/app/src/main/java/ch/dissem/apps/abit/MessageListFragment.java
index 5de7c7e..802b901 100644
--- a/app/src/main/java/ch/dissem/apps/abit/MessageListFragment.java
+++ b/app/src/main/java/ch/dissem/apps/abit/MessageListFragment.java
@@ -44,11 +44,6 @@ public class MessageListFragment extends AbstractItemListFragment {
public MessageListFragment() {
}
- @SuppressLint("ValidFragment")
- public MessageListFragment(Context ctx) {
- bmc = Singleton.getBitmessageContext(ctx);
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -73,7 +68,7 @@ public class MessageListFragment extends AbstractItemListFragment {
getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
- bmc.messages().findMessages(label)) {
+ Singleton.getMessageRepository(getContext()).findMessages(label)) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
@@ -138,7 +133,7 @@ public class MessageListFragment extends AbstractItemListFragment {
case R.id.empty_trash:
if (currentLabel.getType() != Label.Type.TRASH) return true;
- MessageRepository repo = bmc.messages();
+ MessageRepository repo = Singleton.getMessageRepository(getContext());
for (Plaintext message : repo.findMessages(currentLabel)) {
repo.remove(message);
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/OpenBitmessageLinkActivity.java b/app/src/main/java/ch/dissem/apps/abit/OpenBitmessageLinkActivity.java
index cff4772..8f87f8a 100644
--- a/app/src/main/java/ch/dissem/apps/abit/OpenBitmessageLinkActivity.java
+++ b/app/src/main/java/ch/dissem/apps/abit/OpenBitmessageLinkActivity.java
@@ -17,19 +17,52 @@
package ch.dissem.apps.abit;
import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
-import ch.dissem.apps.abit.service.Singleton;
-import ch.dissem.bitmessage.BitmessageContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.dissem.apps.abit.synchronization.BitmessageService;
import ch.dissem.bitmessage.entity.BitmessageAddress;
+import static ch.dissem.apps.abit.synchronization.BitmessageService.DATA_FIELD_ADDRESS;
+import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_ADD_CONTACT;
+import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_SUBSCRIBE;
+import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_SUBSCRIBE_AND_ADD_CONTACT;
+
public class OpenBitmessageLinkActivity extends AppCompatActivity {
+ private static final Logger LOG = LoggerFactory.getLogger(OpenBitmessageLinkActivity.class);
+
+ private Messenger service;
+ private boolean bound;
+ private ServiceConnection connection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ OpenBitmessageLinkActivity.this.service = new Messenger(service);
+ OpenBitmessageLinkActivity.this.bound = true;
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ service = null;
+ bound = false;
+ }
+ };
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -70,14 +103,29 @@ public class OpenBitmessageLinkActivity extends AppCompatActivity {
ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- BitmessageContext bmc = Singleton.getBitmessageContext(OpenBitmessageLinkActivity.this);
BitmessageAddress bmAddress = new BitmessageAddress(address);
bmAddress.setAlias(label.getText().toString());
- if (subscribe.isChecked()) {
- bmc.addSubscribtion(bmAddress);
- }
- if (importContact.isChecked()) {
- bmc.addContact(bmAddress);
+
+ final int what;
+ if (subscribe.isChecked() && importContact.isChecked())
+ what = MSG_SUBSCRIBE_AND_ADD_CONTACT;
+ else if (subscribe.isChecked())
+ what = MSG_SUBSCRIBE;
+ else if (importContact.isChecked())
+ what = MSG_ADD_CONTACT;
+ else
+ what = 0;
+
+ if (what != 0) {
+ try {
+ Message message = Message.obtain(null, what);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(DATA_FIELD_ADDRESS, bmAddress);
+ message.setData(bundle);
+ service.send(message);
+ } catch (RemoteException e) {
+ LOG.error(e.getMessage(), e);
+ }
}
setResult(Activity.RESULT_OK);
finish();
@@ -110,4 +158,19 @@ public class OpenBitmessageLinkActivity extends AppCompatActivity {
return new String[0];
}
}
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ bindService(new Intent(this, BitmessageService.class), connection, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onStop() {
+ if (bound) {
+ unbindService(connection);
+ bound = false;
+ }
+ super.onStop();
+ }
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/SubscriptionDetailFragment.java b/app/src/main/java/ch/dissem/apps/abit/SubscriptionDetailFragment.java
index fa16aec..0fa31e8 100644
--- a/app/src/main/java/ch/dissem/apps/abit/SubscriptionDetailFragment.java
+++ b/app/src/main/java/ch/dissem/apps/abit/SubscriptionDetailFragment.java
@@ -27,6 +27,7 @@ import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;
+
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.entity.BitmessageAddress;
@@ -115,7 +116,7 @@ public class SubscriptionDetailFragment extends Fragment {
@Override
public void onPause() {
- Singleton.getBitmessageContext(getActivity()).addresses().save(item);
+ Singleton.getAddressRepository(getContext()).save(item);
super.onPause();
}
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/SubscriptionListFragment.java b/app/src/main/java/ch/dissem/apps/abit/SubscriptionListFragment.java
index a3c7b00..18fa320 100644
--- a/app/src/main/java/ch/dissem/apps/abit/SubscriptionListFragment.java
+++ b/app/src/main/java/ch/dissem/apps/abit/SubscriptionListFragment.java
@@ -24,6 +24,8 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
+
+import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.valueobject.Label;
@@ -32,7 +34,7 @@ import java.util.Comparator;
import java.util.List;
/**
- * Created by chris on 06.09.15.
+ * Fragment that shows a list of all contacts, the ones we subscribed to first.
*/
public class SubscriptionListFragment extends AbstractItemListFragment {
@Override
@@ -43,7 +45,7 @@ public class SubscriptionListFragment extends AbstractItemListFragment addresses = bmc.addresses().getContacts();
+ List addresses = Singleton.getAddressRepository(getContext()).getContacts();
Collections.sort(addresses, new Comparator() {
/**
* Yields the following order:
diff --git a/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.java b/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.java
index a013602..3530c2a 100644
--- a/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.java
+++ b/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.java
@@ -25,9 +25,9 @@ public class NetworkNotification extends AbstractNotification {
private final BitmessageContext bmc;
private NotificationCompat.Builder builder;
- public NetworkNotification(Context ctx) {
- super(ctx);
- bmc = Singleton.getBitmessageContext(ctx);
+ public NetworkNotification(Context ctx, BitmessageContext bmc) {
+ super(ctx.getApplicationContext());
+ this.bmc = bmc;
builder = new NotificationCompat.Builder(ctx);
builder.setSmallIcon(R.drawable.ic_notification_full_node)
.setContentTitle(ctx.getString(R.string.bitmessage_full_node))
diff --git a/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.java b/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.java
index ee10bf1..2bb63df 100644
--- a/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.java
+++ b/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.java
@@ -21,6 +21,7 @@ import ch.dissem.bitmessage.entity.Plaintext;
import static ch.dissem.apps.abit.util.Drawables.toBitmap;
public class NewMessageNotification extends AbstractNotification {
+ public static final int NEW_MESSAGE_NOTIFICATION_ID = 1;
private static final StyleSpan SPAN_EMPHASIS = new StyleSpan(Typeface.BOLD);
public NewMessageNotification(Context ctx) {
@@ -76,6 +77,6 @@ public class NewMessageNotification extends AbstractNotification {
@Override
protected int getNotificationId() {
- return 1;
+ return NEW_MESSAGE_NOTIFICATION_ID;
}
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.java b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.java
index eba1b0d..83293e7 100644
--- a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.java
+++ b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.java
@@ -23,11 +23,13 @@ import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import ch.dissem.apps.abit.R;
+import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.InternalContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
import ch.dissem.bitmessage.entity.valueobject.Label;
+import ch.dissem.bitmessage.ports.AddressRepository;
import ch.dissem.bitmessage.ports.MessageRepository;
import ch.dissem.bitmessage.utils.Encode;
@@ -45,7 +47,7 @@ import static ch.dissem.apps.abit.repository.SqlHelper.join;
/**
* {@link MessageRepository} implementation using the Android SQL API.
*/
-public class AndroidMessageRepository implements MessageRepository, InternalContext.ContextHolder {
+public class AndroidMessageRepository implements MessageRepository {
private static final Logger LOG = LoggerFactory.getLogger(AndroidMessageRepository.class);
private static final String TABLE_NAME = "Message";
@@ -71,16 +73,13 @@ public class AndroidMessageRepository implements MessageRepository, InternalCont
private static final String LBL_COLUMN_ORDER = "ord";
private final SqlHelper sql;
private final Context ctx;
- private InternalContext bmc;
+
+ private final AddressRepository addressRepo;
public AndroidMessageRepository(SqlHelper sql, Context ctx) {
this.sql = sql;
this.ctx = ctx;
- }
-
- @Override
- public void setContext(InternalContext context) {
- bmc = context;
+ this.addressRepo = Singleton.getAddressRepository(ctx);
}
@Override
@@ -230,8 +229,8 @@ public class AndroidMessageRepository implements MessageRepository, InternalCont
long id = c.getLong(c.getColumnIndex(COLUMN_ID));
builder.id(id);
builder.IV(new InventoryVector(iv));
- builder.from(bmc.getAddressRepo().getAddress(c.getString(c.getColumnIndex(COLUMN_SENDER))));
- builder.to(bmc.getAddressRepo().getAddress(c.getString(c.getColumnIndex(COLUMN_RECIPIENT))));
+ builder.from(addressRepo.getAddress(c.getString(c.getColumnIndex(COLUMN_SENDER))));
+ builder.to(addressRepo.getAddress(c.getString(c.getColumnIndex(COLUMN_RECIPIENT))));
builder.sent(c.getLong(c.getColumnIndex(COLUMN_SENT)));
builder.received(c.getLong(c.getColumnIndex(COLUMN_RECEIVED)));
builder.status(Plaintext.Status.valueOf(c.getString(c.getColumnIndex(COLUMN_STATUS))));
@@ -257,12 +256,12 @@ public class AndroidMessageRepository implements MessageRepository, InternalCont
// save from address if necessary
if (message.getId() == null) {
- BitmessageAddress savedAddress = bmc.getAddressRepo().getAddress(message.getFrom().getAddress());
+ BitmessageAddress savedAddress = addressRepo.getAddress(message.getFrom().getAddress());
if (savedAddress == null || savedAddress.getPrivateKey() == null) {
if (savedAddress != null && savedAddress.getAlias() != null) {
message.getFrom().setAlias(savedAddress.getAlias());
}
- bmc.getAddressRepo().save(message.getFrom());
+ addressRepo.save(message.getFrom());
}
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/service/Singleton.java b/app/src/main/java/ch/dissem/apps/abit/service/Singleton.java
index 220dc36..469d1db 100644
--- a/app/src/main/java/ch/dissem/apps/abit/service/Singleton.java
+++ b/app/src/main/java/ch/dissem/apps/abit/service/Singleton.java
@@ -2,6 +2,7 @@ package ch.dissem.apps.abit.service;
import android.content.Context;
+import ch.dissem.apps.abit.MessageListActivity;
import ch.dissem.apps.abit.listener.MessageListener;
import ch.dissem.apps.abit.repository.AndroidAddressRepository;
import ch.dissem.apps.abit.repository.AndroidInventory;
@@ -9,35 +10,24 @@ import ch.dissem.apps.abit.repository.AndroidMessageRepository;
import ch.dissem.apps.abit.repository.SqlHelper;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.networking.DefaultNetworkHandler;
+import ch.dissem.bitmessage.ports.AddressRepository;
import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
+import ch.dissem.bitmessage.ports.MessageRepository;
+import ch.dissem.bitmessage.ports.Security;
import ch.dissem.bitmessage.security.sc.SpongySecurity;
/**
* Provides singleton objects across the application.
*/
public class Singleton {
- private static BitmessageContext bitmessageContext;
+ private static SqlHelper sqlHelper;
+ private static Security security;
+ private static MessageRepository messageRepository;
private static MessageListener messageListener;
+ private static AddressRepository addressRepository;
- public static BitmessageContext getBitmessageContext(Context context) {
- if (bitmessageContext == null) {
- synchronized (Singleton.class) {
- if (bitmessageContext == null) {
- final Context ctx = context.getApplicationContext();
- SqlHelper sqlHelper = new SqlHelper(ctx);
- bitmessageContext = new BitmessageContext.Builder()
- .security(new SpongySecurity())
- .nodeRegistry(new MemoryNodeRegistry())
- .inventory(new AndroidInventory(sqlHelper))
- .addressRepo(new AndroidAddressRepository(sqlHelper))
- .messageRepo(new AndroidMessageRepository(sqlHelper, ctx))
- .networkHandler(new DefaultNetworkHandler())
- .listener(getMessageListener(ctx))
- .build();
- }
- }
- }
- return bitmessageContext;
+ static {
+ ch.dissem.bitmessage.utils.Singleton.initialize(new SpongySecurity());
}
public static MessageListener getMessageListener(Context ctx) {
@@ -50,4 +40,41 @@ public class Singleton {
}
return messageListener;
}
+
+ public static SqlHelper getSqlHelper(Context ctx) {
+ if (sqlHelper == null) {
+ synchronized (Singleton.class) {
+ if (sqlHelper == null) {
+ sqlHelper = new SqlHelper(ctx.getApplicationContext());
+ }
+ }
+ }
+ return sqlHelper;
+ }
+
+ public static MessageRepository getMessageRepository(Context ctx) {
+ if (messageRepository == null) {
+ ctx = ctx.getApplicationContext();
+ getSqlHelper(ctx);
+ synchronized (Singleton.class) {
+ if (messageRepository == null) {
+ messageRepository = new AndroidMessageRepository(sqlHelper, ctx);
+ }
+ }
+ }
+ return messageRepository;
+ }
+
+ public static AddressRepository getAddressRepository(Context ctx) {
+ if (addressRepository == null) {
+ ctx = ctx.getApplicationContext();
+ getSqlHelper(ctx);
+ synchronized (Singleton.class) {
+ if (addressRepository == null) {
+ addressRepository = new AndroidAddressRepository(sqlHelper);
+ }
+ }
+ }
+ return addressRepository;
+ }
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/synchronization/BitmessageService.java b/app/src/main/java/ch/dissem/apps/abit/synchronization/BitmessageService.java
new file mode 100644
index 0000000..76176fb
--- /dev/null
+++ b/app/src/main/java/ch/dissem/apps/abit/synchronization/BitmessageService.java
@@ -0,0 +1,186 @@
+package ch.dissem.apps.abit.synchronization;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.preference.PreferenceManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import ch.dissem.apps.abit.listener.MessageListener;
+import ch.dissem.apps.abit.notification.NetworkNotification;
+import ch.dissem.apps.abit.repository.AndroidInventory;
+import ch.dissem.apps.abit.repository.SqlHelper;
+import ch.dissem.apps.abit.service.Singleton;
+import ch.dissem.bitmessage.BitmessageContext;
+import ch.dissem.bitmessage.entity.BitmessageAddress;
+import ch.dissem.bitmessage.networking.DefaultNetworkHandler;
+import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
+import ch.dissem.bitmessage.security.sc.SpongySecurity;
+
+import static ch.dissem.apps.abit.notification.NetworkNotification.ONGOING_NOTIFICATION_ID;
+
+/**
+ * Define a Service that returns an IBinder for the
+ * sync adapter class, allowing the sync adapter framework to call
+ * onPerformSync().
+ */
+public class BitmessageService extends Service {
+ public static final Logger LOG = LoggerFactory.getLogger(BitmessageService.class);
+
+ public static final int MSG_SYNC = 2;
+ public static final int MSG_CREATE_IDENTITY = 10;
+ public static final int MSG_SUBSCRIBE = 20;
+ public static final int MSG_ADD_CONTACT = 21;
+ public static final int MSG_SUBSCRIBE_AND_ADD_CONTACT = 23;
+ public static final int MSG_START_NODE = 100;
+ public static final int MSG_STOP_NODE = 101;
+
+ public static final String DATA_FIELD_ADDRESS = "address";
+
+ // Object to use as a thread-safe lock
+ private static final Object lock = new Object();
+
+ private static MessageListener messageListener = null;
+ private static NetworkNotification notification = null;
+ private static BitmessageContext bmc = null;
+
+ private static volatile boolean running = false;
+
+ private static Messenger messenger;
+
+ public static boolean isRunning() {
+ return running;
+ }
+
+ @Override
+ public void onCreate() {
+ synchronized (lock) {
+ if (bmc == null) {
+ messageListener = Singleton.getMessageListener(this);
+ SqlHelper sqlHelper = Singleton.getSqlHelper(this);
+ bmc = new BitmessageContext.Builder()
+ .security(new SpongySecurity())
+ .nodeRegistry(new MemoryNodeRegistry())
+ .inventory(new AndroidInventory(sqlHelper))
+ .addressRepo(Singleton.getAddressRepository(this))
+ .messageRepo(Singleton.getMessageRepository(this))
+ .networkHandler(new DefaultNetworkHandler())
+ .listener(messageListener)
+ .build();
+ notification = new NetworkNotification(this, bmc);
+ messenger = new Messenger(new IncomingHandler());
+ }
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ return Service.START_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ bmc.shutdown();
+ running = false;
+ }
+
+ /**
+ * Return an object that allows the system to invoke
+ * the sync adapter.
+ */
+ @Override
+ public IBinder onBind(Intent intent) {
+ return messenger.getBinder();
+ }
+
+ private class IncomingHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_CREATE_IDENTITY:
+ BitmessageAddress identity = bmc.createIdentity(false);
+ if (msg.replyTo != null) {
+ try {
+ Message message = Message.obtain(this, MSG_CREATE_IDENTITY);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(DATA_FIELD_ADDRESS, identity);
+ message.setData(bundle);
+ msg.replyTo.send(message);
+ } catch (RemoteException e) {
+ LOG.debug(e.getMessage(), e);
+ }
+ }
+ break;
+ case MSG_SUBSCRIBE:
+ BitmessageAddress address = (BitmessageAddress) msg.getData().getSerializable(DATA_FIELD_ADDRESS);
+ bmc.addSubscribtion(address);
+ break;
+ case MSG_SYNC:
+ LOG.info("Synchronizing Bitmessage");
+ // If the Bitmessage context acts as a full node, synchronization isn't necessary
+ if (bmc.isRunning()) break;
+
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(
+ BitmessageService.this);
+
+ String trustedNode = preferences.getString("trusted_node", null);
+ if (trustedNode == null) break;
+ trustedNode = trustedNode.trim();
+ if (trustedNode.isEmpty()) break;
+
+ int port;
+ if (trustedNode.matches("^(?![0-9a-fA-F]*:[0-9a-fA-F]*:).*(:[0-9]+)$")) {
+ int index = trustedNode.lastIndexOf(':');
+ String portString = trustedNode.substring(index + 1);
+ trustedNode = trustedNode.substring(0, index);
+ try {
+ port = Integer.parseInt(portString);
+ } catch (NumberFormatException e) {
+ LOG.error("Invalid port " + portString);
+ // TODO: show error as notification
+ return;
+ }
+ } else {
+ port = 8444;
+ }
+ long timeoutInSeconds = preferences.getInt("sync_timeout", 120);
+ try {
+ LOG.info("Synchronization started");
+ bmc.synchronize(InetAddress.getByName(trustedNode), port, timeoutInSeconds, true);
+ LOG.info("Synchronization finished");
+ } catch (UnknownHostException e) {
+ LOG.error("Couldn't synchronize", e);
+ // TODO: show error as notification
+ }
+ break;
+ case MSG_START_NODE:
+ startService(new Intent(BitmessageService.this, BitmessageService.class));
+ // TODO: warn user, option to restrict to WiFi
+ running = true;
+ startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification());
+ bmc.startup();
+ notification.show();
+ break;
+ case MSG_STOP_NODE:
+ bmc.shutdown();
+ running = false;
+ stopForeground(false);
+ stopService(new Intent(BitmessageService.this, BitmessageService.class));
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncService.java b/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncService.java
index f744299..dca34dc 100644
--- a/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncService.java
+++ b/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncService.java
@@ -1,16 +1,12 @@
package ch.dissem.apps.abit.synchronization;
import android.app.Service;
-import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
-import ch.dissem.apps.abit.MessageListActivity;
import ch.dissem.apps.abit.listener.MessageListener;
import ch.dissem.apps.abit.notification.NetworkNotification;
-import ch.dissem.apps.abit.repository.AndroidAddressRepository;
import ch.dissem.apps.abit.repository.AndroidInventory;
-import ch.dissem.apps.abit.repository.AndroidMessageRepository;
import ch.dissem.apps.abit.repository.SqlHelper;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.BitmessageContext;
@@ -26,20 +22,12 @@ import static ch.dissem.apps.abit.notification.NetworkNotification.ONGOING_NOTIF
* onPerformSync().
*/
public class SyncService extends Service {
- private static MessageListener messageListener = null;
- private static BitmessageContext bmc = null;
// Storage for an instance of the sync adapter
private static SyncAdapter syncAdapter = null;
// Object to use as a thread-safe lock
private static final Object syncAdapterLock = new Object();
- private static volatile boolean running = false;
-
- public static boolean isRunning() {
- return running;
- }
-
- /*
+ /**
* Instantiate the sync adapter object.
*/
@Override
@@ -50,46 +38,12 @@ public class SyncService extends Service {
* Disallow parallel syncs
*/
synchronized (syncAdapterLock) {
- final Context ctx = getApplicationContext();
- if (bmc == null) {
-// messageListener = new MessageListener(ctx);
-// SqlHelper sqlHelper = new SqlHelper(ctx);
-// bmc = new BitmessageContext.Builder()
-// .security(new SpongySecurity())
-// .nodeRegistry(new MemoryNodeRegistry())
-// .inventory(new AndroidInventory(sqlHelper))
-// .addressRepo(new AndroidAddressRepository(sqlHelper))
-// .messageRepo(new AndroidMessageRepository(sqlHelper, ctx))
-// .networkHandler(new DefaultNetworkHandler())
-// .listener(messageListener)
-// .build();
- // FIXME: this needs to change once I figured out how to get rid of those singletons
- messageListener = Singleton.getMessageListener(ctx);
- bmc = Singleton.getBitmessageContext(ctx);
- }
if (syncAdapter == null) {
- syncAdapter = new SyncAdapter(ctx, bmc);
+ syncAdapter = new SyncAdapter(this, null); // FIXME
}
}
}
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- // TODO: warn user, option to restrict to WiFi
- running = true;
- NetworkNotification networkNotification = new NetworkNotification(this);
- startForeground(ONGOING_NOTIFICATION_ID, networkNotification.getNotification());
- bmc.startup();
- networkNotification.show();
- return Service.START_STICKY;
- }
-
- @Override
- public void onDestroy() {
- bmc.shutdown();
- running = false;
- }
-
/**
* Return an object that allows the system to invoke
* the sync adapter.