Files
shadowsocks-android/src/main/scala/com/github/shadowsocks/ShadowsocksNotification.scala
T

97 lines
4.5 KiB
Scala

package com.github.shadowsocks
import java.util.Locale
import android.app.{KeyguardManager, NotificationManager, PendingIntent}
import android.content.{BroadcastReceiver, Context, Intent, IntentFilter}
import android.os.PowerManager
import android.support.v4.app.NotificationCompat
import android.support.v4.app.NotificationCompat.BigTextStyle
import android.support.v4.content.ContextCompat
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback.Stub
import com.github.shadowsocks.utils.{TrafficMonitor, Action, State, Utils}
import com.github.shadowsocks.ShadowsocksApplication.app
/**
* @author Mygod
*/
class ShadowsocksNotification(private val service: BaseService, profileName: String, visible: Boolean = false) {
private val keyGuard = service.getSystemService(Context.KEYGUARD_SERVICE).asInstanceOf[KeyguardManager]
private lazy val nm = service.getSystemService(Context.NOTIFICATION_SERVICE).asInstanceOf[NotificationManager]
private lazy val callback = new Stub {
override def stateChanged(state: Int, profileName: String, msg: String) = () // ignore
override def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
val txr = TrafficMonitor.formatTraffic(txRate)
val rxr = TrafficMonitor.formatTraffic(rxRate)
builder.setContentText(service.getString(R.string.traffic_summary).formatLocal(Locale.ENGLISH, txr, rxr))
style.bigText(service.getString(R.string.stat_summary).formatLocal(Locale.ENGLISH, txr, rxr,
TrafficMonitor.formatTraffic(txTotal), TrafficMonitor.formatTraffic(rxTotal)))
show()
}
}
private var lockReceiver: BroadcastReceiver = _
private var callbackRegistered: Boolean = _
private val builder = new NotificationCompat.Builder(service)
.setWhen(0)
.setColor(ContextCompat.getColor(service, R.color.material_accent_500))
.setTicker(service.getString(R.string.forward_success))
.setContentTitle(profileName)
.setContentIntent(PendingIntent.getActivity(service, 0, new Intent(service, classOf[Shadowsocks])
.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT), 0))
.setSmallIcon(R.drawable.ic_stat_shadowsocks)
if (!ShadowsocksTileService.running) builder.addAction(R.drawable.ic_navigation_close,
service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, new Intent(Action.CLOSE), 0))
app.profileManager.getAllProfiles match {
case Some(profiles) => if (profiles.length > 1)
builder.addAction(R.drawable.ic_action_settings, service.getString(R.string.quick_switch),
PendingIntent.getActivity(service, 0, new Intent(Action.QUICK_SWITCH), 0))
case _ =>
}
private lazy val style = new BigTextStyle(builder)
private var isVisible = true
update(if (service.getSystemService(Context.POWER_SERVICE).asInstanceOf[PowerManager].isScreenOn)
Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
lockReceiver = (context: Context, intent: Intent) => update(intent.getAction)
val screenFilter = new IntentFilter()
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
if (visible && Utils.isLollipopOrAbove) screenFilter.addAction(Intent.ACTION_USER_PRESENT)
service.registerReceiver(lockReceiver, screenFilter)
private def update(action: String, forceShow: Boolean = false) =
if (forceShow || service.getState == State.CONNECTED) action match {
case Intent.ACTION_SCREEN_OFF =>
setVisible(visible && !Utils.isLollipopOrAbove, forceShow)
unregisterCallback // unregister callback to save battery
case Intent.ACTION_SCREEN_ON =>
setVisible(visible && Utils.isLollipopOrAbove && !keyGuard.inKeyguardRestrictedInputMode, forceShow)
service.binder.registerCallback(callback)
callbackRegistered = true
case Intent.ACTION_USER_PRESENT => setVisible(true, forceShow)
}
private def unregisterCallback = if (callbackRegistered) {
service.binder.unregisterCallback(callback)
callbackRegistered = false
}
def setVisible(visible: Boolean, forceShow: Boolean = false) = if (isVisible != visible) {
isVisible = visible
builder.setPriority(if (visible) NotificationCompat.PRIORITY_LOW else NotificationCompat.PRIORITY_MIN)
show()
} else if (forceShow) show()
def show() = service.startForeground(1, builder.build)
def destroy() {
if (lockReceiver != null) {
service.unregisterReceiver(lockReceiver)
lockReceiver = null
}
unregisterCallback
service.stopForeground(true)
nm.cancel(1)
}
}