Merge branch 'release/1.0-beta20'
This commit is contained in:
commit
8a668f4af2
@ -20,8 +20,8 @@ android {
|
||||
applicationId "ch.dissem.apps.${appName.toLowerCase()}"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 27
|
||||
versionCode 19
|
||||
versionName "1.0-beta19"
|
||||
versionCode 20
|
||||
versionName "1.0-beta20"
|
||||
multiDexEnabled true
|
||||
}
|
||||
compileOptions {
|
||||
|
@ -19,8 +19,8 @@ package ch.dissem.apps.abit.listener
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import ch.dissem.apps.abit.service.BitmessageService
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
import ch.dissem.apps.abit.util.Preferences
|
||||
import org.jetbrains.anko.connectivityManager
|
||||
|
||||
@ -29,7 +29,7 @@ class WifiReceiver : BroadcastReceiver() {
|
||||
if ("android.net.conn.CONNECTIVITY_CHANGE" == intent.action) {
|
||||
val bmc = Singleton.getBitmessageContext(ctx)
|
||||
if (Preferences.isFullNodeActive(ctx) && !bmc.isRunning() && !(Preferences.isWifiOnly(ctx) && ctx.connectivityManager.isActiveNetworkMetered)) {
|
||||
ctx.startService(Intent(ctx, BitmessageService::class.java))
|
||||
NetworkUtils.doStartBitmessageService(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,13 @@
|
||||
package ch.dissem.apps.abit.notification
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.support.annotation.ColorRes
|
||||
import android.support.v4.content.ContextCompat
|
||||
import ch.dissem.apps.abit.R
|
||||
import org.jetbrains.anko.notificationManager
|
||||
|
||||
/**
|
||||
@ -46,4 +51,30 @@ abstract class AbstractNotification(ctx: Context) {
|
||||
showing = false
|
||||
manager.cancel(notificationId)
|
||||
}
|
||||
|
||||
protected fun initChannel(channelId: String, @ColorRes color: Int = R.color.colorPrimary) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
ctx.notificationManager.createNotificationChannel(
|
||||
NotificationChannel(
|
||||
channelId,
|
||||
ctx.getText(R.string.app_name),
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
).apply {
|
||||
lightColor = ContextCompat.getColor(ctx, color)
|
||||
lockscreenVisibility = Notification.VISIBILITY_PRIVATE
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
internal const val ONGOING_CHANNEL_ID = "abit.ongoing"
|
||||
internal const val MESSAGE_CHANNEL_ID = "abit.message"
|
||||
internal const val ERROR_CHANNEL_ID = "abit.error"
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,14 @@ import ch.dissem.apps.abit.R
|
||||
*/
|
||||
class ErrorNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
|
||||
private val builder = NotificationCompat.Builder(ctx, "abit.error")
|
||||
private val builder = NotificationCompat.Builder(ctx, ERROR_CHANNEL_ID)
|
||||
.setContentTitle(ctx.getString(R.string.app_name))
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
|
||||
init {
|
||||
initChannel(ERROR_CHANNEL_ID, R.color.colorPrimaryDark)
|
||||
}
|
||||
|
||||
fun setWarning(@StringRes resId: Int, vararg args: Any): ErrorNotification {
|
||||
builder.setSmallIcon(R.drawable.ic_notification_warning)
|
||||
.setContentText(ctx.getString(resId, *args))
|
||||
|
@ -34,10 +34,11 @@ import kotlin.concurrent.fixedRateTimer
|
||||
*/
|
||||
class NetworkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
|
||||
private val builder = NotificationCompat.Builder(ctx, "abit.network")
|
||||
private val builder = NotificationCompat.Builder(ctx, ONGOING_CHANNEL_ID)
|
||||
private var timer: Timer? = null
|
||||
|
||||
init {
|
||||
initChannel(ONGOING_CHANNEL_ID, R.color.colorAccent)
|
||||
val showAppIntent = Intent(ctx, MainActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(ctx, 1, showAppIntent, 0)
|
||||
builder
|
||||
@ -63,11 +64,19 @@ class NetworkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
val streamNumber = Integer.parseInt(stream.name.substring("stream ".length))
|
||||
val nodeCount = stream.getProperty("nodes")!!.value as Int?
|
||||
if (nodeCount == 1) {
|
||||
info.append(ctx.getString(R.string.connection_info_1,
|
||||
streamNumber))
|
||||
info.append(
|
||||
ctx.getString(
|
||||
R.string.connection_info_1,
|
||||
streamNumber
|
||||
)
|
||||
)
|
||||
} else {
|
||||
info.append(ctx.getString(R.string.connection_info_n,
|
||||
streamNumber, nodeCount))
|
||||
info.append(
|
||||
ctx.getString(
|
||||
R.string.connection_info_n,
|
||||
streamNumber, nodeCount
|
||||
)
|
||||
)
|
||||
}
|
||||
info.append('\n')
|
||||
}
|
||||
@ -77,14 +86,18 @@ class NetworkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
val intent = Intent(ctx, BitmessageIntentService::class.java)
|
||||
if (running) {
|
||||
intent.putExtra(BitmessageIntentService.EXTRA_SHUTDOWN_NODE, true)
|
||||
builder.addAction(R.drawable.ic_notification_node_stop,
|
||||
builder.addAction(
|
||||
R.drawable.ic_notification_node_stop,
|
||||
ctx.getString(R.string.full_node_stop),
|
||||
PendingIntent.getService(ctx, 0, intent, FLAG_UPDATE_CURRENT))
|
||||
PendingIntent.getService(ctx, 0, intent, FLAG_UPDATE_CURRENT)
|
||||
)
|
||||
} else {
|
||||
intent.putExtra(BitmessageIntentService.EXTRA_STARTUP_NODE, true)
|
||||
builder.addAction(R.drawable.ic_notification_node_start,
|
||||
builder.addAction(
|
||||
R.drawable.ic_notification_node_start,
|
||||
ctx.getString(R.string.full_node_restart),
|
||||
PendingIntent.getService(ctx, 1, intent, FLAG_UPDATE_CURRENT))
|
||||
PendingIntent.getService(ctx, 1, intent, FLAG_UPDATE_CURRENT)
|
||||
)
|
||||
}
|
||||
notification = builder.build()
|
||||
return running
|
||||
@ -116,13 +129,15 @@ class NetworkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
val intent = Intent(ctx, BitmessageIntentService::class.java)
|
||||
intent.putExtra(BitmessageIntentService.EXTRA_SHUTDOWN_NODE, true)
|
||||
builder.mActions.clear()
|
||||
builder.addAction(R.drawable.ic_notification_node_stop,
|
||||
builder.addAction(
|
||||
R.drawable.ic_notification_node_stop,
|
||||
ctx.getString(R.string.full_node_stop),
|
||||
PendingIntent.getService(ctx, 0, intent, FLAG_UPDATE_CURRENT))
|
||||
PendingIntent.getService(ctx, 0, intent, FLAG_UPDATE_CURRENT)
|
||||
)
|
||||
notification = builder.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val NETWORK_NOTIFICATION_ID = 2
|
||||
const val NETWORK_NOTIFICATION_ID = 2
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,12 @@ import ch.dissem.apps.abit.util.Drawables.toBitmap
|
||||
|
||||
class NewMessageNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
|
||||
init {
|
||||
initChannel(MESSAGE_CHANNEL_ID, R.color.colorPrimary)
|
||||
}
|
||||
|
||||
fun singleNotification(plaintext: Plaintext): NewMessageNotification {
|
||||
val builder = NotificationCompat.Builder(ctx, CHANNEL_ID)
|
||||
val builder = NotificationCompat.Builder(ctx, MESSAGE_CHANNEL_ID)
|
||||
val bigText = SpannableString(plaintext.subject + "\n" + plaintext.text)
|
||||
plaintext.subject?.let { subject ->
|
||||
bigText.setSpan(SPAN_EMPHASIS, 0, subject.length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
|
||||
@ -56,22 +60,30 @@ class NewMessageNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
.setContentInfo("Info")
|
||||
|
||||
builder.setContentIntent(
|
||||
createActivityIntent(EXTRA_SHOW_MESSAGE, plaintext))
|
||||
builder.addAction(R.drawable.ic_action_reply, ctx.getString(R.string.reply),
|
||||
createActivityIntent(EXTRA_REPLY_TO_MESSAGE, plaintext))
|
||||
builder.addAction(R.drawable.ic_action_delete, ctx.getString(R.string.delete),
|
||||
createServiceIntent(ctx, EXTRA_DELETE_MESSAGE, plaintext))
|
||||
createActivityIntent(EXTRA_SHOW_MESSAGE, plaintext)
|
||||
)
|
||||
builder.addAction(
|
||||
R.drawable.ic_action_reply, ctx.getString(R.string.reply),
|
||||
createActivityIntent(EXTRA_REPLY_TO_MESSAGE, plaintext)
|
||||
)
|
||||
builder.addAction(
|
||||
R.drawable.ic_action_delete, ctx.getString(R.string.delete),
|
||||
createServiceIntent(ctx, EXTRA_DELETE_MESSAGE, plaintext)
|
||||
)
|
||||
notification = builder.build()
|
||||
return this
|
||||
}
|
||||
|
||||
private fun createActivityIntent(action: String, message: Plaintext): PendingIntent {
|
||||
val intent = Intent(ctx, MainActivity::class.java)
|
||||
intent.putExtra(action, message)
|
||||
val intent = Intent(ctx, MainActivity::class.java).putExtra(action, message)
|
||||
return PendingIntent.getActivity(ctx, action.hashCode(), intent, FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
private fun createServiceIntent(ctx: Context, action: String, message: Plaintext): PendingIntent {
|
||||
private fun createServiceIntent(
|
||||
ctx: Context,
|
||||
action: String,
|
||||
message: Plaintext
|
||||
): PendingIntent {
|
||||
val intent = Intent(ctx, BitmessageIntentService::class.java)
|
||||
intent.putExtra(action, message)
|
||||
return PendingIntent.getService(ctx, action.hashCode(), intent, FLAG_UPDATE_CURRENT)
|
||||
@ -82,8 +94,11 @@ class NewMessageNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
* * accessed it will be in a `synchronized(unacknowledged)
|
||||
* * {}` block
|
||||
*/
|
||||
fun multiNotification(unacknowledged: Collection<Plaintext>, numberOfUnacknowledgedMessages: Int): NewMessageNotification {
|
||||
val builder = NotificationCompat.Builder(ctx, CHANNEL_ID)
|
||||
fun multiNotification(
|
||||
unacknowledged: Collection<Plaintext>,
|
||||
numberOfUnacknowledgedMessages: Int
|
||||
): NewMessageNotification {
|
||||
val builder = NotificationCompat.Builder(ctx, MESSAGE_CHANNEL_ID)
|
||||
builder.setSmallIcon(R.drawable.ic_notification_new_message)
|
||||
.setContentTitle(ctx.getString(R.string.n_new_messages, numberOfUnacknowledgedMessages))
|
||||
.setContentText(ctx.getString(R.string.app_name))
|
||||
@ -93,8 +108,10 @@ class NewMessageNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
synchronized(unacknowledged) {
|
||||
for (msg in unacknowledged) {
|
||||
val sb = SpannableString(msg.from.toString() + " " + msg.subject)
|
||||
sb.setSpan(SPAN_EMPHASIS, 0, msg.from.toString().length, Spannable
|
||||
.SPAN_INCLUSIVE_EXCLUSIVE)
|
||||
sb.setSpan(
|
||||
SPAN_EMPHASIS, 0, msg.from.toString().length, Spannable
|
||||
.SPAN_INCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
inboxStyle.addLine(sb)
|
||||
}
|
||||
}
|
||||
@ -113,6 +130,5 @@ class NewMessageNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
companion object {
|
||||
private val NEW_MESSAGE_NOTIFICATION_ID = 1
|
||||
private val SPAN_EMPHASIS = StyleSpan(Typeface.BOLD)
|
||||
private val CHANNEL_ID = "abit.message"
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import kotlin.concurrent.fixedRateTimer
|
||||
*/
|
||||
class ProofOfWorkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
|
||||
private val builder = NotificationCompat.Builder(ctx, "abit.pow")
|
||||
private val builder = NotificationCompat.Builder(ctx, ONGOING_CHANNEL_ID)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setUsesChronometer(true)
|
||||
.setOngoing(true)
|
||||
@ -46,6 +46,7 @@ class ProofOfWorkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
private var timer: Timer? = null
|
||||
|
||||
init {
|
||||
initChannel(ONGOING_CHANNEL_ID, R.color.colorAccent)
|
||||
update(0)
|
||||
}
|
||||
|
||||
@ -67,10 +68,6 @@ class ProofOfWorkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ONGOING_NOTIFICATION_ID = 3
|
||||
}
|
||||
|
||||
fun start(item: ProofOfWorkService.PowItem) {
|
||||
val expectedPowTimeInMilliseconds = PowStats.getExpectedPowTimeInMilliseconds(ctx, item.targetValue)
|
||||
val delta = (expectedPowTimeInMilliseconds / 3).toInt()
|
||||
@ -101,4 +98,8 @@ class ProofOfWorkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ONGOING_NOTIFICATION_ID = 3
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import android.net.ConnectivityManager
|
||||
import android.os.Handler
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification.Companion.NETWORK_NOTIFICATION_ID
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
import ch.dissem.apps.abit.util.Preferences
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.utils.Property
|
||||
import org.jetbrains.anko.connectivityManager
|
||||
@ -39,9 +41,9 @@ class BitmessageService : Service() {
|
||||
private val bmc: BitmessageContext by lazy { Singleton.getBitmessageContext(this) }
|
||||
private lateinit var notification: NetworkNotification
|
||||
|
||||
private val connectivityReceiver: BroadcastReceiver = object: BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (bmc.isRunning() && connectivityManager.isActiveNetworkMetered){
|
||||
private val connectivityReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
if (bmc.isRunning() && !Preferences.isConnectionAllowed(this@BitmessageService)) {
|
||||
bmc.shutdown()
|
||||
}
|
||||
}
|
||||
@ -58,7 +60,10 @@ class BitmessageService : Service() {
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
registerReceiver(connectivityReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
|
||||
registerReceiver(
|
||||
connectivityReceiver,
|
||||
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
)
|
||||
notification = NetworkNotification(this)
|
||||
running = false
|
||||
}
|
||||
@ -85,13 +90,15 @@ class BitmessageService : Service() {
|
||||
notification.showShutdown()
|
||||
cleanupHandler.removeCallbacks(cleanupTask)
|
||||
bmc.cleanup()
|
||||
unregisterReceiver(connectivityReceiver)
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent) = null
|
||||
|
||||
companion object {
|
||||
@Volatile private var running = false
|
||||
@Volatile
|
||||
private var running = false
|
||||
|
||||
val isRunning: Boolean
|
||||
get() = running && Singleton.bitmessageContext?.isRunning() == true
|
||||
|
@ -20,6 +20,7 @@ import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.support.v4.content.ContextCompat
|
||||
import ch.dissem.apps.abit.notification.ProofOfWorkNotification
|
||||
import ch.dissem.apps.abit.notification.ProofOfWorkNotification.Companion.ONGOING_NOTIFICATION_ID
|
||||
import ch.dissem.apps.abit.util.PowStats
|
||||
@ -44,9 +45,14 @@ class ProofOfWorkService : Service() {
|
||||
private val notification = service.notification
|
||||
|
||||
fun process(item: PowItem) = synchronized(queue) {
|
||||
service.startService(Intent(service, ProofOfWorkService::class.java))
|
||||
service.startForeground(ONGOING_NOTIFICATION_ID,
|
||||
notification.notification)
|
||||
ContextCompat.startForegroundService(
|
||||
service,
|
||||
Intent(service, ProofOfWorkService::class.java)
|
||||
)
|
||||
service.startForeground(
|
||||
ONGOING_NOTIFICATION_ID,
|
||||
notification.notification
|
||||
)
|
||||
if (!calculating) {
|
||||
calculating = true
|
||||
service.calculateNonce(item)
|
||||
@ -58,7 +64,11 @@ class ProofOfWorkService : Service() {
|
||||
}
|
||||
|
||||
|
||||
data class PowItem(val initialHash: ByteArray, val targetValue: ByteArray, val callback: ProofOfWorkEngine.Callback) {
|
||||
data class PowItem(
|
||||
val initialHash: ByteArray,
|
||||
val targetValue: ByteArray,
|
||||
val callback: ProofOfWorkEngine.Callback
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
@ -81,7 +91,10 @@ class ProofOfWorkService : Service() {
|
||||
private fun calculateNonce(item: PowItem) {
|
||||
notification.start(item)
|
||||
val startTime = System.currentTimeMillis()
|
||||
engine.calculateNonce(item.initialHash, item.targetValue, object : ProofOfWorkEngine.Callback {
|
||||
engine.calculateNonce(
|
||||
item.initialHash,
|
||||
item.targetValue,
|
||||
object : ProofOfWorkEngine.Callback {
|
||||
override fun onNonceCalculated(initialHash: ByteArray, nonce: ByteArray) {
|
||||
notification.finished()
|
||||
val time = System.currentTimeMillis() - startTime
|
||||
|
@ -5,6 +5,7 @@ import android.app.job.JobService
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.support.annotation.RequiresApi
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
import ch.dissem.apps.abit.util.Preferences
|
||||
|
||||
/**
|
||||
@ -19,7 +20,7 @@ class StartupNodeOnWifiService : JobService() {
|
||||
override fun onStartJob(params: JobParameters?): Boolean {
|
||||
val bmc = Singleton.getBitmessageContext(this)
|
||||
if (Preferences.isFullNodeActive(this) && !bmc.isRunning()) {
|
||||
applicationContext.startService(Intent(this, BitmessageService::class.java))
|
||||
NetworkUtils.doStartBitmessageService(applicationContext)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.support.annotation.RequiresApi
|
||||
import android.support.v4.content.ContextCompat
|
||||
import ch.dissem.apps.abit.MainActivity
|
||||
import ch.dissem.apps.abit.dialog.FullNodeDialogActivity
|
||||
import ch.dissem.apps.abit.service.BitmessageService
|
||||
@ -23,7 +24,7 @@ object NetworkUtils {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
scheduleNodeStart(ctx)
|
||||
} else {
|
||||
ctx.startService(Intent(ctx, BitmessageService::class.java))
|
||||
doStartBitmessageService(ctx)
|
||||
MainActivity.updateNodeSwitch()
|
||||
}
|
||||
} else if (ask) {
|
||||
@ -37,11 +38,15 @@ object NetworkUtils {
|
||||
scheduleNodeStart(ctx)
|
||||
}
|
||||
} else {
|
||||
ctx.startService(Intent(ctx, BitmessageService::class.java))
|
||||
doStartBitmessageService(ctx)
|
||||
MainActivity.updateNodeSwitch()
|
||||
}
|
||||
}
|
||||
|
||||
fun doStartBitmessageService(ctx: Context) {
|
||||
ContextCompat.startForegroundService(ctx, Intent(ctx, BitmessageService::class.java))
|
||||
}
|
||||
|
||||
fun disableNode(ctx: Context) {
|
||||
Preferences.setFullNodeActive(ctx, false)
|
||||
ctx.stopService(Intent(ctx, BitmessageService::class.java))
|
||||
|
Loading…
Reference in New Issue
Block a user