From 62a52c78ed8dbed62a292d7b9a4d2579822f0d41 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Sun, 12 Mar 2017 22:28:57 +0800 Subject: [PATCH] fixed user stream position key - now notifications can work properly --- .../twidere/constant/PreferenceKeys.kt | 2 + .../service/AccountAuthenticatorService.kt | 2 +- .../twidere/service/AccountSyncService.kt | 2 +- .../mariotaku/twidere/service/BaseService.kt | 53 +++++++++++++++++ .../twidere/service/LegacyTaskService.kt | 14 +---- .../twidere/service/StreamingService.kt | 58 +++++++++++++++---- .../twidere/util/dagger/ApplicationModule.kt | 5 ++ .../twidere/util/dagger/GeneralComponent.kt | 7 +-- 8 files changed, 115 insertions(+), 28 deletions(-) create mode 100644 twidere/src/main/kotlin/org/mariotaku/twidere/service/BaseService.kt diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt index 4253ff249..94ae8e298 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt @@ -69,6 +69,8 @@ val floatingDetailedContentsKey = KBooleanKey("floating_detailed_contents", true val localTrendsWoeIdKey = KIntKey(KEY_LOCAL_TRENDS_WOEID, 1) val phishingLinksWaringKey = KBooleanKey(KEY_PHISHING_LINK_WARNING, true) 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(KEY_THEME_BACKGROUND_ALPHA, 0xFF) { override fun read(preferences: SharedPreferences): Int { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountAuthenticatorService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountAuthenticatorService.kt index f0e47b000..4cc41524b 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountAuthenticatorService.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountAuthenticatorService.kt @@ -16,7 +16,7 @@ import org.mariotaku.twidere.activity.SignInActivity /** * Created by mariotaku on 2016/12/2. */ -class AccountAuthenticatorService : Service() { +class AccountAuthenticatorService : BaseService() { private lateinit var authenticator: TwidereAccountAuthenticator diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountSyncService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountSyncService.kt index fe17812f8..19c8b98d2 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountSyncService.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/service/AccountSyncService.kt @@ -10,7 +10,7 @@ import android.os.IBinder /** * Created by mariotaku on 2016/12/3. */ -class AccountSyncService : Service() { +class AccountSyncService : BaseService() { override fun onCreate() { /* diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/BaseService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/BaseService.kt new file mode 100644 index 000000000..5ca0572cd --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/service/BaseService.kt @@ -0,0 +1,53 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * 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 . + */ + +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) + } +} \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/LegacyTaskService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/LegacyTaskService.kt index ae8dcc434..ad9ea7245 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/service/LegacyTaskService.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/service/LegacyTaskService.kt @@ -19,26 +19,18 @@ package org.mariotaku.twidere.service -import android.app.Service import android.content.Intent import android.os.Build import android.os.IBinder -import org.mariotaku.kpreferences.KPreferences +import org.mariotaku.kpreferences.get import org.mariotaku.twidere.annotation.AutoRefreshType 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_HOME_TIMELINE import org.mariotaku.twidere.util.TaskServiceRunner.Companion.ACTION_REFRESH_NOTIFICATIONS import org.mariotaku.twidere.util.dagger.GeneralComponentHelper -import javax.inject.Inject -class LegacyTaskService : Service() { - - @Inject - internal lateinit var taskServiceRunner: TaskServiceRunner - @Inject - internal lateinit var kPreferences: KPreferences +class LegacyTaskService : BaseService() { override fun onBind(intent: Intent): IBinder? = null @@ -49,7 +41,7 @@ class LegacyTaskService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 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 taskServiceRunner.runTask(action) { stopSelfResult(startId) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt index 47979ad00..192ae3053 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt @@ -3,14 +3,15 @@ package org.mariotaku.twidere.service import android.accounts.AccountManager import android.accounts.OnAccountsUpdateListener import android.app.PendingIntent -import android.app.Service import android.content.Context import android.content.Intent import android.os.Handler import android.os.Looper import android.support.v4.app.NotificationCompat +import android.support.v4.net.ConnectivityManagerCompat import org.apache.commons.lang3.concurrent.BasicThreadFactory import org.mariotaku.abstask.library.TaskStarter +import org.mariotaku.kpreferences.get import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe 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.Status import org.mariotaku.twidere.R +import org.mariotaku.twidere.TwidereConstants.LOGTAG import org.mariotaku.twidere.activity.SettingsActivity 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.isStreamingSupported 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.message.GetMessagesTask 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.streaming.TwitterTimelineStreamCallback import java.util.* @@ -43,12 +48,9 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.Future 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 handler: Handler @@ -84,6 +86,16 @@ class StreamingService : Service() { override fun onBind(intent: Intent) = throw UnsupportedOperationException() 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()) { showNotification() return true @@ -162,7 +174,7 @@ class StreamingService : Service() { try { instance.beginStreaming() } catch (e: MicroBlogException) { - + DebugLog.w(LOGTAG, tr = e) } Thread.sleep(TimeUnit.MINUTES.toMillis(1)) } @@ -191,6 +203,9 @@ class StreamingService : Service() { } val callback = object : TwitterTimelineStreamCallback(account.key.id) { + + private var lastStatusTimestamps = LongArray(2) + private var homeInsertGap = false private var interactionsInsertGap = false override fun onConnected(): Boolean { @@ -200,9 +215,23 @@ class StreamingService : Service() { } 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) - .create(ParcelableStatusUtils.fromStatus(status, account.key, homeInsertGap, - profileImageSize)) + .create(parcelableStatus) context.contentResolver.insert(Statuses.CONTENT_URI, values) homeInsertGap = false return true @@ -217,9 +246,11 @@ class StreamingService : Service() { handler.postDelayed(interactionsTimeoutRunnable, TimeUnit.SECONDS.toMillis(30)) } } else { + val parcelableActivity = ParcelableActivityUtils.fromActivity(activity, + account.key, interactionsInsertGap, profileImageSize) + parcelableActivity.position_key = parcelableActivity.timestamp val values = ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java) - .create(ParcelableActivityUtils.fromActivity(activity, account.key, - interactionsInsertGap, profileImageSize)) + .create(parcelableActivity) context.contentResolver.insert(Activities.AboutMe.CONTENT_URI, values) interactionsInsertGap = false } @@ -236,6 +267,11 @@ class StreamingService : Service() { return true } + override fun onException(ex: Throwable): Boolean { + DebugLog.w(LOGTAG, tr = ex) + return true + } + private fun getInteractions() { val task = GetActivitiesAboutMeTask(context) task.params = object : SimpleRefreshTaskParam() { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/ApplicationModule.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/ApplicationModule.kt index 406bbff5a..f66c366c3 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/ApplicationModule.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/ApplicationModule.kt @@ -297,6 +297,11 @@ class ApplicationModule(private val application: Application) { return application.getSystemService(Context.LOCATION_SERVICE) as LocationManager } + @Provides + fun connectivityManager(): ConnectivityManager { + return application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + } + @Provides fun okHttpClient(preferences: SharedPreferencesWrapper, dns: Dns, connectionPool: ConnectionPool, cache: Cache): OkHttpClient { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt index 35d9f0cf8..de1cf3488 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt @@ -38,10 +38,7 @@ import org.mariotaku.twidere.preference.PremiumEntryPreferenceCategory import org.mariotaku.twidere.preference.sync.SyncItemPreference import org.mariotaku.twidere.provider.CacheProvider import org.mariotaku.twidere.provider.TwidereDataProvider -import org.mariotaku.twidere.service.BaseIntentService -import org.mariotaku.twidere.service.JobTaskService -import org.mariotaku.twidere.service.LegacyTaskService -import org.mariotaku.twidere.service.StreamingService +import org.mariotaku.twidere.service.* import org.mariotaku.twidere.task.BaseAbstractTask import org.mariotaku.twidere.task.ManagedAsyncTask import org.mariotaku.twidere.text.util.EmojiEditableFactory @@ -144,4 +141,6 @@ interface GeneralComponent { fun inject(fragment: ExoPlayerPageFragment) fun inject(service: StreamingService) + + fun inject(service: BaseService) }