improved refresh services
This commit is contained in:
parent
dcf608e3ff
commit
5b1ac84a3b
|
@ -72,19 +72,10 @@ public interface IntentConstants {
|
||||||
|
|
||||||
String BROADCAST_NOTIFICATION_DELETED = INTENT_PACKAGE_PREFIX + "NOTIFICATION_DELETED";
|
String BROADCAST_NOTIFICATION_DELETED = INTENT_PACKAGE_PREFIX + "NOTIFICATION_DELETED";
|
||||||
|
|
||||||
String BROADCAST_USER_LIST_MEMBERS_DELETED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_DELETED";
|
String ACTION_REFRESH_HOME_TIMELINE = INTENT_PACKAGE_PREFIX + "REFRESH_HOME_TIMELINE";
|
||||||
String BROADCAST_REFRESH_HOME_TIMELINE = INTENT_PACKAGE_PREFIX + "REFRESH_HOME_TIMELINE";
|
String ACTION_REFRESH_NOTIFICATIONS = INTENT_PACKAGE_PREFIX + "REFRESH_NOTIFICATIONS";
|
||||||
String BROADCAST_REFRESH_NOTIFICATIONS = INTENT_PACKAGE_PREFIX + "REFRESH_NOTIFICATIONS";
|
String ACTION_REFRESH_DIRECT_MESSAGES = INTENT_PACKAGE_PREFIX + "REFRESH_DIRECT_MESSAGES";
|
||||||
String BROADCAST_REFRESH_DIRECT_MESSAGES = INTENT_PACKAGE_PREFIX + "REFRESH_DIRECT_MESSAGES";
|
String ACTION_REFRESH_TRENDS = INTENT_PACKAGE_PREFIX + "REFRESH_TRENDS";
|
||||||
String BROADCAST_REFRESH_TRENDS = INTENT_PACKAGE_PREFIX + "REFRESH_TRENDS";
|
|
||||||
String BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING = INTENT_PACKAGE_PREFIX
|
|
||||||
+ "RESCHEDULE_HOME_TIMELINE_REFRESHING";
|
|
||||||
String BROADCAST_RESCHEDULE_MENTIONS_REFRESHING = INTENT_PACKAGE_PREFIX
|
|
||||||
+ "RESCHEDULE_MENTIONS_REFRESHING";
|
|
||||||
String BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING = INTENT_PACKAGE_PREFIX
|
|
||||||
+ "RESCHEDULE_DIRECT_MESSAGES_REFRESHING";
|
|
||||||
String BROADCAST_RESCHEDULE_TRENDS_REFRESHING = INTENT_PACKAGE_PREFIX
|
|
||||||
+ "RESCHEDULE_TRENDS_REFRESHING";
|
|
||||||
|
|
||||||
String EXTRA_LATITUDE = "latitude";
|
String EXTRA_LATITUDE = "latitude";
|
||||||
String EXTRA_LONGITUDE = "longitude";
|
String EXTRA_LONGITUDE = "longitude";
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.NFC"/>
|
<uses-permission android:name="android.permission.NFC"/>
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
|
||||||
<!-- Used for account management -->
|
<!-- Used for account management -->
|
||||||
<uses-permission
|
<uses-permission
|
||||||
|
@ -588,14 +589,6 @@
|
||||||
android:scheme="android_secret_code"/>
|
android:scheme="android_secret_code"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".receiver.PowerStateReceiver">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.BATTERY_LOW"/>
|
|
||||||
<action android:name="android.intent.action.BATTERY_OKAY"/>
|
|
||||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
|
||||||
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.mariotaku.twidere.annotation;
|
||||||
|
|
||||||
|
import android.support.annotation.StringDef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2016/12/17.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@StringDef({AutoRefreshType.HOME_TIMELINE, AutoRefreshType.INTERACTIONS_TIMELINE, AutoRefreshType.DIRECT_MESSAGES})
|
||||||
|
public @interface AutoRefreshType {
|
||||||
|
|
||||||
|
String HOME_TIMELINE = "home_timeline";
|
||||||
|
String INTERACTIONS_TIMELINE = "interactions_timeline";
|
||||||
|
String DIRECT_MESSAGES = "direct_messages";
|
||||||
|
|
||||||
|
String[] ALL = {HOME_TIMELINE, INTERACTIONS_TIMELINE, DIRECT_MESSAGES};
|
||||||
|
}
|
|
@ -48,7 +48,6 @@ public class ConnectivityStateReceiver extends BroadcastReceiver implements Cons
|
||||||
if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) return;
|
if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) return;
|
||||||
final TwidereApplication application = TwidereApplication.Companion.getInstance(context);
|
final TwidereApplication application = TwidereApplication.Companion.getInstance(context);
|
||||||
// application.reloadConnectivitySettings();
|
// application.reloadConnectivitySettings();
|
||||||
Utils.startRefreshServiceIfNeeded(application);
|
|
||||||
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
|
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
|
||||||
Context.MODE_PRIVATE);
|
Context.MODE_PRIVATE);
|
||||||
if (prefs.getBoolean(KEY_USAGE_STATISTICS, false) && prefs.getBoolean(KEY_SETTINGS_WIZARD_COMPLETED, false)) {
|
if (prefs.getBoolean(KEY_USAGE_STATISTICS, false) && prefs.getBoolean(KEY_SETTINGS_WIZARD_COMPLETED, false)) {
|
||||||
|
|
|
@ -1019,8 +1019,11 @@ public class DataStoreUtils implements Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void prepareDatabase(@NonNull Context context) {
|
public static void prepareDatabase(@NonNull Context context) {
|
||||||
context.getContentResolver().query(TwidereDataStore.CONTENT_URI_DATABASE_PREPARE, null,
|
final ContentResolver cr = context.getContentResolver();
|
||||||
null, null, null);
|
final Cursor cursor = cr.query(TwidereDataStore.CONTENT_URI_DATABASE_PREPARE, null, null,
|
||||||
|
null, null);
|
||||||
|
if (cursor == null) return;
|
||||||
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FieldArrayCreator<T> {
|
interface FieldArrayCreator<T> {
|
||||||
|
|
|
@ -47,7 +47,6 @@ import android.net.NetworkInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.nfc.NfcAdapter;
|
import android.nfc.NfcAdapter;
|
||||||
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
|
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -125,7 +124,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
|
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||||
import org.mariotaku.twidere.service.RefreshService;
|
|
||||||
import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle;
|
import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle;
|
||||||
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
||||||
import org.mariotaku.twidere.view.ShapedImageView;
|
import org.mariotaku.twidere.view.ShapedImageView;
|
||||||
|
@ -1184,27 +1182,6 @@ public final class Utils implements Constants {
|
||||||
showErrorMessage(context, message, long_message);
|
showErrorMessage(context, message, long_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startRefreshServiceIfNeeded(@NonNull final Context context) {
|
|
||||||
final Context appContext = context.getApplicationContext();
|
|
||||||
if (appContext == null) return;
|
|
||||||
if (!appContext.getResources().getBoolean(R.bool.use_legacy_refresh_service)) return;
|
|
||||||
final Intent refreshServiceIntent = new Intent(appContext, RefreshService.class);
|
|
||||||
DataStoreUtils.prepareDatabase(context);
|
|
||||||
AsyncTask.execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (isNetworkAvailable(appContext) && hasAutoRefreshAccounts(appContext)) {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(LOGTAG, "Start background refresh service");
|
|
||||||
}
|
|
||||||
appContext.startService(refreshServiceIntent);
|
|
||||||
} else {
|
|
||||||
appContext.stopService(refreshServiceIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startStatusShareChooser(final Context context, final ParcelableStatus status) {
|
public static void startStatusShareChooser(final Context context, final ParcelableStatus status) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
intent.setType("text/plain");
|
intent.setType("text/plain");
|
||||||
|
@ -1230,10 +1207,6 @@ public final class Utils implements Constants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String trim(final String str) {
|
|
||||||
return str != null ? str.trim() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String trimLineBreak(final String orig) {
|
public static String trimLineBreak(final String orig) {
|
||||||
if (orig == null) return null;
|
if (orig == null) return null;
|
||||||
return orig.replaceAll("\\n+", "\n");
|
return orig.replaceAll("\\n+", "\n");
|
||||||
|
@ -1306,11 +1279,6 @@ public final class Utils implements Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void setSharedElementTransition(Context context, Window window, int transitionRes) {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
|
|
||||||
UtilsL.setSharedElementTransition(context, window, transitionRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Object findFieldOfTypes(T obj, Class<? extends T> cls, Class<?>... checkTypes) {
|
public static <T> Object findFieldOfTypes(T obj, Class<? extends T> cls, Class<?>... checkTypes) {
|
||||||
labelField:
|
labelField:
|
||||||
for (Field field : cls.getDeclaredFields()) {
|
for (Field field : cls.getDeclaredFields()) {
|
||||||
|
@ -1476,4 +1444,5 @@ public final class Utils implements Constants {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,6 @@ import org.mariotaku.twidere.constant.apiLastChangeKey
|
||||||
import org.mariotaku.twidere.constant.bugReportsKey
|
import org.mariotaku.twidere.constant.bugReportsKey
|
||||||
import org.mariotaku.twidere.constant.defaultFeatureLastUpdated
|
import org.mariotaku.twidere.constant.defaultFeatureLastUpdated
|
||||||
import org.mariotaku.twidere.model.DefaultFeatures
|
import org.mariotaku.twidere.model.DefaultFeatures
|
||||||
import org.mariotaku.twidere.service.RefreshService
|
|
||||||
import org.mariotaku.twidere.util.*
|
import org.mariotaku.twidere.util.*
|
||||||
import org.mariotaku.twidere.util.content.TwidereSQLiteOpenHelper
|
import org.mariotaku.twidere.util.content.TwidereSQLiteOpenHelper
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
|
@ -93,6 +92,8 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
lateinit internal var externalThemeManager: ExternalThemeManager
|
lateinit internal var externalThemeManager: ExternalThemeManager
|
||||||
@Inject
|
@Inject
|
||||||
lateinit internal var kPreferences: KPreferences
|
lateinit internal var kPreferences: KPreferences
|
||||||
|
@Inject
|
||||||
|
lateinit internal var autoRefreshController: AutoRefreshController
|
||||||
|
|
||||||
private lateinit var profileImageViewViewProcessor: ProfileImageViewViewProcessor
|
private lateinit var profileImageViewViewProcessor: ProfileImageViewViewProcessor
|
||||||
private lateinit var fontFamilyTagProcessor: FontFamilyTagProcessor
|
private lateinit var fontFamilyTagProcessor: FontFamilyTagProcessor
|
||||||
|
@ -129,13 +130,10 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
updateEasterEggIcon()
|
updateEasterEggIcon()
|
||||||
|
|
||||||
migrateUsageStatisticsPreferences()
|
migrateUsageStatisticsPreferences()
|
||||||
if (resources.getBoolean(R.bool.use_job_refresh_service)) {
|
|
||||||
} else {
|
|
||||||
Utils.startRefreshServiceIfNeeded(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
GeneralComponentHelper.build(this).inject(this)
|
GeneralComponentHelper.build(this).inject(this)
|
||||||
|
|
||||||
|
autoRefreshController.appStarted()
|
||||||
|
|
||||||
registerActivityLifecycleCallbacks(activityTracker)
|
registerActivityLifecycleCallbacks(activityTracker)
|
||||||
|
|
||||||
listenExternalThemeChange()
|
listenExternalThemeChange()
|
||||||
|
@ -288,8 +286,7 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
|
||||||
when (key) {
|
when (key) {
|
||||||
KEY_REFRESH_INTERVAL -> {
|
KEY_REFRESH_INTERVAL -> {
|
||||||
stopService(Intent(this, RefreshService::class.java))
|
autoRefreshController.rescheduleAll()
|
||||||
Utils.startRefreshServiceIfNeeded(this)
|
|
||||||
}
|
}
|
||||||
KEY_ENABLE_PROXY, KEY_PROXY_HOST, KEY_PROXY_PORT, KEY_PROXY_TYPE, KEY_PROXY_USERNAME,
|
KEY_ENABLE_PROXY, KEY_PROXY_HOST, KEY_PROXY_PORT, KEY_PROXY_TYPE, KEY_PROXY_USERNAME,
|
||||||
KEY_PROXY_PASSWORD, KEY_CONNECTION_TIMEOUT, KEY_RETRY_ON_NETWORK_ISSUE -> {
|
KEY_PROXY_PASSWORD, KEY_CONNECTION_TIMEOUT, KEY_RETRY_ON_NETWORK_ISSUE -> {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import org.mariotaku.kpreferences.*
|
import org.mariotaku.kpreferences.*
|
||||||
|
import org.mariotaku.ktextension.toLong
|
||||||
import org.mariotaku.twidere.BuildConfig
|
import org.mariotaku.twidere.BuildConfig
|
||||||
import org.mariotaku.twidere.Constants.KEY_NO_CLOSE_AFTER_TWEET_SENT
|
import org.mariotaku.twidere.Constants.KEY_NO_CLOSE_AFTER_TWEET_SENT
|
||||||
import org.mariotaku.twidere.TwidereConstants.*
|
import org.mariotaku.twidere.TwidereConstants.*
|
||||||
|
@ -44,6 +45,18 @@ val randomizeAccountNameKey = KBooleanKey(KEY_RANDOMIZE_ACCOUNT_NAME, false)
|
||||||
val defaultAutoRefreshKey = KBooleanKey(KEY_DEFAULT_AUTO_REFRESH, false)
|
val defaultAutoRefreshKey = KBooleanKey(KEY_DEFAULT_AUTO_REFRESH, false)
|
||||||
val defaultAutoRefreshKeyAsked = KBooleanKey("default_auto_refresh_asked", true)
|
val defaultAutoRefreshKeyAsked = KBooleanKey("default_auto_refresh_asked", true)
|
||||||
|
|
||||||
|
object refreshIntervalKey : KSimpleKey<Long>(KEY_REFRESH_INTERVAL, 15) {
|
||||||
|
override fun read(preferences: SharedPreferences): Long {
|
||||||
|
return preferences.getString(key, null).toLong(def)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(editor: SharedPreferences.Editor, value: Long): Boolean {
|
||||||
|
editor.putString(key, value.toString())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
object defaultAPIConfigKey : KPreferenceKey<CustomAPIConfig> {
|
object defaultAPIConfigKey : KPreferenceKey<CustomAPIConfig> {
|
||||||
override fun contains(preferences: SharedPreferences): Boolean {
|
override fun contains(preferences: SharedPreferences): Boolean {
|
||||||
if (preferences.getString(KEY_API_URL_FORMAT, null) == null) return false
|
if (preferences.getString(KEY_API_URL_FORMAT, null) == null) return false
|
||||||
|
|
|
@ -19,11 +19,9 @@
|
||||||
|
|
||||||
package org.mariotaku.twidere.fragment
|
package org.mariotaku.twidere.fragment
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_AUTO_REFRESH
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_AUTO_REFRESH
|
||||||
import org.mariotaku.twidere.constant.defaultAutoRefreshKey
|
import org.mariotaku.twidere.constant.defaultAutoRefreshKey
|
||||||
import org.mariotaku.twidere.util.Utils
|
|
||||||
|
|
||||||
class AccountRefreshSettingsFragment : BaseAccountPreferenceFragment() {
|
class AccountRefreshSettingsFragment : BaseAccountPreferenceFragment() {
|
||||||
|
|
||||||
|
@ -36,9 +34,4 @@ class AccountRefreshSettingsFragment : BaseAccountPreferenceFragment() {
|
||||||
override val switchPreferenceKey: String?
|
override val switchPreferenceKey: String?
|
||||||
get() = KEY_AUTO_REFRESH
|
get() = KEY_AUTO_REFRESH
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
|
|
||||||
if (KEY_AUTO_REFRESH == key) {
|
|
||||||
Utils.startRefreshServiceIfNeeded(activity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Twidere - Twitter client for Android
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012-2015 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.receiver
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
|
|
||||||
import edu.tsinghua.hotmobi.model.BatteryRecord
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mariotaku on 15/9/29.
|
|
||||||
*/
|
|
||||||
class PowerStateReceiver : BroadcastReceiver() {
|
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
when (intent.action) {
|
|
||||||
Intent.ACTION_BATTERY_LOW, Intent.ACTION_BATTERY_OKAY, Intent.ACTION_POWER_CONNECTED,
|
|
||||||
Intent.ACTION_POWER_DISCONNECTED -> {
|
|
||||||
if (serviceReceiverStarted) return
|
|
||||||
BatteryRecord.log(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
var serviceReceiverStarted: Boolean = false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,17 +24,13 @@ import android.annotation.TargetApi
|
||||||
import android.app.job.JobParameters
|
import android.app.job.JobParameters
|
||||||
import android.app.job.JobService
|
import android.app.job.JobService
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import org.mariotaku.abstask.library.AbstractTask
|
import android.util.Log
|
||||||
import org.mariotaku.abstask.library.TaskStarter
|
import org.mariotaku.abstask.library.TaskStarter
|
||||||
import org.mariotaku.kpreferences.KPreferences
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.BuildConfig
|
||||||
|
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||||
|
import org.mariotaku.twidere.annotation.AutoRefreshType
|
||||||
import org.mariotaku.twidere.constant.stopAutoRefreshWhenBatteryLowKey
|
import org.mariotaku.twidere.constant.stopAutoRefreshWhenBatteryLowKey
|
||||||
import org.mariotaku.twidere.model.AccountPreferences
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
|
||||||
import org.mariotaku.twidere.task.GetActivitiesAboutMeTask
|
|
||||||
import org.mariotaku.twidere.task.GetHomeTimelineTask
|
|
||||||
import org.mariotaku.twidere.task.GetReceivedDirectMessagesTask
|
|
||||||
import org.mariotaku.twidere.util.DataStoreUtils
|
|
||||||
import org.mariotaku.twidere.util.Utils
|
import org.mariotaku.twidere.util.Utils
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -59,10 +55,16 @@ class JobRefreshService : JobService() {
|
||||||
// Low battery, don't refresh
|
// Low battery, don't refresh
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.d(LOGTAG, "Running job ${params.jobId}")
|
||||||
|
}
|
||||||
|
|
||||||
val task = createJobTask(params) ?: return false
|
val task = run {
|
||||||
|
val type = getRefreshType(params.jobId) ?: return@run null
|
||||||
|
return@run RefreshService.createJobTask(this, type)
|
||||||
|
} ?: return false
|
||||||
task.callback = {
|
task.callback = {
|
||||||
this.jobFinished(params, true)
|
this.jobFinished(params, false)
|
||||||
}
|
}
|
||||||
TaskStarter.execute(task)
|
TaskStarter.execute(task)
|
||||||
return true
|
return true
|
||||||
|
@ -72,30 +74,23 @@ class JobRefreshService : JobService() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun createJobTask(params: JobParameters): AbstractTask<*, *, () -> Unit>? {
|
companion object {
|
||||||
when (params.extras?.getString(EXTRA_ACTION)) {
|
const val ID_REFRESH_HOME_TIMELINE = 1
|
||||||
BROADCAST_REFRESH_HOME_TIMELINE -> {
|
const val ID_REFRESH_NOTIFICATIONS = 2
|
||||||
val task = GetHomeTimelineTask(this)
|
const val ID_REFRESH_DIRECT_MESSAGES = 3
|
||||||
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshHomeTimelineEnabled) { accountKeys ->
|
|
||||||
DataStoreUtils.getNewestStatusIds(this, Statuses.CONTENT_URI, accountKeys)
|
fun getJobId(@AutoRefreshType type: String): Int = when (type) {
|
||||||
}
|
AutoRefreshType.HOME_TIMELINE -> JobRefreshService.ID_REFRESH_HOME_TIMELINE
|
||||||
return task
|
AutoRefreshType.INTERACTIONS_TIMELINE -> JobRefreshService.ID_REFRESH_NOTIFICATIONS
|
||||||
}
|
AutoRefreshType.DIRECT_MESSAGES -> JobRefreshService.ID_REFRESH_DIRECT_MESSAGES
|
||||||
BROADCAST_REFRESH_NOTIFICATIONS -> {
|
else -> 0
|
||||||
val task = GetActivitiesAboutMeTask(this)
|
}
|
||||||
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
|
|
||||||
DataStoreUtils.getNewestActivityMaxPositions(this, Activities.AboutMe.CONTENT_URI, accountKeys)
|
fun getRefreshType(jobId: Int): String? = when (jobId) {
|
||||||
}
|
JobRefreshService.ID_REFRESH_HOME_TIMELINE -> AutoRefreshType.HOME_TIMELINE
|
||||||
return task
|
JobRefreshService.ID_REFRESH_NOTIFICATIONS -> AutoRefreshType.INTERACTIONS_TIMELINE
|
||||||
}
|
JobRefreshService.ID_REFRESH_DIRECT_MESSAGES -> AutoRefreshType.DIRECT_MESSAGES
|
||||||
BROADCAST_REFRESH_DIRECT_MESSAGES -> {
|
else -> null
|
||||||
val task = GetReceivedDirectMessagesTask(this)
|
|
||||||
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
|
|
||||||
DataStoreUtils.getNewestMessageIds(this, DirectMessages.Inbox.CONTENT_URI, accountKeys)
|
|
||||||
}
|
|
||||||
return task
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,269 +19,53 @@
|
||||||
|
|
||||||
package org.mariotaku.twidere.service
|
package org.mariotaku.twidere.service
|
||||||
|
|
||||||
import android.app.AlarmManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
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.os.SystemClock
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import edu.tsinghua.hotmobi.model.BatteryRecord
|
import org.mariotaku.abstask.library.AbstractTask
|
||||||
import edu.tsinghua.hotmobi.model.ScreenEvent
|
import org.mariotaku.ktextension.convert
|
||||||
import org.apache.commons.lang3.math.NumberUtils
|
|
||||||
import org.mariotaku.twidere.BuildConfig
|
|
||||||
import org.mariotaku.twidere.Constants
|
|
||||||
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||||
|
import org.mariotaku.twidere.annotation.AutoRefreshType
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.*
|
|
||||||
import org.mariotaku.twidere.model.AccountPreferences
|
import org.mariotaku.twidere.model.AccountPreferences
|
||||||
import org.mariotaku.twidere.model.SimpleRefreshTaskParam
|
import org.mariotaku.twidere.model.SimpleRefreshTaskParam
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||||
import org.mariotaku.twidere.receiver.PowerStateReceiver
|
import org.mariotaku.twidere.task.GetActivitiesAboutMeTask
|
||||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper
|
import org.mariotaku.twidere.task.GetHomeTimelineTask
|
||||||
|
import org.mariotaku.twidere.task.GetReceivedDirectMessagesTask
|
||||||
import org.mariotaku.twidere.util.DataStoreUtils
|
import org.mariotaku.twidere.util.DataStoreUtils
|
||||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper
|
import org.mariotaku.twidere.util.SharedPreferencesWrapper
|
||||||
import org.mariotaku.twidere.util.Utils
|
|
||||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RefreshService : Service(), Constants {
|
class RefreshService : Service() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
internal lateinit var preferences: SharedPreferencesWrapper
|
internal lateinit var preferences: SharedPreferencesWrapper
|
||||||
@Inject
|
|
||||||
internal lateinit var twitterWrapper: AsyncTwitterWrapper
|
|
||||||
|
|
||||||
private lateinit var alarmManager: AlarmManager
|
override fun onBind(intent: Intent): IBinder? = null
|
||||||
private var pendingRefreshHomeTimelineIntent: PendingIntent? = null
|
|
||||||
private var pendingRefreshMentionsIntent: PendingIntent? = null
|
|
||||||
private var pendingRefreshDirectMessagesIntent: PendingIntent? = null
|
|
||||||
private var pendingRefreshTrendsIntent: PendingIntent? = null
|
|
||||||
|
|
||||||
private val mStateReceiver = object : BroadcastReceiver() {
|
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
val action = intent.action
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(LOGTAG, String.format("Refresh service received action %s", action))
|
|
||||||
}
|
|
||||||
when (action) {
|
|
||||||
BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING -> {
|
|
||||||
rescheduleHomeTimelineRefreshing()
|
|
||||||
}
|
|
||||||
BROADCAST_RESCHEDULE_MENTIONS_REFRESHING -> {
|
|
||||||
rescheduleMentionsRefreshing()
|
|
||||||
}
|
|
||||||
BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING -> {
|
|
||||||
rescheduleDirectMessagesRefreshing()
|
|
||||||
}
|
|
||||||
BROADCAST_RESCHEDULE_TRENDS_REFRESHING -> {
|
|
||||||
rescheduleTrendsRefreshing()
|
|
||||||
}
|
|
||||||
BROADCAST_REFRESH_HOME_TIMELINE -> {
|
|
||||||
if (isAutoRefreshAllowed) {
|
|
||||||
twitterWrapper.getHomeTimelineAsync(AutoRefreshTaskParam(context,
|
|
||||||
AccountPreferences::isAutoRefreshHomeTimelineEnabled) { accountKeys ->
|
|
||||||
DataStoreUtils.getNewestStatusIds(context, Statuses.CONTENT_URI, accountKeys)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BROADCAST_REFRESH_NOTIFICATIONS -> {
|
|
||||||
if (isAutoRefreshAllowed) {
|
|
||||||
twitterWrapper.getActivitiesAboutMeAsync(AutoRefreshTaskParam(context,
|
|
||||||
AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
|
|
||||||
DataStoreUtils.getNewestActivityMaxPositions(context,
|
|
||||||
Activities.AboutMe.CONTENT_URI, accountKeys)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BROADCAST_REFRESH_DIRECT_MESSAGES -> {
|
|
||||||
if (isAutoRefreshAllowed) {
|
|
||||||
twitterWrapper.getReceivedDirectMessagesAsync(AutoRefreshTaskParam(context,
|
|
||||||
AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
|
|
||||||
DataStoreUtils.getNewestMessageIds(context,
|
|
||||||
DirectMessages.Inbox.CONTENT_URI, accountKeys)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BROADCAST_REFRESH_TRENDS -> {
|
|
||||||
if (isAutoRefreshAllowed) {
|
|
||||||
val prefs = AccountPreferences.getAccountPreferences(context,
|
|
||||||
DataStoreUtils.getAccountKeys(context)).filter(AccountPreferences::isAutoRefreshEnabled)
|
|
||||||
getLocalTrends(prefs.filter(AccountPreferences::isAutoRefreshTrendsEnabled)
|
|
||||||
.map(AccountPreferences::getAccountKey).toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private val mPowerStateReceiver = object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
when (intent.action) {
|
|
||||||
Intent.ACTION_BATTERY_CHANGED -> {
|
|
||||||
BatteryRecord.log(context, intent)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
BatteryRecord.log(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val mScreenStateReceiver = object : BroadcastReceiver() {
|
|
||||||
var mPresentTime: Long = -1
|
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
when (intent.action) {
|
|
||||||
Intent.ACTION_SCREEN_ON -> {
|
|
||||||
ScreenEvent.log(context, ScreenEvent.Action.ON, presentDuration)
|
|
||||||
}
|
|
||||||
Intent.ACTION_SCREEN_OFF -> {
|
|
||||||
ScreenEvent.log(context, ScreenEvent.Action.OFF, presentDuration)
|
|
||||||
mPresentTime = -1
|
|
||||||
}
|
|
||||||
Intent.ACTION_USER_PRESENT -> {
|
|
||||||
mPresentTime = SystemClock.elapsedRealtime()
|
|
||||||
ScreenEvent.log(context, ScreenEvent.Action.PRESENT, -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val presentDuration: Long
|
|
||||||
get() {
|
|
||||||
if (mPresentTime < 0) return -1
|
|
||||||
return SystemClock.elapsedRealtime() - mPresentTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
GeneralComponentHelper.build(this).inject(this)
|
GeneralComponentHelper.build(this).inject(this)
|
||||||
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
}
|
||||||
pendingRefreshHomeTimelineIntent = PendingIntent.getBroadcast(this, 0, Intent(
|
|
||||||
BROADCAST_REFRESH_HOME_TIMELINE), 0)
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
pendingRefreshMentionsIntent = PendingIntent.getBroadcast(this, 0, Intent(BROADCAST_REFRESH_NOTIFICATIONS), 0)
|
Log.d(LOGTAG, "onStartCommand ${intent?.action}")
|
||||||
pendingRefreshDirectMessagesIntent = PendingIntent.getBroadcast(this, 0, Intent(
|
val task = run {
|
||||||
BROADCAST_REFRESH_DIRECT_MESSAGES), 0)
|
val type = intent?.action?.convert { getRefreshType(it) } ?: return@run null
|
||||||
pendingRefreshTrendsIntent = PendingIntent.getBroadcast(this, 0, Intent(BROADCAST_REFRESH_TRENDS), 0)
|
return@run createJobTask(this, type)
|
||||||
val refreshFilter = IntentFilter(BROADCAST_NOTIFICATION_DELETED)
|
} ?: run {
|
||||||
refreshFilter.addAction(BROADCAST_REFRESH_HOME_TIMELINE)
|
stopSelfResult(startId)
|
||||||
refreshFilter.addAction(BROADCAST_REFRESH_NOTIFICATIONS)
|
return START_NOT_STICKY
|
||||||
refreshFilter.addAction(BROADCAST_REFRESH_DIRECT_MESSAGES)
|
|
||||||
refreshFilter.addAction(BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING)
|
|
||||||
refreshFilter.addAction(BROADCAST_RESCHEDULE_MENTIONS_REFRESHING)
|
|
||||||
refreshFilter.addAction(BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING)
|
|
||||||
registerReceiver(mStateReceiver, refreshFilter)
|
|
||||||
val batteryFilter = IntentFilter()
|
|
||||||
batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED)
|
|
||||||
batteryFilter.addAction(Intent.ACTION_BATTERY_OKAY)
|
|
||||||
batteryFilter.addAction(Intent.ACTION_BATTERY_LOW)
|
|
||||||
batteryFilter.addAction(Intent.ACTION_POWER_CONNECTED)
|
|
||||||
batteryFilter.addAction(Intent.ACTION_POWER_DISCONNECTED)
|
|
||||||
val screenFilter = IntentFilter()
|
|
||||||
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
|
|
||||||
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
|
||||||
screenFilter.addAction(Intent.ACTION_USER_PRESENT)
|
|
||||||
registerReceiver(mPowerStateReceiver, batteryFilter)
|
|
||||||
registerReceiver(mScreenStateReceiver, screenFilter)
|
|
||||||
PowerStateReceiver.serviceReceiverStarted = true
|
|
||||||
if (Utils.hasAutoRefreshAccounts(this)) {
|
|
||||||
startAutoRefresh()
|
|
||||||
} else {
|
|
||||||
stopSelf()
|
|
||||||
}
|
}
|
||||||
}
|
task.callback = {
|
||||||
|
stopSelfResult(startId)
|
||||||
override fun onDestroy() {
|
|
||||||
PowerStateReceiver.serviceReceiverStarted = false
|
|
||||||
unregisterReceiver(mScreenStateReceiver)
|
|
||||||
unregisterReceiver(mPowerStateReceiver)
|
|
||||||
unregisterReceiver(mStateReceiver)
|
|
||||||
if (Utils.hasAutoRefreshAccounts(this)) {
|
|
||||||
// Auto refresh enabled, so I will try to start service after it was
|
|
||||||
// stopped.
|
|
||||||
startService(Intent(this, javaClass))
|
|
||||||
}
|
}
|
||||||
super.onDestroy()
|
return START_NOT_STICKY
|
||||||
}
|
|
||||||
|
|
||||||
protected val isAutoRefreshAllowed: Boolean
|
|
||||||
get() = Utils.isNetworkAvailable(this) && (Utils.isBatteryOkay(this) || !Utils.shouldStopAutoRefreshOnBatteryLow(this))
|
|
||||||
|
|
||||||
private fun getLocalTrends(accountIds: Array<UserKey>) {
|
|
||||||
val account_id = Utils.getDefaultAccountKey(this)
|
|
||||||
val woeid = preferences.getInt(KEY_LOCAL_TRENDS_WOEID, 1)
|
|
||||||
twitterWrapper.getLocalTrendsAsync(account_id, woeid)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val refreshInterval: Long
|
|
||||||
get() {
|
|
||||||
val prefValue = NumberUtils.toInt(preferences.getString(KEY_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL), -1)
|
|
||||||
return (Math.max(prefValue, 3) * 60 * 1000).toLong()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rescheduleDirectMessagesRefreshing() {
|
|
||||||
alarmManager.cancel(pendingRefreshDirectMessagesIntent)
|
|
||||||
val refreshInterval = refreshInterval
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, pendingRefreshDirectMessagesIntent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rescheduleHomeTimelineRefreshing() {
|
|
||||||
alarmManager.cancel(pendingRefreshHomeTimelineIntent)
|
|
||||||
val refreshInterval = refreshInterval
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, pendingRefreshHomeTimelineIntent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rescheduleMentionsRefreshing() {
|
|
||||||
alarmManager.cancel(pendingRefreshMentionsIntent)
|
|
||||||
val refreshInterval = refreshInterval
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, pendingRefreshMentionsIntent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rescheduleTrendsRefreshing() {
|
|
||||||
alarmManager.cancel(pendingRefreshTrendsIntent)
|
|
||||||
val refreshInterval = refreshInterval
|
|
||||||
if (refreshInterval > 0) {
|
|
||||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
|
||||||
refreshInterval, pendingRefreshTrendsIntent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startAutoRefresh(): Boolean {
|
|
||||||
stopAutoRefresh()
|
|
||||||
val refreshInterval = refreshInterval
|
|
||||||
if (refreshInterval <= 0) return false
|
|
||||||
rescheduleHomeTimelineRefreshing()
|
|
||||||
rescheduleMentionsRefreshing()
|
|
||||||
rescheduleDirectMessagesRefreshing()
|
|
||||||
rescheduleTrendsRefreshing()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun stopAutoRefresh() {
|
|
||||||
alarmManager.cancel(pendingRefreshHomeTimelineIntent)
|
|
||||||
alarmManager.cancel(pendingRefreshMentionsIntent)
|
|
||||||
alarmManager.cancel(pendingRefreshDirectMessagesIntent)
|
|
||||||
alarmManager.cancel(pendingRefreshTrendsIntent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutoRefreshTaskParam(
|
class AutoRefreshTaskParam(
|
||||||
|
@ -301,4 +85,49 @@ class RefreshService : Service(), Constants {
|
||||||
get() = getSinceIds(accountKeys)
|
get() = getSinceIds(accountKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun createJobTask(context: Context, @AutoRefreshType refreshType: String): AbstractTask<*, *, () -> Unit>? {
|
||||||
|
when (refreshType) {
|
||||||
|
AutoRefreshType.HOME_TIMELINE -> {
|
||||||
|
val task = GetHomeTimelineTask(context)
|
||||||
|
task.params = RefreshService.AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshHomeTimelineEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestStatusIds(context, Statuses.CONTENT_URI, accountKeys)
|
||||||
|
}
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
AutoRefreshType.INTERACTIONS_TIMELINE -> {
|
||||||
|
val task = GetActivitiesAboutMeTask(context)
|
||||||
|
task.params = RefreshService.AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestActivityMaxPositions(context, Activities.AboutMe.CONTENT_URI, accountKeys)
|
||||||
|
}
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
AutoRefreshType.DIRECT_MESSAGES -> {
|
||||||
|
val task = GetReceivedDirectMessagesTask(context)
|
||||||
|
task.params = RefreshService.AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
|
||||||
|
DataStoreUtils.getNewestMessageIds(context, DirectMessages.Inbox.CONTENT_URI, accountKeys)
|
||||||
|
}
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoRefreshType
|
||||||
|
fun getRefreshType(action: String): String? = when (action) {
|
||||||
|
ACTION_REFRESH_HOME_TIMELINE -> AutoRefreshType.HOME_TIMELINE
|
||||||
|
ACTION_REFRESH_NOTIFICATIONS -> AutoRefreshType.INTERACTIONS_TIMELINE
|
||||||
|
ACTION_REFRESH_DIRECT_MESSAGES -> AutoRefreshType.DIRECT_MESSAGES
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRefreshAction(@AutoRefreshType type: String): String? = when (type) {
|
||||||
|
AutoRefreshType.HOME_TIMELINE -> ACTION_REFRESH_HOME_TIMELINE
|
||||||
|
AutoRefreshType.INTERACTIONS_TIMELINE -> ACTION_REFRESH_NOTIFICATIONS
|
||||||
|
AutoRefreshType.DIRECT_MESSAGES -> ACTION_REFRESH_DIRECT_MESSAGES
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.mariotaku.twidere.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
|
import org.mariotaku.twidere.annotation.AutoRefreshType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2016/12/17.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class AutoRefreshController(
|
||||||
|
val context: Context,
|
||||||
|
val kPreferences: KPreferences
|
||||||
|
) {
|
||||||
|
|
||||||
|
abstract fun appStarted()
|
||||||
|
|
||||||
|
abstract fun schedule(@AutoRefreshType type: String)
|
||||||
|
|
||||||
|
abstract fun unschedule(@AutoRefreshType type: String)
|
||||||
|
|
||||||
|
fun reschedule(@AutoRefreshType type: String) {
|
||||||
|
unschedule(type)
|
||||||
|
schedule(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rescheduleAll() {
|
||||||
|
AutoRefreshType.ALL.forEach { reschedule(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.mariotaku.twidere.util
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
|
import android.app.job.JobInfo
|
||||||
|
import android.app.job.JobScheduler
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
|
import org.mariotaku.twidere.annotation.AutoRefreshType
|
||||||
|
import org.mariotaku.twidere.constant.refreshIntervalKey
|
||||||
|
import org.mariotaku.twidere.service.JobRefreshService
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import android.Manifest.permission as AndroidPermissions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2016/12/17.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
class JobSchedulerAutoRefreshController(
|
||||||
|
context: Context,
|
||||||
|
kPreferences: KPreferences
|
||||||
|
) : AutoRefreshController(context, kPreferences) {
|
||||||
|
val scheduler: JobScheduler
|
||||||
|
|
||||||
|
init {
|
||||||
|
scheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appStarted() {
|
||||||
|
val allJobs = scheduler.allPendingJobs
|
||||||
|
AutoRefreshType.ALL.forEach { type ->
|
||||||
|
val jobId = JobRefreshService.getJobId(type)
|
||||||
|
if (allJobs.none { job -> job.id == jobId }) {
|
||||||
|
// Start non existing job
|
||||||
|
schedule(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun schedule(@AutoRefreshType type: String) {
|
||||||
|
val jobId = JobRefreshService.getJobId(type)
|
||||||
|
scheduler.cancel(jobId)
|
||||||
|
scheduleJob(jobId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unschedule(type: String) {
|
||||||
|
val jobId = JobRefreshService.getJobId(type)
|
||||||
|
scheduler.cancel(jobId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scheduleJob(jobId: Int, persisted: Boolean = true) {
|
||||||
|
val builder = JobInfo.Builder(jobId, ComponentName(context, JobRefreshService::class.java))
|
||||||
|
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||||
|
builder.setPeriodic(TimeUnit.MINUTES.toMillis(kPreferences[refreshIntervalKey]))
|
||||||
|
builder.setPersisted(persisted)
|
||||||
|
try {
|
||||||
|
scheduler.schedule(builder.build())
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
if (persisted) {
|
||||||
|
scheduleJob(jobId, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.mariotaku.twidere.util
|
||||||
|
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.support.v4.util.ArrayMap
|
||||||
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
|
import org.mariotaku.twidere.annotation.AutoRefreshType
|
||||||
|
import org.mariotaku.twidere.constant.refreshIntervalKey
|
||||||
|
import org.mariotaku.twidere.service.RefreshService
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class LegacyAutoRefreshController(
|
||||||
|
context: Context,
|
||||||
|
kPreferences: KPreferences
|
||||||
|
) : AutoRefreshController(context, kPreferences) {
|
||||||
|
|
||||||
|
private val alarmManager: AlarmManager
|
||||||
|
|
||||||
|
private val pendingIntents: ArrayMap<String, PendingIntent>
|
||||||
|
|
||||||
|
init {
|
||||||
|
alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
|
|
||||||
|
pendingIntents = ArrayMap()
|
||||||
|
|
||||||
|
AutoRefreshType.ALL.forEach { type ->
|
||||||
|
val action = RefreshService.getRefreshAction(type) ?: return@forEach
|
||||||
|
val intent = Intent(context, RefreshService::class.java)
|
||||||
|
intent.action = action
|
||||||
|
pendingIntents[type] = PendingIntent.getService(context, 0, intent, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appStarted() {
|
||||||
|
rescheduleAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unschedule(type: String) {
|
||||||
|
val pendingIntent = pendingIntents[type] ?: return
|
||||||
|
alarmManager.cancel(pendingIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun schedule(type: String) {
|
||||||
|
val pendingIntent = pendingIntents[type] ?: return
|
||||||
|
val interval = TimeUnit.MINUTES.toMillis(kPreferences[refreshIntervalKey])
|
||||||
|
if (interval > 0) {
|
||||||
|
val triggerAt = System.currentTimeMillis() + interval
|
||||||
|
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, triggerAt, interval, pendingIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -42,6 +42,7 @@ import org.mariotaku.mediaviewer.library.MediaDownloader
|
||||||
import org.mariotaku.restfu.http.RestHttpClient
|
import org.mariotaku.restfu.http.RestHttpClient
|
||||||
import org.mariotaku.twidere.BuildConfig
|
import org.mariotaku.twidere.BuildConfig
|
||||||
import org.mariotaku.twidere.Constants
|
import org.mariotaku.twidere.Constants
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
||||||
import org.mariotaku.twidere.model.DefaultFeatures
|
import org.mariotaku.twidere.model.DefaultFeatures
|
||||||
import org.mariotaku.twidere.util.*
|
import org.mariotaku.twidere.util.*
|
||||||
|
@ -228,6 +229,14 @@ class ApplicationModule(private val application: Application) {
|
||||||
return BidiFormatter.getInstance()
|
return BidiFormatter.getInstance()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun autoRefreshController(kPreferences: KPreferences): AutoRefreshController {
|
||||||
|
if (application.resources.getBoolean(R.bool.use_job_refresh_service)) {
|
||||||
|
return JobSchedulerAutoRefreshController(application, kPreferences)
|
||||||
|
}
|
||||||
|
return LegacyAutoRefreshController(application, kPreferences)
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun defaultFeatures(preferences: SharedPreferencesWrapper): DefaultFeatures {
|
fun defaultFeatures(preferences: SharedPreferencesWrapper): DefaultFeatures {
|
||||||
|
@ -270,3 +279,4 @@ class ApplicationModule(private val application: Application) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!--<bool name="use_job_refresh_service">true</bool>-->
|
<bool name="use_job_refresh_service">true</bool>
|
||||||
<!--<bool name="use_legacy_refresh_service">false</bool>-->
|
<bool name="use_legacy_refresh_service">false</bool>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue