fixed user stream position key - now notifications can work properly

This commit is contained in:
Mariotaku Lee 2017-03-12 22:28:57 +08:00
parent 112e8fdb7d
commit 62a52c78ed
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
8 changed files with 115 additions and 28 deletions

View File

@ -69,6 +69,8 @@ val floatingDetailedContentsKey = KBooleanKey("floating_detailed_contents", true
val localTrendsWoeIdKey = KIntKey(KEY_LOCAL_TRENDS_WOEID, 1) val localTrendsWoeIdKey = KIntKey(KEY_LOCAL_TRENDS_WOEID, 1)
val phishingLinksWaringKey = KBooleanKey(KEY_PHISHING_LINK_WARNING, true) val phishingLinksWaringKey = KBooleanKey(KEY_PHISHING_LINK_WARNING, true)
val multiColumnWidthKey = KStringKey("multi_column_tab_width", "normal") val multiColumnWidthKey = KStringKey("multi_column_tab_width", "normal")
val streamingNonMeteredNetworkKey = KBooleanKey("streaming_non_metered_network", true)
val streamingPowerSavingKey = KBooleanKey("streaming_power_saving", true)
object themeBackgroundAlphaKey : KSimpleKey<Int>(KEY_THEME_BACKGROUND_ALPHA, 0xFF) { object themeBackgroundAlphaKey : KSimpleKey<Int>(KEY_THEME_BACKGROUND_ALPHA, 0xFF) {
override fun read(preferences: SharedPreferences): Int { override fun read(preferences: SharedPreferences): Int {

View File

@ -16,7 +16,7 @@ import org.mariotaku.twidere.activity.SignInActivity
/** /**
* Created by mariotaku on 2016/12/2. * Created by mariotaku on 2016/12/2.
*/ */
class AccountAuthenticatorService : Service() { class AccountAuthenticatorService : BaseService() {
private lateinit var authenticator: TwidereAccountAuthenticator private lateinit var authenticator: TwidereAccountAuthenticator

View File

@ -10,7 +10,7 @@ import android.os.IBinder
/** /**
* Created by mariotaku on 2016/12/3. * Created by mariotaku on 2016/12/3.
*/ */
class AccountSyncService : Service() { class AccountSyncService : BaseService() {
override fun onCreate() { override fun onCreate() {
/* /*

View File

@ -0,0 +1,53 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.service
import android.app.Service
import android.net.ConnectivityManager
import com.twitter.Extractor
import com.twitter.Validator
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import javax.inject.Inject
abstract class BaseService : Service() {
@Inject
lateinit var preferences: SharedPreferencesWrapper
@Inject
lateinit var twitterWrapper: AsyncTwitterWrapper
@Inject
lateinit var notificationManager: NotificationManagerWrapper
@Inject
lateinit var validator: Validator
@Inject
lateinit var extractor: Extractor
@Inject
lateinit var userColorNameManager: UserColorNameManager
@Inject
lateinit var taskServiceRunner: TaskServiceRunner
@Inject
lateinit var connectivityManager: ConnectivityManager
override fun onCreate() {
super.onCreate()
GeneralComponentHelper.build(this).inject(this)
}
}

View File

@ -19,26 +19,18 @@
package org.mariotaku.twidere.service package org.mariotaku.twidere.service
import android.app.Service
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.IBinder import android.os.IBinder
import org.mariotaku.kpreferences.KPreferences import org.mariotaku.kpreferences.get
import org.mariotaku.twidere.annotation.AutoRefreshType import org.mariotaku.twidere.annotation.AutoRefreshType
import org.mariotaku.twidere.constant.autoRefreshCompatibilityModeKey import org.mariotaku.twidere.constant.autoRefreshCompatibilityModeKey
import org.mariotaku.twidere.util.TaskServiceRunner
import org.mariotaku.twidere.util.TaskServiceRunner.Companion.ACTION_REFRESH_DIRECT_MESSAGES import org.mariotaku.twidere.util.TaskServiceRunner.Companion.ACTION_REFRESH_DIRECT_MESSAGES
import org.mariotaku.twidere.util.TaskServiceRunner.Companion.ACTION_REFRESH_HOME_TIMELINE import org.mariotaku.twidere.util.TaskServiceRunner.Companion.ACTION_REFRESH_HOME_TIMELINE
import org.mariotaku.twidere.util.TaskServiceRunner.Companion.ACTION_REFRESH_NOTIFICATIONS import org.mariotaku.twidere.util.TaskServiceRunner.Companion.ACTION_REFRESH_NOTIFICATIONS
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import javax.inject.Inject
class LegacyTaskService : Service() { class LegacyTaskService : BaseService() {
@Inject
internal lateinit var taskServiceRunner: TaskServiceRunner
@Inject
internal lateinit var kPreferences: KPreferences
override fun onBind(intent: Intent): IBinder? = null override fun onBind(intent: Intent): IBinder? = null
@ -49,7 +41,7 @@ class LegacyTaskService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
!kPreferences[autoRefreshCompatibilityModeKey]) return START_NOT_STICKY !preferences[autoRefreshCompatibilityModeKey]) return START_NOT_STICKY
val action = intent?.action ?: return START_NOT_STICKY val action = intent?.action ?: return START_NOT_STICKY
taskServiceRunner.runTask(action) { taskServiceRunner.runTask(action) {
stopSelfResult(startId) stopSelfResult(startId)

View File

@ -3,14 +3,15 @@ package org.mariotaku.twidere.service
import android.accounts.AccountManager import android.accounts.AccountManager
import android.accounts.OnAccountsUpdateListener import android.accounts.OnAccountsUpdateListener
import android.app.PendingIntent import android.app.PendingIntent
import android.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.support.v4.app.NotificationCompat import android.support.v4.app.NotificationCompat
import android.support.v4.net.ConnectivityManagerCompat
import org.apache.commons.lang3.concurrent.BasicThreadFactory import org.apache.commons.lang3.concurrent.BasicThreadFactory
import org.mariotaku.abstask.library.TaskStarter import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe
import org.mariotaku.library.objectcursor.ObjectCursor import org.mariotaku.library.objectcursor.ObjectCursor
@ -21,8 +22,11 @@ import org.mariotaku.microblog.library.twitter.model.Activity
import org.mariotaku.microblog.library.twitter.model.DirectMessage import org.mariotaku.microblog.library.twitter.model.DirectMessage
import org.mariotaku.microblog.library.twitter.model.Status import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.R import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.LOGTAG
import org.mariotaku.twidere.activity.SettingsActivity import org.mariotaku.twidere.activity.SettingsActivity
import org.mariotaku.twidere.annotation.AccountType import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.constant.streamingNonMeteredNetworkKey
import org.mariotaku.twidere.constant.streamingPowerSavingKey
import org.mariotaku.twidere.extension.model.isOfficial import org.mariotaku.twidere.extension.model.isOfficial
import org.mariotaku.twidere.extension.model.isStreamingSupported import org.mariotaku.twidere.extension.model.isStreamingSupported
import org.mariotaku.twidere.extension.model.newMicroBlogInstance import org.mariotaku.twidere.extension.model.newMicroBlogInstance
@ -35,7 +39,8 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
import org.mariotaku.twidere.task.twitter.GetActivitiesAboutMeTask import org.mariotaku.twidere.task.twitter.GetActivitiesAboutMeTask
import org.mariotaku.twidere.task.twitter.message.GetMessagesTask import org.mariotaku.twidere.task.twitter.message.GetMessagesTask
import org.mariotaku.twidere.util.DataStoreUtils import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.NotificationManagerWrapper import org.mariotaku.twidere.util.DebugLog
import org.mariotaku.twidere.util.Utils
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.util.streaming.TwitterTimelineStreamCallback import org.mariotaku.twidere.util.streaming.TwitterTimelineStreamCallback
import java.util.* import java.util.*
@ -43,12 +48,9 @@ import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.Future import java.util.concurrent.Future
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.inject.Inject
class StreamingService : Service() { class StreamingService : BaseService() {
@Inject
internal lateinit var notificationManager: NotificationManagerWrapper
internal lateinit var threadPoolExecutor: ExecutorService internal lateinit var threadPoolExecutor: ExecutorService
internal lateinit var handler: Handler internal lateinit var handler: Handler
@ -84,6 +86,16 @@ class StreamingService : Service() {
override fun onBind(intent: Intent) = throw UnsupportedOperationException() override fun onBind(intent: Intent) = throw UnsupportedOperationException()
private fun setupStreaming(): Boolean { private fun setupStreaming(): Boolean {
val isNetworkMetered = ConnectivityManagerCompat.isActiveNetworkMetered(connectivityManager)
if (preferences[streamingNonMeteredNetworkKey] && isNetworkMetered) {
stopSelf()
return false
}
val isCharging = Utils.isCharging(this)
if (preferences[streamingPowerSavingKey] && !isCharging) {
stopSelf()
return false
}
if (updateStreamingInstances()) { if (updateStreamingInstances()) {
showNotification() showNotification()
return true return true
@ -162,7 +174,7 @@ class StreamingService : Service() {
try { try {
instance.beginStreaming() instance.beginStreaming()
} catch (e: MicroBlogException) { } catch (e: MicroBlogException) {
DebugLog.w(LOGTAG, tr = e)
} }
Thread.sleep(TimeUnit.MINUTES.toMillis(1)) Thread.sleep(TimeUnit.MINUTES.toMillis(1))
} }
@ -191,6 +203,9 @@ class StreamingService : Service() {
} }
val callback = object : TwitterTimelineStreamCallback(account.key.id) { val callback = object : TwitterTimelineStreamCallback(account.key.id) {
private var lastStatusTimestamps = LongArray(2)
private var homeInsertGap = false private var homeInsertGap = false
private var interactionsInsertGap = false private var interactionsInsertGap = false
override fun onConnected(): Boolean { override fun onConnected(): Boolean {
@ -200,9 +215,23 @@ class StreamingService : Service() {
} }
override fun onHomeTimeline(status: Status): Boolean { override fun onHomeTimeline(status: Status): Boolean {
val parcelableStatus = ParcelableStatusUtils.fromStatus(status, account.key,
homeInsertGap, profileImageSize)
val currentTimeMillis = System.currentTimeMillis()
if (lastStatusTimestamps[0] >= parcelableStatus.timestamp) {
val extraValue = (currentTimeMillis - lastStatusTimestamps[1]).coerceAtMost(499)
parcelableStatus.position_key = parcelableStatus.timestamp + extraValue
} else {
parcelableStatus.position_key = parcelableStatus.timestamp
}
parcelableStatus.inserted_date = currentTimeMillis
lastStatusTimestamps[0] = parcelableStatus.position_key
lastStatusTimestamps[1] = parcelableStatus.inserted_date
val values = ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java) val values = ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java)
.create(ParcelableStatusUtils.fromStatus(status, account.key, homeInsertGap, .create(parcelableStatus)
profileImageSize))
context.contentResolver.insert(Statuses.CONTENT_URI, values) context.contentResolver.insert(Statuses.CONTENT_URI, values)
homeInsertGap = false homeInsertGap = false
return true return true
@ -217,9 +246,11 @@ class StreamingService : Service() {
handler.postDelayed(interactionsTimeoutRunnable, TimeUnit.SECONDS.toMillis(30)) handler.postDelayed(interactionsTimeoutRunnable, TimeUnit.SECONDS.toMillis(30))
} }
} else { } else {
val parcelableActivity = ParcelableActivityUtils.fromActivity(activity,
account.key, interactionsInsertGap, profileImageSize)
parcelableActivity.position_key = parcelableActivity.timestamp
val values = ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java) val values = ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java)
.create(ParcelableActivityUtils.fromActivity(activity, account.key, .create(parcelableActivity)
interactionsInsertGap, profileImageSize))
context.contentResolver.insert(Activities.AboutMe.CONTENT_URI, values) context.contentResolver.insert(Activities.AboutMe.CONTENT_URI, values)
interactionsInsertGap = false interactionsInsertGap = false
} }
@ -236,6 +267,11 @@ class StreamingService : Service() {
return true return true
} }
override fun onException(ex: Throwable): Boolean {
DebugLog.w(LOGTAG, tr = ex)
return true
}
private fun getInteractions() { private fun getInteractions() {
val task = GetActivitiesAboutMeTask(context) val task = GetActivitiesAboutMeTask(context)
task.params = object : SimpleRefreshTaskParam() { task.params = object : SimpleRefreshTaskParam() {

View File

@ -297,6 +297,11 @@ class ApplicationModule(private val application: Application) {
return application.getSystemService(Context.LOCATION_SERVICE) as LocationManager return application.getSystemService(Context.LOCATION_SERVICE) as LocationManager
} }
@Provides
fun connectivityManager(): ConnectivityManager {
return application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
}
@Provides @Provides
fun okHttpClient(preferences: SharedPreferencesWrapper, dns: Dns, connectionPool: ConnectionPool, fun okHttpClient(preferences: SharedPreferencesWrapper, dns: Dns, connectionPool: ConnectionPool,
cache: Cache): OkHttpClient { cache: Cache): OkHttpClient {

View File

@ -38,10 +38,7 @@ import org.mariotaku.twidere.preference.PremiumEntryPreferenceCategory
import org.mariotaku.twidere.preference.sync.SyncItemPreference import org.mariotaku.twidere.preference.sync.SyncItemPreference
import org.mariotaku.twidere.provider.CacheProvider import org.mariotaku.twidere.provider.CacheProvider
import org.mariotaku.twidere.provider.TwidereDataProvider import org.mariotaku.twidere.provider.TwidereDataProvider
import org.mariotaku.twidere.service.BaseIntentService import org.mariotaku.twidere.service.*
import org.mariotaku.twidere.service.JobTaskService
import org.mariotaku.twidere.service.LegacyTaskService
import org.mariotaku.twidere.service.StreamingService
import org.mariotaku.twidere.task.BaseAbstractTask import org.mariotaku.twidere.task.BaseAbstractTask
import org.mariotaku.twidere.task.ManagedAsyncTask import org.mariotaku.twidere.task.ManagedAsyncTask
import org.mariotaku.twidere.text.util.EmojiEditableFactory import org.mariotaku.twidere.text.util.EmojiEditableFactory
@ -144,4 +141,6 @@ interface GeneralComponent {
fun inject(fragment: ExoPlayerPageFragment) fun inject(fragment: ExoPlayerPageFragment)
fun inject(service: StreamingService) fun inject(service: StreamingService)
fun inject(service: BaseService)
} }