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 1797d17..e3b469f 100644 --- a/app/src/main/java/ch/dissem/apps/abit/MessageListActivity.java +++ b/app/src/main/java/ch/dissem/apps/abit/MessageListActivity.java @@ -47,14 +47,13 @@ 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.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.DATA_FIELD_IDENTITY; 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; @@ -419,19 +418,23 @@ public class MessageListActivity extends AppCompatActivity @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); + case BitmessageService.MSG_CREATE_IDENTITY: { + Serializable data = msg.getData().getSerializable(DATA_FIELD_IDENTITY); + if (data instanceof BitmessageAddress) { + BitmessageAddress identity = (BitmessageAddress) data; + 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/repository/AndroidMessageRepository.java b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.java index 83293e7..eba1b0d 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,13 +23,11 @@ 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; @@ -47,7 +45,7 @@ import static ch.dissem.apps.abit.repository.SqlHelper.join; /** * {@link MessageRepository} implementation using the Android SQL API. */ -public class AndroidMessageRepository implements MessageRepository { +public class AndroidMessageRepository implements MessageRepository, InternalContext.ContextHolder { private static final Logger LOG = LoggerFactory.getLogger(AndroidMessageRepository.class); private static final String TABLE_NAME = "Message"; @@ -73,13 +71,16 @@ public class AndroidMessageRepository implements MessageRepository { private static final String LBL_COLUMN_ORDER = "ord"; private final SqlHelper sql; private final Context ctx; - - private final AddressRepository addressRepo; + private InternalContext bmc; public AndroidMessageRepository(SqlHelper sql, Context ctx) { this.sql = sql; this.ctx = ctx; - this.addressRepo = Singleton.getAddressRepository(ctx); + } + + @Override + public void setContext(InternalContext context) { + bmc = context; } @Override @@ -229,8 +230,8 @@ public class AndroidMessageRepository implements MessageRepository { long id = c.getLong(c.getColumnIndex(COLUMN_ID)); builder.id(id); builder.IV(new InventoryVector(iv)); - builder.from(addressRepo.getAddress(c.getString(c.getColumnIndex(COLUMN_SENDER)))); - builder.to(addressRepo.getAddress(c.getString(c.getColumnIndex(COLUMN_RECIPIENT)))); + builder.from(bmc.getAddressRepo().getAddress(c.getString(c.getColumnIndex(COLUMN_SENDER)))); + builder.to(bmc.getAddressRepo().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)))); @@ -256,12 +257,12 @@ public class AndroidMessageRepository implements MessageRepository { // save from address if necessary if (message.getId() == null) { - BitmessageAddress savedAddress = addressRepo.getAddress(message.getFrom().getAddress()); + BitmessageAddress savedAddress = bmc.getAddressRepo().getAddress(message.getFrom().getAddress()); if (savedAddress == null || savedAddress.getPrivateKey() == null) { if (savedAddress != null && savedAddress.getAlias() != null) { message.getFrom().setAlias(savedAddress.getAlias()); } - addressRepo.save(message.getFrom()); + bmc.getAddressRepo().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 469d1db..f00d3c7 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,8 @@ package ch.dissem.apps.abit.service; import android.content.Context; +import java.util.Objects; + import ch.dissem.apps.abit.MessageListActivity; import ch.dissem.apps.abit.listener.MessageListener; import ch.dissem.apps.abit.repository.AndroidAddressRepository; @@ -20,14 +22,29 @@ import ch.dissem.bitmessage.security.sc.SpongySecurity; * Provides singleton objects across the application. */ public class Singleton { - private static SqlHelper sqlHelper; - private static Security security; - private static MessageRepository messageRepository; + public static final Object lock = new Object(); + private static BitmessageContext bitmessageContext; private static MessageListener messageListener; - private static AddressRepository addressRepository; - static { - ch.dissem.bitmessage.utils.Singleton.initialize(new SpongySecurity()); + public static BitmessageContext getBitmessageContext(Context context) { + if (bitmessageContext == null) { + synchronized (lock) { + 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; } public static MessageListener getMessageListener(Context ctx) { @@ -41,40 +58,11 @@ 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; + return getBitmessageContext(ctx).messages(); } 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; + return getBitmessageContext(ctx).addresses(); } } 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 index f611630..bb15042 100644 --- a/app/src/main/java/ch/dissem/apps/abit/synchronization/BitmessageService.java +++ b/app/src/main/java/ch/dissem/apps/abit/synchronization/BitmessageService.java @@ -14,19 +14,14 @@ import android.preference.PreferenceManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.Serializable; 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; @@ -43,15 +38,19 @@ public class BitmessageService extends Service { 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_SEND_MESSAGE = 30; + public static final int MSG_SEND_BROADCAST = 31; public static final int MSG_START_NODE = 100; public static final int MSG_STOP_NODE = 101; + public static final String DATA_FIELD_IDENTITY = "identity"; public static final String DATA_FIELD_ADDRESS = "address"; + public static final String DATA_FIELD_SUBJECT = "subject"; + public static final String DATA_FIELD_MESSAGE = "message"; // 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; @@ -67,17 +66,7 @@ public class BitmessageService extends Service { 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(); + bmc = Singleton.getBitmessageContext(this); notification = new NetworkNotification(this, bmc); messenger = new Messenger(new IncomingHandler()); } @@ -108,13 +97,13 @@ public class BitmessageService extends Service { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_CREATE_IDENTITY: + 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); + bundle.putSerializable(DATA_FIELD_IDENTITY, identity); message.setData(bundle); msg.replyTo.send(message); } catch (RemoteException e) { @@ -122,11 +111,15 @@ public class BitmessageService extends Service { } } break; - case MSG_SUBSCRIBE: - BitmessageAddress address = (BitmessageAddress) msg.getData().getSerializable(DATA_FIELD_ADDRESS); - bmc.addSubscribtion(address); + } + case MSG_SUBSCRIBE: { + Serializable data = msg.getData().getSerializable(DATA_FIELD_ADDRESS); + if (data instanceof BitmessageAddress) { + bmc.addSubscribtion((BitmessageAddress) data); + } break; - case MSG_SYNC: + } + case MSG_SYNC: { LOG.info("Synchronizing Bitmessage"); // If the Bitmessage context acts as a full node, synchronization isn't necessary if (bmc.isRunning()) break; @@ -164,9 +157,32 @@ public class BitmessageService extends Service { // TODO: show error as notification } break; + } + case MSG_SEND_MESSAGE: { + Serializable identity = msg.getData().getSerializable(DATA_FIELD_IDENTITY); + Serializable address = msg.getData().getSerializable(DATA_FIELD_ADDRESS); + if (identity instanceof BitmessageAddress + && address instanceof BitmessageAddress) { + String subject = msg.getData().getString(DATA_FIELD_SUBJECT); + String message = msg.getData().getString(DATA_FIELD_MESSAGE); + bmc.send((BitmessageAddress) identity, (BitmessageAddress) address, + subject, message); + } + break; + } + case MSG_SEND_BROADCAST: { + Serializable data = msg.getData().getSerializable(DATA_FIELD_IDENTITY); + if (data instanceof BitmessageAddress) { + String subject = msg.getData().getString(DATA_FIELD_SUBJECT); + String message = msg.getData().getString(DATA_FIELD_MESSAGE); + bmc.broadcast((BitmessageAddress) data, subject, message); + } + break; + } case MSG_START_NODE: - startService(new Intent(BitmessageService.this, BitmessageService.class)); // TODO: warn user, option to restrict to WiFi + // (I'm not quite sure this can be done here, though) + startService(new Intent(BitmessageService.this, BitmessageService.class)); running = true; startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification()); bmc.startup(); diff --git a/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncAdapter.java b/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncAdapter.java index efc1333..4935e68 100644 --- a/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncAdapter.java +++ b/app/src/main/java/ch/dissem/apps/abit/synchronization/SyncAdapter.java @@ -30,9 +30,9 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter { /** * Set up the sync adapter */ - public SyncAdapter(Context context, BitmessageContext bitmessageContext) { - super(context, true); - bmc = bitmessageContext; + public SyncAdapter(Context context, boolean autoInitialize) { + super(context, autoInitialize); + bmc = Singleton.getBitmessageContext(context); } @Override 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 dca34dc..cdd0143 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 @@ -39,7 +39,7 @@ public class SyncService extends Service { */ synchronized (syncAdapterLock) { if (syncAdapter == null) { - syncAdapter = new SyncAdapter(this, null); // FIXME + syncAdapter = new SyncAdapter(this, true); } } }