mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-17 04:00:48 +01:00
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_USER_LIST_MEMBERS_DELETED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_DELETED";
|
||||
String BROADCAST_REFRESH_HOME_TIMELINE = INTENT_PACKAGE_PREFIX + "REFRESH_HOME_TIMELINE";
|
||||
String BROADCAST_REFRESH_NOTIFICATIONS = INTENT_PACKAGE_PREFIX + "REFRESH_NOTIFICATIONS";
|
||||
String BROADCAST_REFRESH_DIRECT_MESSAGES = INTENT_PACKAGE_PREFIX + "REFRESH_DIRECT_MESSAGES";
|
||||
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 ACTION_REFRESH_HOME_TIMELINE = INTENT_PACKAGE_PREFIX + "REFRESH_HOME_TIMELINE";
|
||||
String ACTION_REFRESH_NOTIFICATIONS = INTENT_PACKAGE_PREFIX + "REFRESH_NOTIFICATIONS";
|
||||
String ACTION_REFRESH_DIRECT_MESSAGES = INTENT_PACKAGE_PREFIX + "REFRESH_DIRECT_MESSAGES";
|
||||
String ACTION_REFRESH_TRENDS = INTENT_PACKAGE_PREFIX + "REFRESH_TRENDS";
|
||||
|
||||
String EXTRA_LATITUDE = "latitude";
|
||||
String EXTRA_LONGITUDE = "longitude";
|
||||
|
@ -39,6 +39,7 @@
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.NFC"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
|
||||
<!-- Used for account management -->
|
||||
<uses-permission
|
||||
@ -588,14 +589,6 @@
|
||||
android:scheme="android_secret_code"/>
|
||||
</intent-filter>
|
||||
</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>
|
||||
|
||||
|
@ -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;
|
||||
final TwidereApplication application = TwidereApplication.Companion.getInstance(context);
|
||||
// application.reloadConnectivitySettings();
|
||||
Utils.startRefreshServiceIfNeeded(application);
|
||||
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
|
||||
Context.MODE_PRIVATE);
|
||||
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) {
|
||||
context.getContentResolver().query(TwidereDataStore.CONTENT_URI_DATABASE_PREPARE, null,
|
||||
null, null, null);
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
final Cursor cursor = cr.query(TwidereDataStore.CONTENT_URI_DATABASE_PREPARE, null, null,
|
||||
null, null);
|
||||
if (cursor == null) return;
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
interface FieldArrayCreator<T> {
|
||||
|
@ -47,7 +47,6 @@ import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Build;
|
||||
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.ConversationEntries;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
import org.mariotaku.twidere.service.RefreshService;
|
||||
import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle;
|
||||
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
||||
import org.mariotaku.twidere.view.ShapedImageView;
|
||||
@ -1184,27 +1182,6 @@ public final class Utils implements Constants {
|
||||
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) {
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
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) {
|
||||
if (orig == null) return null;
|
||||
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) {
|
||||
labelField:
|
||||
for (Field field : cls.getDeclaredFields()) {
|
||||
@ -1476,4 +1444,5 @@ public final class Utils implements Constants {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -62,7 +62,6 @@ import org.mariotaku.twidere.constant.apiLastChangeKey
|
||||
import org.mariotaku.twidere.constant.bugReportsKey
|
||||
import org.mariotaku.twidere.constant.defaultFeatureLastUpdated
|
||||
import org.mariotaku.twidere.model.DefaultFeatures
|
||||
import org.mariotaku.twidere.service.RefreshService
|
||||
import org.mariotaku.twidere.util.*
|
||||
import org.mariotaku.twidere.util.content.TwidereSQLiteOpenHelper
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||
@ -93,6 +92,8 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||
lateinit internal var externalThemeManager: ExternalThemeManager
|
||||
@Inject
|
||||
lateinit internal var kPreferences: KPreferences
|
||||
@Inject
|
||||
lateinit internal var autoRefreshController: AutoRefreshController
|
||||
|
||||
private lateinit var profileImageViewViewProcessor: ProfileImageViewViewProcessor
|
||||
private lateinit var fontFamilyTagProcessor: FontFamilyTagProcessor
|
||||
@ -129,13 +130,10 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||
updateEasterEggIcon()
|
||||
|
||||
migrateUsageStatisticsPreferences()
|
||||
if (resources.getBoolean(R.bool.use_job_refresh_service)) {
|
||||
} else {
|
||||
Utils.startRefreshServiceIfNeeded(this)
|
||||
}
|
||||
|
||||
GeneralComponentHelper.build(this).inject(this)
|
||||
|
||||
autoRefreshController.appStarted()
|
||||
|
||||
registerActivityLifecycleCallbacks(activityTracker)
|
||||
|
||||
listenExternalThemeChange()
|
||||
@ -288,8 +286,7 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
|
||||
when (key) {
|
||||
KEY_REFRESH_INTERVAL -> {
|
||||
stopService(Intent(this, RefreshService::class.java))
|
||||
Utils.startRefreshServiceIfNeeded(this)
|
||||
autoRefreshController.rescheduleAll()
|
||||
}
|
||||
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 -> {
|
||||
|
@ -4,6 +4,7 @@ import android.content.SharedPreferences
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import org.mariotaku.kpreferences.*
|
||||
import org.mariotaku.ktextension.toLong
|
||||
import org.mariotaku.twidere.BuildConfig
|
||||
import org.mariotaku.twidere.Constants.KEY_NO_CLOSE_AFTER_TWEET_SENT
|
||||
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 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> {
|
||||
override fun contains(preferences: SharedPreferences): Boolean {
|
||||
if (preferences.getString(KEY_API_URL_FORMAT, null) == null) return false
|
||||
|
@ -19,11 +19,9 @@
|
||||
|
||||
package org.mariotaku.twidere.fragment
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_AUTO_REFRESH
|
||||
import org.mariotaku.twidere.constant.defaultAutoRefreshKey
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
|
||||
class AccountRefreshSettingsFragment : BaseAccountPreferenceFragment() {
|
||||
|
||||
@ -36,9 +34,4 @@ class AccountRefreshSettingsFragment : BaseAccountPreferenceFragment() {
|
||||
override val switchPreferenceKey: String?
|
||||
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.JobService
|
||||
import android.os.Build
|
||||
import org.mariotaku.abstask.library.AbstractTask
|
||||
import android.util.Log
|
||||
import org.mariotaku.abstask.library.TaskStarter
|
||||
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.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.dagger.GeneralComponentHelper
|
||||
import javax.inject.Inject
|
||||
@ -59,10 +55,16 @@ class JobRefreshService : JobService() {
|
||||
// Low battery, don't refresh
|
||||
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 = {
|
||||
this.jobFinished(params, true)
|
||||
this.jobFinished(params, false)
|
||||
}
|
||||
TaskStarter.execute(task)
|
||||
return true
|
||||
@ -72,30 +74,23 @@ class JobRefreshService : JobService() {
|
||||
return false
|
||||
}
|
||||
|
||||
internal fun createJobTask(params: JobParameters): AbstractTask<*, *, () -> Unit>? {
|
||||
when (params.extras?.getString(EXTRA_ACTION)) {
|
||||
BROADCAST_REFRESH_HOME_TIMELINE -> {
|
||||
val task = GetHomeTimelineTask(this)
|
||||
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshHomeTimelineEnabled) { accountKeys ->
|
||||
DataStoreUtils.getNewestStatusIds(this, Statuses.CONTENT_URI, accountKeys)
|
||||
}
|
||||
return task
|
||||
}
|
||||
BROADCAST_REFRESH_NOTIFICATIONS -> {
|
||||
val task = GetActivitiesAboutMeTask(this)
|
||||
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
|
||||
DataStoreUtils.getNewestActivityMaxPositions(this, Activities.AboutMe.CONTENT_URI, accountKeys)
|
||||
}
|
||||
return task
|
||||
}
|
||||
BROADCAST_REFRESH_DIRECT_MESSAGES -> {
|
||||
val task = GetReceivedDirectMessagesTask(this)
|
||||
task.params = RefreshService.AutoRefreshTaskParam(this, AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
|
||||
DataStoreUtils.getNewestMessageIds(this, DirectMessages.Inbox.CONTENT_URI, accountKeys)
|
||||
}
|
||||
return task
|
||||
}
|
||||
companion object {
|
||||
const val ID_REFRESH_HOME_TIMELINE = 1
|
||||
const val ID_REFRESH_NOTIFICATIONS = 2
|
||||
const val ID_REFRESH_DIRECT_MESSAGES = 3
|
||||
|
||||
fun getJobId(@AutoRefreshType type: String): Int = when (type) {
|
||||
AutoRefreshType.HOME_TIMELINE -> JobRefreshService.ID_REFRESH_HOME_TIMELINE
|
||||
AutoRefreshType.INTERACTIONS_TIMELINE -> JobRefreshService.ID_REFRESH_NOTIFICATIONS
|
||||
AutoRefreshType.DIRECT_MESSAGES -> JobRefreshService.ID_REFRESH_DIRECT_MESSAGES
|
||||
else -> 0
|
||||
}
|
||||
|
||||
fun getRefreshType(jobId: Int): String? = when (jobId) {
|
||||
JobRefreshService.ID_REFRESH_HOME_TIMELINE -> AutoRefreshType.HOME_TIMELINE
|
||||
JobRefreshService.ID_REFRESH_NOTIFICATIONS -> AutoRefreshType.INTERACTIONS_TIMELINE
|
||||
JobRefreshService.ID_REFRESH_DIRECT_MESSAGES -> AutoRefreshType.DIRECT_MESSAGES
|
||||
else -> null
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
@ -19,269 +19,53 @@
|
||||
|
||||
package org.mariotaku.twidere.service
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.IBinder
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import edu.tsinghua.hotmobi.model.BatteryRecord
|
||||
import edu.tsinghua.hotmobi.model.ScreenEvent
|
||||
import org.apache.commons.lang3.math.NumberUtils
|
||||
import org.mariotaku.twidere.BuildConfig
|
||||
import org.mariotaku.twidere.Constants
|
||||
import org.mariotaku.abstask.library.AbstractTask
|
||||
import org.mariotaku.ktextension.convert
|
||||
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||
import org.mariotaku.twidere.annotation.AutoRefreshType
|
||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.*
|
||||
import org.mariotaku.twidere.model.AccountPreferences
|
||||
import org.mariotaku.twidere.model.SimpleRefreshTaskParam
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||
import org.mariotaku.twidere.receiver.PowerStateReceiver
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper
|
||||
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.SharedPreferencesWrapper
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
class RefreshService : Service(), Constants {
|
||||
class RefreshService : Service() {
|
||||
|
||||
@Inject
|
||||
internal lateinit var preferences: SharedPreferencesWrapper
|
||||
@Inject
|
||||
internal lateinit var twitterWrapper: AsyncTwitterWrapper
|
||||
|
||||
private lateinit var alarmManager: AlarmManager
|
||||
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 onBind(intent: Intent): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
GeneralComponentHelper.build(this).inject(this)
|
||||
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
pendingRefreshHomeTimelineIntent = PendingIntent.getBroadcast(this, 0, Intent(
|
||||
BROADCAST_REFRESH_HOME_TIMELINE), 0)
|
||||
pendingRefreshMentionsIntent = PendingIntent.getBroadcast(this, 0, Intent(BROADCAST_REFRESH_NOTIFICATIONS), 0)
|
||||
pendingRefreshDirectMessagesIntent = PendingIntent.getBroadcast(this, 0, Intent(
|
||||
BROADCAST_REFRESH_DIRECT_MESSAGES), 0)
|
||||
pendingRefreshTrendsIntent = PendingIntent.getBroadcast(this, 0, Intent(BROADCAST_REFRESH_TRENDS), 0)
|
||||
val refreshFilter = IntentFilter(BROADCAST_NOTIFICATION_DELETED)
|
||||
refreshFilter.addAction(BROADCAST_REFRESH_HOME_TIMELINE)
|
||||
refreshFilter.addAction(BROADCAST_REFRESH_NOTIFICATIONS)
|
||||
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()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Log.d(LOGTAG, "onStartCommand ${intent?.action}")
|
||||
val task = run {
|
||||
val type = intent?.action?.convert { getRefreshType(it) } ?: return@run null
|
||||
return@run createJobTask(this, type)
|
||||
} ?: run {
|
||||
stopSelfResult(startId)
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
task.callback = {
|
||||
stopSelfResult(startId)
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
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)
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
class AutoRefreshTaskParam(
|
||||
@ -301,4 +85,49 @@ class RefreshService : Service(), Constants {
|
||||
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.twidere.BuildConfig
|
||||
import org.mariotaku.twidere.Constants
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
||||
import org.mariotaku.twidere.model.DefaultFeatures
|
||||
import org.mariotaku.twidere.util.*
|
||||
@ -228,6 +229,14 @@ class ApplicationModule(private val application: Application) {
|
||||
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
|
||||
@Singleton
|
||||
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"?>
|
||||
<resources>
|
||||
<!--<bool name="use_job_refresh_service">true</bool>-->
|
||||
<!--<bool name="use_legacy_refresh_service">false</bool>-->
|
||||
<bool name="use_job_refresh_service">true</bool>
|
||||
<bool name="use_legacy_refresh_service">false</bool>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user