Added a service based POW engine, so it shouldn't be killed by the system, at least not that easily. (WIP)
This commit is contained in:
parent
e98eefe2cc
commit
54a319638b
@ -102,7 +102,8 @@
|
|||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<service android:name=".synchronization.BitmessageService" />
|
<service android:name=".service.BitmessageService" />
|
||||||
|
<service android:name=".service.ProofOfWorkService" />
|
||||||
|
|
||||||
<!-- Synchronization -->
|
<!-- Synchronization -->
|
||||||
<provider
|
<provider
|
||||||
|
@ -40,22 +40,23 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import ch.dissem.apps.abit.listener.ActionBarListener;
|
import ch.dissem.apps.abit.listener.ActionBarListener;
|
||||||
import ch.dissem.apps.abit.listener.ListSelectionListener;
|
import ch.dissem.apps.abit.listener.ListSelectionListener;
|
||||||
|
import ch.dissem.apps.abit.service.BitmessageService;
|
||||||
import ch.dissem.apps.abit.service.Singleton;
|
import ch.dissem.apps.abit.service.Singleton;
|
||||||
import ch.dissem.apps.abit.synchronization.Authenticator;
|
import ch.dissem.apps.abit.synchronization.Authenticator;
|
||||||
import ch.dissem.apps.abit.synchronization.BitmessageService;
|
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||||
import ch.dissem.bitmessage.ports.AddressRepository;
|
import ch.dissem.bitmessage.ports.AddressRepository;
|
||||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||||
|
|
||||||
import static ch.dissem.apps.abit.synchronization.BitmessageService.DATA_FIELD_IDENTITY;
|
import static ch.dissem.apps.abit.service.BitmessageService.DATA_FIELD_IDENTITY;
|
||||||
import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_START_NODE;
|
import static ch.dissem.apps.abit.service.BitmessageService.MSG_START_NODE;
|
||||||
import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_STOP_NODE;
|
import static ch.dissem.apps.abit.service.BitmessageService.MSG_STOP_NODE;
|
||||||
import static ch.dissem.apps.abit.synchronization.StubProvider.AUTHORITY;
|
import static ch.dissem.apps.abit.synchronization.StubProvider.AUTHORITY;
|
||||||
|
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ public class MessageListActivity extends AppCompatActivity
|
|||||||
public static final String ACTION_SHOW_INBOX = "ch.dissem.abit.ShowInbox";
|
public static final String ACTION_SHOW_INBOX = "ch.dissem.abit.ShowInbox";
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MessageListActivity.class);
|
private static final Logger LOG = LoggerFactory.getLogger(MessageListActivity.class);
|
||||||
private static final long SYNC_FREQUENCY = 15;// FIXME * 60; // seconds
|
private static final long SYNC_FREQUENCY = 15 * 60; // seconds
|
||||||
private static final int ADD_IDENTITY = 1;
|
private static final int ADD_IDENTITY = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,14 +92,15 @@ public class MessageListActivity extends AppCompatActivity
|
|||||||
*/
|
*/
|
||||||
private boolean twoPane;
|
private boolean twoPane;
|
||||||
|
|
||||||
private Messenger messenger = new Messenger(new IncomingHandler());
|
private static IncomingHandler incomingHandler = new IncomingHandler();
|
||||||
private Messenger service;
|
private static Messenger messenger = new Messenger(incomingHandler);
|
||||||
private boolean bound;
|
private static Messenger service;
|
||||||
private ServiceConnection connection = new ServiceConnection() {
|
private static boolean bound;
|
||||||
|
private static ServiceConnection connection = new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
MessageListActivity.this.service = new Messenger(service);
|
MessageListActivity.service = new Messenger(service);
|
||||||
MessageListActivity.this.bound = true;
|
MessageListActivity.bound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -108,7 +110,6 @@ public class MessageListActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private AccountHeader accountHeader;
|
|
||||||
private Label selectedLabel;
|
private Label selectedLabel;
|
||||||
|
|
||||||
private MessageRepository messageRepo;
|
private MessageRepository messageRepo;
|
||||||
@ -208,7 +209,7 @@ public class MessageListActivity extends AppCompatActivity
|
|||||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||||
);
|
);
|
||||||
// Create the AccountHeader
|
// Create the AccountHeader
|
||||||
accountHeader = new AccountHeaderBuilder()
|
AccountHeader accountHeader = new AccountHeaderBuilder()
|
||||||
.withActivity(this)
|
.withActivity(this)
|
||||||
.withHeaderBackground(R.drawable.header)
|
.withHeaderBackground(R.drawable.header)
|
||||||
.withProfiles(profiles)
|
.withProfiles(profiles)
|
||||||
@ -229,6 +230,7 @@ public class MessageListActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
incomingHandler.updateAccountHeader(accountHeader);
|
||||||
|
|
||||||
ArrayList<IDrawerItem> drawerItems = new ArrayList<>();
|
ArrayList<IDrawerItem> drawerItems = new ArrayList<>();
|
||||||
for (Label label : messageRepo.getLabels()) {
|
for (Label label : messageRepo.getLabels()) {
|
||||||
@ -414,11 +416,24 @@ public class MessageListActivity extends AppCompatActivity
|
|||||||
super.onStop();
|
super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IncomingHandler extends Handler {
|
private static class IncomingHandler extends Handler {
|
||||||
|
private WeakReference<AccountHeader> accountHeaderRef;
|
||||||
|
|
||||||
|
private IncomingHandler() {
|
||||||
|
accountHeaderRef = new WeakReference<>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAccountHeader(AccountHeader accountHeader){
|
||||||
|
accountHeaderRef = new WeakReference<>(accountHeader);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case BitmessageService.MSG_CREATE_IDENTITY: {
|
case BitmessageService.MSG_CREATE_IDENTITY: {
|
||||||
|
AccountHeader accountHeader = accountHeaderRef.get();
|
||||||
|
if (accountHeader == null) break;
|
||||||
|
|
||||||
Serializable data = msg.getData().getSerializable(DATA_FIELD_IDENTITY);
|
Serializable data = msg.getData().getSerializable(DATA_FIELD_IDENTITY);
|
||||||
if (data instanceof BitmessageAddress) {
|
if (data instanceof BitmessageAddress) {
|
||||||
BitmessageAddress identity = (BitmessageAddress) data;
|
BitmessageAddress identity = (BitmessageAddress) data;
|
||||||
|
@ -37,13 +37,13 @@ import android.widget.TextView;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ch.dissem.apps.abit.synchronization.BitmessageService;
|
import ch.dissem.apps.abit.service.BitmessageService;
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||||
|
|
||||||
import static ch.dissem.apps.abit.synchronization.BitmessageService.DATA_FIELD_ADDRESS;
|
import static ch.dissem.apps.abit.service.BitmessageService.DATA_FIELD_ADDRESS;
|
||||||
import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_ADD_CONTACT;
|
import static ch.dissem.apps.abit.service.BitmessageService.MSG_ADD_CONTACT;
|
||||||
import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_SUBSCRIBE;
|
import static ch.dissem.apps.abit.service.BitmessageService.MSG_SUBSCRIBE;
|
||||||
import static ch.dissem.apps.abit.synchronization.BitmessageService.MSG_SUBSCRIBE_AND_ADD_CONTACT;
|
import static ch.dissem.apps.abit.service.BitmessageService.MSG_SUBSCRIBE_AND_ADD_CONTACT;
|
||||||
|
|
||||||
public class OpenBitmessageLinkActivity extends AppCompatActivity {
|
public class OpenBitmessageLinkActivity extends AppCompatActivity {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(OpenBitmessageLinkActivity.class);
|
private static final Logger LOG = LoggerFactory.getLogger(OpenBitmessageLinkActivity.class);
|
||||||
|
@ -14,7 +14,7 @@ public abstract class AbstractNotification {
|
|||||||
|
|
||||||
|
|
||||||
public AbstractNotification(Context ctx) {
|
public AbstractNotification(Context ctx) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx.getApplicationContext();
|
||||||
this.manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
|
this.manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,6 +23,10 @@ public abstract class AbstractNotification {
|
|||||||
*/
|
*/
|
||||||
protected abstract int getNotificationId();
|
protected abstract int getNotificationId();
|
||||||
|
|
||||||
|
public Notification getNotification() {
|
||||||
|
return notification;
|
||||||
|
}
|
||||||
|
|
||||||
public void show() {
|
public void show() {
|
||||||
manager.notify(getNotificationId(), notification);
|
manager.notify(getNotificationId(), notification);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ch.dissem.apps.abit.notification;
|
package ch.dissem.apps.abit.notification;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v7.app.NotificationCompat;
|
import android.support.v7.app.NotificationCompat;
|
||||||
|
|
||||||
import ch.dissem.apps.abit.R;
|
import ch.dissem.apps.abit.R;
|
||||||
@ -20,14 +21,14 @@ public class ErrorNotification extends AbstractNotification {
|
|||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErrorNotification setWarning(int resId, Object... args) {
|
public ErrorNotification setWarning(@StringRes int resId, Object... args) {
|
||||||
builder.setSmallIcon(R.drawable.ic_notification_warning)
|
builder.setSmallIcon(R.drawable.ic_notification_warning)
|
||||||
.setContentText(ctx.getString(resId, args));
|
.setContentText(ctx.getString(resId, args));
|
||||||
notification = builder.build();
|
notification = builder.build();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErrorNotification setError(int resId, Object... args) {
|
public ErrorNotification setError(@StringRes int resId, Object... args) {
|
||||||
builder.setSmallIcon(R.drawable.ic_notification_error)
|
builder.setSmallIcon(R.drawable.ic_notification_error)
|
||||||
.setContentText(ctx.getString(resId, args));
|
.setContentText(ctx.getString(resId, args));
|
||||||
notification = builder.build();
|
notification = builder.build();
|
||||||
|
@ -12,7 +12,6 @@ import java.util.TimerTask;
|
|||||||
|
|
||||||
import ch.dissem.apps.abit.MessageListActivity;
|
import ch.dissem.apps.abit.MessageListActivity;
|
||||||
import ch.dissem.apps.abit.R;
|
import ch.dissem.apps.abit.R;
|
||||||
import ch.dissem.apps.abit.service.Singleton;
|
|
||||||
import ch.dissem.bitmessage.BitmessageContext;
|
import ch.dissem.bitmessage.BitmessageContext;
|
||||||
import ch.dissem.bitmessage.utils.Property;
|
import ch.dissem.bitmessage.utils.Property;
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ public class NetworkNotification extends AbstractNotification {
|
|||||||
private NotificationCompat.Builder builder;
|
private NotificationCompat.Builder builder;
|
||||||
|
|
||||||
public NetworkNotification(Context ctx, BitmessageContext bmc) {
|
public NetworkNotification(Context ctx, BitmessageContext bmc) {
|
||||||
super(ctx.getApplicationContext());
|
super(ctx);
|
||||||
this.bmc = bmc;
|
this.bmc = bmc;
|
||||||
builder = new NotificationCompat.Builder(ctx);
|
builder = new NotificationCompat.Builder(ctx);
|
||||||
builder.setSmallIcon(R.drawable.ic_notification_full_node)
|
builder.setSmallIcon(R.drawable.ic_notification_full_node)
|
||||||
@ -34,6 +33,7 @@ public class NetworkNotification extends AbstractNotification {
|
|||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Notification getNotification() {
|
public Notification getNotification() {
|
||||||
update();
|
update();
|
||||||
return notification;
|
return notification;
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package ch.dissem.apps.abit.notification;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.v7.app.NotificationCompat;
|
||||||
|
|
||||||
|
import ch.dissem.apps.abit.MessageListActivity;
|
||||||
|
import ch.dissem.apps.abit.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ongoing notification while proof of work is in progress.
|
||||||
|
*/
|
||||||
|
public class ProofOfWorkNotification extends AbstractNotification {
|
||||||
|
public static final int ONGOING_NOTIFICATION_ID = 3;
|
||||||
|
|
||||||
|
public ProofOfWorkNotification(Context ctx) {
|
||||||
|
super(ctx);
|
||||||
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
|
||||||
|
|
||||||
|
Intent showMessageIntent = new Intent(ctx, MessageListActivity.class);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, showMessageIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
|
.setUsesChronometer(true)
|
||||||
|
.setSmallIcon(R.drawable.ic_notification_proof_of_work)
|
||||||
|
.setContentTitle(ctx.getString(R.string.proof_of_work_title))
|
||||||
|
.setContentText(ctx.getString(R.string.proof_of_work_text))
|
||||||
|
.setContentIntent(pendingIntent);
|
||||||
|
|
||||||
|
notification = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getNotificationId() {
|
||||||
|
return ONGOING_NOTIFICATION_ID;
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,21 @@
|
|||||||
package ch.dissem.apps.abit.synchronization;
|
package ch.dissem.apps.abit.service;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.InetAddress;
|
import java.lang.ref.WeakReference;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
import ch.dissem.apps.abit.notification.NetworkNotification;
|
import ch.dissem.apps.abit.notification.NetworkNotification;
|
||||||
import ch.dissem.apps.abit.service.Singleton;
|
|
||||||
import ch.dissem.bitmessage.BitmessageContext;
|
import ch.dissem.bitmessage.BitmessageContext;
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||||
|
|
||||||
@ -33,7 +29,6 @@ import static ch.dissem.apps.abit.notification.NetworkNotification.ONGOING_NOTIF
|
|||||||
public class BitmessageService extends Service {
|
public class BitmessageService extends Service {
|
||||||
public static final Logger LOG = LoggerFactory.getLogger(BitmessageService.class);
|
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_CREATE_IDENTITY = 10;
|
||||||
public static final int MSG_SUBSCRIBE = 20;
|
public static final int MSG_SUBSCRIBE = 20;
|
||||||
public static final int MSG_ADD_CONTACT = 21;
|
public static final int MSG_ADD_CONTACT = 21;
|
||||||
@ -68,7 +63,7 @@ public class BitmessageService extends Service {
|
|||||||
if (bmc == null) {
|
if (bmc == null) {
|
||||||
bmc = Singleton.getBitmessageContext(this);
|
bmc = Singleton.getBitmessageContext(this);
|
||||||
notification = new NetworkNotification(this, bmc);
|
notification = new NetworkNotification(this, bmc);
|
||||||
messenger = new Messenger(new IncomingHandler());
|
messenger = new Messenger(new IncomingHandler(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +88,13 @@ public class BitmessageService extends Service {
|
|||||||
return messenger.getBinder();
|
return messenger.getBinder();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IncomingHandler extends Handler {
|
private static class IncomingHandler extends Handler {
|
||||||
|
private WeakReference<BitmessageService> service;
|
||||||
|
|
||||||
|
private IncomingHandler(BitmessageService service) {
|
||||||
|
this.service = new WeakReference<>(service);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
@ -119,45 +120,6 @@ public class BitmessageService extends Service {
|
|||||||
}
|
}
|
||||||
break;
|
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_SEND_MESSAGE: {
|
case MSG_SEND_MESSAGE: {
|
||||||
Serializable identity = msg.getData().getSerializable(DATA_FIELD_IDENTITY);
|
Serializable identity = msg.getData().getSerializable(DATA_FIELD_IDENTITY);
|
||||||
Serializable address = msg.getData().getSerializable(DATA_FIELD_ADDRESS);
|
Serializable address = msg.getData().getSerializable(DATA_FIELD_ADDRESS);
|
||||||
@ -182,17 +144,17 @@ public class BitmessageService extends Service {
|
|||||||
case MSG_START_NODE:
|
case MSG_START_NODE:
|
||||||
// TODO: warn user, option to restrict to WiFi
|
// TODO: warn user, option to restrict to WiFi
|
||||||
// (I'm not quite sure this can be done here, though)
|
// (I'm not quite sure this can be done here, though)
|
||||||
startService(new Intent(BitmessageService.this, BitmessageService.class));
|
service.get().startService(new Intent(service.get(), BitmessageService.class));
|
||||||
running = true;
|
running = true;
|
||||||
startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification());
|
service.get().startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification());
|
||||||
bmc.startup();
|
bmc.startup();
|
||||||
notification.show();
|
notification.show();
|
||||||
break;
|
break;
|
||||||
case MSG_STOP_NODE:
|
case MSG_STOP_NODE:
|
||||||
bmc.shutdown();
|
bmc.shutdown();
|
||||||
running = false;
|
running = false;
|
||||||
stopForeground(false);
|
service.get().stopForeground(false);
|
||||||
stopService(new Intent(BitmessageService.this, BitmessageService.class));
|
service.get().stopSelf();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
super.handleMessage(msg);
|
super.handleMessage(msg);
|
@ -0,0 +1,88 @@
|
|||||||
|
package ch.dissem.apps.abit.service;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import ch.dissem.apps.abit.notification.ProofOfWorkNotification;
|
||||||
|
import ch.dissem.bitmessage.ports.MultiThreadedPOWEngine;
|
||||||
|
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
||||||
|
|
||||||
|
import static ch.dissem.apps.abit.notification.ProofOfWorkNotification.ONGOING_NOTIFICATION_ID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Proof of Work Service makes sure POW is done in a foreground process, so it shouldn't be
|
||||||
|
* killed by the system before the nonce is found.
|
||||||
|
*/
|
||||||
|
public class ProofOfWorkService extends Service {
|
||||||
|
public static final Logger LOG = LoggerFactory.getLogger(ProofOfWorkService.class);
|
||||||
|
|
||||||
|
// Object to use as a thread-safe lock
|
||||||
|
private static final Object lock = new Object();
|
||||||
|
private static ProofOfWorkEngine engine;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (engine == null) {
|
||||||
|
engine = new MultiThreadedPOWEngine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return new PowBinder(engine, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PowBinder extends Binder {
|
||||||
|
private final ProofOfWorkEngine engine;
|
||||||
|
|
||||||
|
private PowBinder(ProofOfWorkEngine engine, ProofOfWorkService service) {
|
||||||
|
this.engine = new EngineWrapper(engine, service);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProofOfWorkEngine getEngine() {
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class EngineWrapper implements ProofOfWorkEngine {
|
||||||
|
private final ProofOfWorkNotification notification;
|
||||||
|
private final ProofOfWorkEngine engine;
|
||||||
|
private final WeakReference<ProofOfWorkService> serviceRef;
|
||||||
|
|
||||||
|
private EngineWrapper(ProofOfWorkEngine engine, ProofOfWorkService service) {
|
||||||
|
this.engine = engine;
|
||||||
|
this.serviceRef = new WeakReference<>(service);
|
||||||
|
this.notification = new ProofOfWorkNotification(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void calculateNonce(byte[] initialHash, byte[] target, final Callback callback) {
|
||||||
|
final ProofOfWorkService service = serviceRef.get();
|
||||||
|
service.startService(new Intent(service, ProofOfWorkService.class));
|
||||||
|
service.startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification());
|
||||||
|
engine.calculateNonce(initialHash, target, new ProofOfWorkEngine.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onNonceCalculated(byte[] nonce) {
|
||||||
|
try {
|
||||||
|
callback.onNonceCalculated(nonce);
|
||||||
|
} finally {
|
||||||
|
service.stopForeground(true);
|
||||||
|
service.stopSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package ch.dissem.apps.abit.service;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
import ch.dissem.apps.abit.service.ProofOfWorkService.PowBinder;
|
||||||
|
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
||||||
|
|
||||||
|
import static android.content.Context.BIND_AUTO_CREATE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proof of Work engine that uses the Proof of Work service.
|
||||||
|
*/
|
||||||
|
public class ServicePowEngine implements ProofOfWorkEngine, ProofOfWorkEngine.Callback {
|
||||||
|
private final Semaphore semaphore = new Semaphore(1, true);
|
||||||
|
private final Context ctx;
|
||||||
|
|
||||||
|
private byte[] initialHash, targetValue;
|
||||||
|
private Callback callback;
|
||||||
|
|
||||||
|
public ServicePowEngine(Context ctx) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServiceConnection connection = new ServiceConnection() {
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
((PowBinder) service).getEngine().calculateNonce(initialHash, targetValue, ServicePowEngine.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
semaphore.release();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void calculateNonce(byte[] initialHash, byte[] targetValue, Callback callback) {
|
||||||
|
try {
|
||||||
|
semaphore.acquire();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
this.initialHash = initialHash;
|
||||||
|
this.targetValue = targetValue;
|
||||||
|
this.callback = callback;
|
||||||
|
ctx.bindService(new Intent(ctx, ProofOfWorkService.class), connection, BIND_AUTO_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNonceCalculated(byte[] bytes) {
|
||||||
|
callback.onNonceCalculated(bytes);
|
||||||
|
ctx.unbindService(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,9 +2,6 @@ package ch.dissem.apps.abit.service;
|
|||||||
|
|
||||||
import android.content.Context;
|
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.listener.MessageListener;
|
||||||
import ch.dissem.apps.abit.repository.AndroidAddressRepository;
|
import ch.dissem.apps.abit.repository.AndroidAddressRepository;
|
||||||
import ch.dissem.apps.abit.repository.AndroidInventory;
|
import ch.dissem.apps.abit.repository.AndroidInventory;
|
||||||
@ -15,7 +12,6 @@ import ch.dissem.bitmessage.networking.DefaultNetworkHandler;
|
|||||||
import ch.dissem.bitmessage.ports.AddressRepository;
|
import ch.dissem.bitmessage.ports.AddressRepository;
|
||||||
import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
|
import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
|
||||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||||
import ch.dissem.bitmessage.ports.Security;
|
|
||||||
import ch.dissem.bitmessage.security.sc.SpongySecurity;
|
import ch.dissem.bitmessage.security.sc.SpongySecurity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,6 +29,7 @@ public class Singleton {
|
|||||||
final Context ctx = context.getApplicationContext();
|
final Context ctx = context.getApplicationContext();
|
||||||
SqlHelper sqlHelper = new SqlHelper(ctx);
|
SqlHelper sqlHelper = new SqlHelper(ctx);
|
||||||
bitmessageContext = new BitmessageContext.Builder()
|
bitmessageContext = new BitmessageContext.Builder()
|
||||||
|
.proofOfWorkEngine(new ServicePowEngine(ctx))
|
||||||
.security(new SpongySecurity())
|
.security(new SpongySecurity())
|
||||||
.nodeRegistry(new MemoryNodeRegistry())
|
.nodeRegistry(new MemoryNodeRegistry())
|
||||||
.inventory(new AndroidInventory(sqlHelper))
|
.inventory(new AndroidInventory(sqlHelper))
|
||||||
|
@ -15,6 +15,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import ch.dissem.apps.abit.R;
|
||||||
|
import ch.dissem.apps.abit.notification.ErrorNotification;
|
||||||
import ch.dissem.apps.abit.service.Singleton;
|
import ch.dissem.apps.abit.service.Singleton;
|
||||||
import ch.dissem.bitmessage.BitmessageContext;
|
import ch.dissem.bitmessage.BitmessageContext;
|
||||||
|
|
||||||
@ -59,8 +61,9 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
try {
|
try {
|
||||||
port = Integer.parseInt(portString);
|
port = Integer.parseInt(portString);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
LOG.error("Invalid port " + portString);
|
new ErrorNotification(getContext())
|
||||||
// TODO: show error as notification
|
.setError(R.string.error_invalid_sync_port, portString)
|
||||||
|
.show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -72,8 +75,11 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
bmc.synchronize(InetAddress.getByName(trustedNode), port, timeoutInSeconds, true);
|
bmc.synchronize(InetAddress.getByName(trustedNode), port, timeoutInSeconds, true);
|
||||||
LOG.info("Synchronization finished");
|
LOG.info("Synchronization finished");
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
LOG.error("Couldn't synchronize", e);
|
new ErrorNotification(getContext())
|
||||||
// TODO: show error as notification
|
.setError(R.string.error_invalid_sync_host)
|
||||||
|
.show();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
LOG.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,4 +42,8 @@
|
|||||||
<string name="connection_info_n">Stream %1$d: %2$d Verbindungen</string>
|
<string name="connection_info_n">Stream %1$d: %2$d Verbindungen</string>
|
||||||
<string name="connection_info_disconnected">Getrennt</string>
|
<string name="connection_info_disconnected">Getrennt</string>
|
||||||
<string name="connection_info_pending">Verbindung wird aufgebaut…</string>
|
<string name="connection_info_pending">Verbindung wird aufgebaut…</string>
|
||||||
|
<string name="proof_of_work_text">Warnung: dies könnte das Gerät erwärmen bis die Batterie leer ist.</string>
|
||||||
|
<string name="proof_of_work_title">Proof of Work</string>
|
||||||
|
<string name="error_invalid_sync_host">Synchronisation fehlgeschlagen: der vertrauenswürdige Knoten konnte nicht erreicht werden.</string>
|
||||||
|
<string name="error_invalid_sync_port">Ungültiger Port in den Synchronisationseinstellungen: %s</string>
|
||||||
</resources>
|
</resources>
|
@ -42,4 +42,8 @@
|
|||||||
<string name="send">Send</string>
|
<string name="send">Send</string>
|
||||||
<string name="connection_info_disconnected">Disconnected</string>
|
<string name="connection_info_disconnected">Disconnected</string>
|
||||||
<string name="connection_info_pending">Connecting…</string>
|
<string name="connection_info_pending">Connecting…</string>
|
||||||
|
<string name="proof_of_work_title">Proof of Work</string>
|
||||||
|
<string name="proof_of_work_text">Warning: This might heat your device until the battery\'s dead.</string>
|
||||||
|
<string name="error_invalid_sync_port">Invalid port in synchronization settings: %s</string>
|
||||||
|
<string name="error_invalid_sync_host">Synchronization failed: Trusted node could not be reached.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user