Commit 940e4e30 authored by Mygod's avatar Mygod

Allow subscription service to be aborted

parent 20e4023c
...@@ -84,8 +84,8 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam ...@@ -84,8 +84,8 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam
service as Context service as Context
val closeAction = NotificationCompat.Action.Builder( val closeAction = NotificationCompat.Action.Builder(
R.drawable.ic_navigation_close, R.drawable.ic_navigation_close,
service.getString(R.string.stop), service.getText(R.string.stop),
PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE), 0)).apply { PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE).setPackage(service.packageName), 0)).apply {
setShowsUserInterface(false) setShowsUserInterface(false)
}.build() }.build()
if (Build.VERSION.SDK_INT < 24) builder.addAction(closeAction) else builder.addInvisibleAction(closeAction) if (Build.VERSION.SDK_INT < 24) builder.addAction(closeAction) else builder.addInvisibleAction(closeAction)
......
...@@ -22,8 +22,12 @@ package com.github.shadowsocks.subscription ...@@ -22,8 +22,12 @@ package com.github.shadowsocks.subscription
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
...@@ -58,16 +62,33 @@ class SubscriptionService : Service() { ...@@ -58,16 +62,33 @@ class SubscriptionService : Service() {
app.getText(R.string.service_subscription), NotificationManager.IMPORTANCE_LOW) app.getText(R.string.service_subscription), NotificationManager.IMPORTANCE_LOW)
} }
private object CancelReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
worker?.cancel()
}
}
private var counter = 0
private var receiverRegistered = false
override fun onBind(intent: Intent?): IBinder? = null override fun onBind(intent: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (worker == null) { if (worker == null) {
idle.value = false idle.value = false
if (!receiverRegistered) registerReceiver(CancelReceiver, IntentFilter(Action.ABORT))
worker = GlobalScope.launch { worker = GlobalScope.launch {
val urls = Subscription.instance.urls val urls = Subscription.instance.urls
val notification = NotificationCompat.Builder(this@SubscriptionService, NOTIFICATION_CHANNEL).apply { val notification = NotificationCompat.Builder(this@SubscriptionService, NOTIFICATION_CHANNEL).apply {
color = ContextCompat.getColor(this@SubscriptionService, R.color.material_primary_500) color = ContextCompat.getColor(this@SubscriptionService, R.color.material_primary_500)
priority = NotificationCompat.PRIORITY_LOW priority = NotificationCompat.PRIORITY_LOW
addAction(NotificationCompat.Action.Builder(
R.drawable.ic_navigation_close,
getText(R.string.stop),
PendingIntent.getBroadcast(this@SubscriptionService, 0,
Intent(Action.ABORT).setPackage(packageName), 0)).apply {
setShowsUserInterface(false)
}.build())
setCategory(NotificationCompat.CATEGORY_PROGRESS) setCategory(NotificationCompat.CATEGORY_PROGRESS)
setContentTitle(getString(R.string.service_subscription_working)) setContentTitle(getString(R.string.service_subscription_working))
setOngoing(true) setOngoing(true)
...@@ -78,12 +99,13 @@ class SubscriptionService : Service() { ...@@ -78,12 +99,13 @@ class SubscriptionService : Service() {
Core.notification.notify(NOTIFICATION_ID, notification.build()) Core.notification.notify(NOTIFICATION_ID, notification.build())
counter = 0 counter = 0
val workers = urls.asIterable().map { url -> val workers = urls.asIterable().map { url ->
async(Dispatchers.IO) { work(url, urls.size(), notification) } async(Dispatchers.IO) { fetchJson(url, urls.size(), notification) }
} }
try { try {
val localJsons = workers.awaitAll() val localJsons = workers.awaitAll()
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Core.notification.notify(NOTIFICATION_ID, notification.apply { Core.notification.notify(NOTIFICATION_ID, notification.apply {
setContentTitle(getText(R.string.service_subscription_finishing))
setProgress(0, 0, true) setProgress(0, 0, true)
}.build()) }.build())
createProfilesFromSubscription(localJsons.asSequence().filterNotNull().map { it.inputStream() }) createProfilesFromSubscription(localJsons.asSequence().filterNotNull().map { it.inputStream() })
...@@ -108,8 +130,7 @@ class SubscriptionService : Service() { ...@@ -108,8 +130,7 @@ class SubscriptionService : Service() {
return START_NOT_STICKY return START_NOT_STICKY
} }
private var counter = 0 private suspend fun fetchJson(url: URL, max: Int, notification: NotificationCompat.Builder): File? {
private suspend fun work(url: URL, max: Int, notification: NotificationCompat.Builder): File? {
val tempFile = File.createTempFile("subscription-", ".json", cacheDir) val tempFile = File.createTempFile("subscription-", ".json", cacheDir)
try { try {
(url.openConnection() as HttpURLConnection).useCancellable { (url.openConnection() as HttpURLConnection).useCancellable {
...@@ -185,6 +206,7 @@ class SubscriptionService : Service() { ...@@ -185,6 +206,7 @@ class SubscriptionService : Service() {
override fun onDestroy() { override fun onDestroy() {
worker?.cancel() worker?.cancel()
if (receiverRegistered) unregisterReceiver(CancelReceiver)
super.onDestroy() super.onDestroy()
} }
} }
...@@ -79,6 +79,7 @@ object Action { ...@@ -79,6 +79,7 @@ object Action {
const val SERVICE = "com.github.shadowsocks.SERVICE" const val SERVICE = "com.github.shadowsocks.SERVICE"
const val CLOSE = "com.github.shadowsocks.CLOSE" const val CLOSE = "com.github.shadowsocks.CLOSE"
const val RELOAD = "com.github.shadowsocks.RELOAD" const val RELOAD = "com.github.shadowsocks.RELOAD"
const val ABORT = "com.github.shadowsocks.ABORT"
const val EXTRA_PROFILE_ID = "com.github.shadowsocks.EXTRA_PROFILE_ID" const val EXTRA_PROFILE_ID = "com.github.shadowsocks.EXTRA_PROFILE_ID"
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment