This commit is contained in:
Mariotaku Lee 2017-01-05 21:08:49 +08:00
parent 55b1631136
commit 5afc2855b5
20 changed files with 145 additions and 126 deletions

View File

@ -72,11 +72,6 @@ public interface IntentConstants {
String BROADCAST_NOTIFICATION_DELETED = INTENT_PACKAGE_PREFIX + "NOTIFICATION_DELETED";
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";
String EXTRA_URI = "uri";

View File

@ -482,11 +482,11 @@
</activity>
<service
android:name=".service.RefreshService"
android:name=".service.LegacyTaskService"
android:enabled="@bool/use_legacy_refresh_service"
android:label="@string/label_refresh_service"/>
<service
android:name=".service.JobRefreshService"
android:name=".service.JobTaskService"
android:enabled="@bool/use_job_refresh_service"
android:exported="true"
android:label="@string/label_refresh_service"
@ -495,7 +495,7 @@
android:name=".service.StreamingService"
android:label="@string/label_streaming_service"/>
<service
android:name=".service.BackgroundOperationService"
android:name=".service.LengthyOperationsService"
android:label="@string/label_background_operation_service"/>
<service
android:name=".service.AccountAuthenticatorService"

View File

@ -88,6 +88,7 @@ import org.mariotaku.twidere.model.DraftCursorIndices;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices;
import org.mariotaku.twidere.model.ParcelableDirectMessageCursorIndices;
import org.mariotaku.twidere.model.ParcelableStatusCursorIndices;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.SpanItem;
import org.mariotaku.twidere.model.StringLongPair;
@ -113,7 +114,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.provider.TwidereDataStore.Suggestions;
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
import org.mariotaku.twidere.receiver.NotificationReceiver;
import org.mariotaku.twidere.service.BackgroundOperationService;
import org.mariotaku.twidere.service.LengthyOperationsService;
import org.mariotaku.twidere.util.ActivityTracker;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.DataStoreFunctionsKt;
@ -561,14 +562,14 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
nb.setAutoCancel(true);
nb.setWhen(System.currentTimeMillis());
nb.setSmallIcon(R.drawable.ic_stat_draft);
final Intent discardIntent = new Intent(context, BackgroundOperationService.class);
final Intent discardIntent = new Intent(context, LengthyOperationsService.class);
discardIntent.setAction(INTENT_ACTION_DISCARD_DRAFT);
final Uri draftUri = Uri.withAppendedPath(Drafts.CONTENT_URI, String.valueOf(draftId));
discardIntent.setData(draftUri);
nb.addAction(R.drawable.ic_action_delete, context.getString(R.string.discard), PendingIntent.getService(context, 0,
discardIntent, PendingIntent.FLAG_ONE_SHOT));
final Intent sendIntent = new Intent(context, BackgroundOperationService.class);
final Intent sendIntent = new Intent(context, LengthyOperationsService.class);
sendIntent.setAction(INTENT_ACTION_SEND_DRAFT);
sendIntent.setData(draftUri);
nb.addAction(R.drawable.ic_action_send, context.getString(R.string.action_send),
@ -1254,7 +1255,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
Statuses.TABLE_NAME, selection).getSQL();
final String[] selectionArgs = {accountKey.toString()};
final String[] userProjection = {Statuses.USER_KEY, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
final String[] statusProjection = {Statuses.STATUS_ID};
final String[] statusProjection = {Statuses.POSITION_KEY};
final Cursor statusCursor = mDatabaseWrapper.query(Statuses.TABLE_NAME, statusProjection,
filteredSelection, selectionArgs, null, null, Statuses.DEFAULT_SORT_ORDER);
final Cursor userCursor = mDatabaseWrapper.query(Statuses.TABLE_NAME, userProjection,
@ -1264,24 +1265,22 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
final int usersCount = userCursor.getCount();
final int statusesCount = statusCursor.getCount();
if (statusesCount == 0 || usersCount == 0) return;
final int idxStatusId = statusCursor.getColumnIndex(Statuses.STATUS_ID),
idxUserName = userCursor.getColumnIndex(Statuses.USER_NAME),
idxUserScreenName = userCursor.getColumnIndex(Statuses.USER_NAME),
idxUserId = userCursor.getColumnIndex(Statuses.USER_NAME);
final long statusId = statusCursor.moveToFirst() ? statusCursor.getLong(idxStatusId) : -1;
final ParcelableStatusCursorIndices statusIndices = new ParcelableStatusCursorIndices(statusCursor),
userIndices = new ParcelableStatusCursorIndices(userCursor);
final long positionKey = statusCursor.moveToFirst() ? statusCursor.getLong(statusIndices.position_key) : -1;
final String notificationTitle = resources.getQuantityString(R.plurals.N_new_statuses,
statusesCount, statusesCount);
final String notificationContent;
userCursor.moveToFirst();
final String displayName = mUserColorNameManager.getDisplayName(userCursor.getString(idxUserId),
userCursor.getString(idxUserName), userCursor.getString(idxUserScreenName),
final String displayName = mUserColorNameManager.getDisplayName(userCursor.getString(userIndices.user_key),
userCursor.getString(userIndices.user_name), userCursor.getString(userIndices.user_screen_name),
mNameFirst);
if (usersCount == 1) {
notificationContent = context.getString(R.string.from_name, displayName);
} else if (usersCount == 2) {
userCursor.moveToPosition(1);
final String othersName = mUserColorNameManager.getDisplayName(userCursor.getString(idxUserId),
userCursor.getString(idxUserName), userCursor.getString(idxUserScreenName),
final String othersName = mUserColorNameManager.getDisplayName(userCursor.getString(userIndices.user_key),
userCursor.getString(userIndices.user_name), userCursor.getString(userIndices.user_screen_name),
mNameFirst);
notificationContent = resources.getString(R.string.from_name_and_name, displayName, othersName);
} else {
@ -1297,9 +1296,9 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
builder.setContentText(notificationContent);
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
builder.setContentIntent(getContentIntent(context, CustomTabType.HOME_TIMELINE,
NotificationType.HOME_TIMELINE, accountKey, statusId));
NotificationType.HOME_TIMELINE, accountKey, positionKey));
builder.setDeleteIntent(getMarkReadDeleteIntent(context, NotificationType.HOME_TIMELINE,
accountKey, statusId, false));
accountKey, positionKey, false));
builder.setNumber(statusesCount);
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
applyNotificationPreferences(builder, pref, pref.getHomeTimelineNotificationType());

View File

@ -92,7 +92,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Inbox;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Outbox;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.service.BackgroundOperationService;
import org.mariotaku.twidere.service.LengthyOperationsService;
import org.mariotaku.twidere.task.AcceptFriendshipTask;
import org.mariotaku.twidere.task.AddUserListMembersTask;
import org.mariotaku.twidere.task.CreateFriendshipTask;
@ -483,7 +483,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
public int sendDirectMessageAsync(final UserKey accountKey, final String recipientId, final String text,
final String imageUri) {
final Intent intent = new Intent(context, BackgroundOperationService.class);
final Intent intent = new Intent(context, LengthyOperationsService.class);
intent.setAction(INTENT_ACTION_SEND_DIRECT_MESSAGE);
intent.putExtra(EXTRA_ACCOUNT_KEY, accountKey);
intent.putExtra(EXTRA_RECIPIENT_ID, recipientId);

View File

@ -403,7 +403,7 @@ public final class Utils implements Constants {
public static String getReadPositionTagWithAccount(@NonNull final String tag,
@Nullable final UserKey accountKey) {
if (accountKey == null) return tag;
return tag + "_" + accountKey;
return accountKey + ":" + tag;
}
public static ParcelableDirectMessage findDirectMessageInDatabases(final Context context,

View File

@ -25,3 +25,35 @@ fun <T> Cursor.map(indices: ObjectCursor.CursorIndices<T>): List<T> {
}
return list
}
/**
* Executes the given [block] function on this resource and then closes it down correctly whether an exception
* is thrown or not.
*
* @param block a function to process this closable resource.
* @return the result of [block] function on this closable resource.
*/
inline fun <R> Cursor.useCursor(block: (Cursor) -> R): R {
var closed = false
try {
return block(this)
} catch (e: Exception) {
closed = true
try {
this?.close()
} catch (closeException: Exception) {
// eat the closeException as we are already throwing the original cause
// and we don't want to mask the real exception
// TODO on Java 7 we should call
// e.addSuppressed(closeException)
// to work like try-with-resources
// http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html#suppressed-exceptions
}
throw e
} finally {
if (!closed) {
this?.close()
}
}
}

View File

@ -84,7 +84,7 @@ import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.ParcelableLocationUtils
import org.mariotaku.twidere.preference.ServicePickerPreference
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts
import org.mariotaku.twidere.service.BackgroundOperationService
import org.mariotaku.twidere.service.LengthyOperationsService
import org.mariotaku.twidere.text.MarkForDeleteSpan
import org.mariotaku.twidere.text.style.EmojiSpan
import org.mariotaku.twidere.util.*
@ -1315,7 +1315,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
update.in_reply_to_status = inReplyToStatus
update.is_possibly_sensitive = isPossiblySensitive
update.attachment_url = (draft?.action_extras as? UpdateStatusActionExtras)?.attachmentUrl
BackgroundOperationService.updateStatusesAsync(this, action, update)
LengthyOperationsService.updateStatusesAsync(this, action, update)
if (preferences[noCloseAfterTweetSentKey] && inReplyToStatus == null) {
possiblySensitive = false
shouldSaveAccounts = true

View File

@ -53,6 +53,7 @@ import org.mariotaku.twidere.util.content.TwidereSQLiteOpenHelper
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.util.media.TwidereMediaDownloader
import org.mariotaku.twidere.util.net.TwidereDns
import org.mariotaku.twidere.util.refresh.AutoRefreshController
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -204,7 +205,7 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
private val sharedPreferences: SharedPreferences by lazy {
val prefs = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
prefs.registerOnSharedPreferenceChangeListener(this)
prefs
return@lazy prefs
}
override fun onTrimMemory(level: Int) {

View File

@ -61,7 +61,7 @@ import org.mariotaku.twidere.model.ParcelableMediaUpdate
import org.mariotaku.twidere.model.draft.SendDirectMessageActionExtras
import org.mariotaku.twidere.model.util.ParcelableStatusUpdateUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts
import org.mariotaku.twidere.service.BackgroundOperationService
import org.mariotaku.twidere.service.LengthyOperationsService
import org.mariotaku.twidere.util.AsyncTaskUtils
import org.mariotaku.twidere.util.JsonSerializer
import org.mariotaku.twidere.util.Utils.getDefaultTextSize
@ -214,7 +214,7 @@ class DraftsFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, OnItemCl
}
when (item.action_type) {
Draft.Action.UPDATE_STATUS_COMPAT_1, Draft.Action.UPDATE_STATUS_COMPAT_2, Draft.Action.UPDATE_STATUS, Draft.Action.REPLY, Draft.Action.QUOTE -> {
BackgroundOperationService.updateStatusesAsync(context, item.action_type,
LengthyOperationsService.updateStatusesAsync(context, item.action_type,
ParcelableStatusUpdateUtils.fromDraftItem(activity, item))
}
Draft.Action.SEND_DIRECT_MESSAGE_COMPAT, Draft.Action.SEND_DIRECT_MESSAGE -> {

View File

@ -46,7 +46,7 @@ import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.ParcelableStatusUpdate
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.service.BackgroundOperationService
import org.mariotaku.twidere.service.LengthyOperationsService
import org.mariotaku.twidere.util.Analyzer
import org.mariotaku.twidere.util.EditTextEnterHandler
import org.mariotaku.twidere.util.LinkCreator
@ -249,7 +249,7 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
}
update.text = commentText
update.is_possibly_sensitive = status.is_possibly_sensitive
BackgroundOperationService.updateStatusesAsync(context, Draft.Action.QUOTE, update)
LengthyOperationsService.updateStatusesAsync(context, Draft.Action.QUOTE, update)
} else {
twitter.retweetStatusAsync(status.account_key, status.id)
}

View File

@ -40,7 +40,7 @@ import javax.inject.Inject
*/
@SuppressLint("Registered")
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class JobRefreshService : JobService() {
class JobTaskService : JobService() {
@Inject
internal lateinit var preferences: KPreferences
@ -61,7 +61,7 @@ class JobRefreshService : JobService() {
val task = run {
val type = getRefreshType(params.jobId) ?: return@run null
return@run RefreshService.createJobTask(this, type)
return@run LegacyTaskService.createJobTask(this, type)
} ?: return false
task.callback = {
this.jobFinished(params, false)
@ -75,21 +75,22 @@ class JobRefreshService : JobService() {
}
companion object {
const val ID_REFRESH_HOME_TIMELINE = 1
const val ID_REFRESH_NOTIFICATIONS = 2
const val ID_REFRESH_DIRECT_MESSAGES = 3
const val JOB_ID_REFRESH_HOME_TIMELINE = 1
const val JOB_ID_REFRESH_NOTIFICATIONS = 2
const val JOB_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
AutoRefreshType.HOME_TIMELINE -> JOB_ID_REFRESH_HOME_TIMELINE
AutoRefreshType.INTERACTIONS_TIMELINE -> JOB_ID_REFRESH_NOTIFICATIONS
AutoRefreshType.DIRECT_MESSAGES -> JOB_ID_REFRESH_DIRECT_MESSAGES
else -> 0
}
@LegacyTaskService.Action
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
JOB_ID_REFRESH_HOME_TIMELINE -> LegacyTaskService.ACTION_REFRESH_HOME_TIMELINE
JOB_ID_REFRESH_NOTIFICATIONS -> LegacyTaskService.ACTION_REFRESH_NOTIFICATIONS
JOB_ID_REFRESH_DIRECT_MESSAGES -> LegacyTaskService.ACTION_REFRESH_DIRECT_MESSAGES
else -> null
}
}

View File

@ -23,10 +23,11 @@ import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import android.support.annotation.StringDef
import org.mariotaku.abstask.library.AbstractTask
import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.twidere.annotation.AutoRefreshType
import org.mariotaku.twidere.constant.IntentConstants.*
import org.mariotaku.twidere.constant.IntentConstants.INTENT_PACKAGE_PREFIX
import org.mariotaku.twidere.model.AccountPreferences
import org.mariotaku.twidere.model.SimpleRefreshTaskParam
import org.mariotaku.twidere.model.UserKey
@ -39,7 +40,7 @@ import org.mariotaku.twidere.util.SharedPreferencesWrapper
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import javax.inject.Inject
class RefreshService : Service() {
class LegacyTaskService : Service() {
@Inject
internal lateinit var preferences: SharedPreferencesWrapper
@ -54,8 +55,7 @@ class RefreshService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val task = run {
val action = intent?.action ?: return@run null
val type = getRefreshType(action) ?: return@run null
return@run createJobTask(this, type)
return@run createJobTask(this, action)
} ?: run {
stopSelfResult(startId)
return START_NOT_STICKY
@ -84,25 +84,37 @@ class RefreshService : Service() {
get() = getSinceIds(accountKeys)
}
companion object {
@StringDef(ACTION_REFRESH_HOME_TIMELINE, ACTION_REFRESH_NOTIFICATIONS,
ACTION_REFRESH_DIRECT_MESSAGES, ACTION_REFRESH_TRENDS)
annotation class Action
fun createJobTask(context: Context, @AutoRefreshType refreshType: String): AbstractTask<*, *, () -> Unit>? {
when (refreshType) {
AutoRefreshType.HOME_TIMELINE -> {
companion object {
@Action
const val ACTION_REFRESH_HOME_TIMELINE = INTENT_PACKAGE_PREFIX + "REFRESH_HOME_TIMELINE"
@Action
const val ACTION_REFRESH_NOTIFICATIONS = INTENT_PACKAGE_PREFIX + "REFRESH_NOTIFICATIONS"
@Action
const val ACTION_REFRESH_DIRECT_MESSAGES = INTENT_PACKAGE_PREFIX + "REFRESH_DIRECT_MESSAGES"
@Action
const val ACTION_REFRESH_TRENDS = INTENT_PACKAGE_PREFIX + "REFRESH_TRENDS"
fun createJobTask(context: Context, @Action action: String): AbstractTask<*, *, () -> Unit>? {
when (action) {
ACTION_REFRESH_HOME_TIMELINE -> {
val task = GetHomeTimelineTask(context)
task.params = AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshHomeTimelineEnabled) { accountKeys ->
DataStoreUtils.getNewestStatusIds(context, Statuses.CONTENT_URI, accountKeys)
}
return task
}
AutoRefreshType.INTERACTIONS_TIMELINE -> {
ACTION_REFRESH_NOTIFICATIONS -> {
val task = GetActivitiesAboutMeTask(context)
task.params = AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshMentionsEnabled) { accountKeys ->
DataStoreUtils.getNewestActivityMaxPositions(context, Activities.AboutMe.CONTENT_URI, accountKeys)
}
return task
}
AutoRefreshType.DIRECT_MESSAGES -> {
ACTION_REFRESH_DIRECT_MESSAGES -> {
val task = GetReceivedDirectMessagesTask(context)
task.params = AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
DataStoreUtils.getNewestMessageIds(context, DirectMessages.Inbox.CONTENT_URI, accountKeys)
@ -113,14 +125,6 @@ class RefreshService : Service() {
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

View File

@ -20,6 +20,7 @@
package org.mariotaku.twidere.service
import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.app.Notification
import android.app.Service
import android.content.ContentValues
@ -45,6 +46,7 @@ import org.mariotaku.abstask.library.ManualTaskStarter
import org.mariotaku.ktextension.configure
import org.mariotaku.ktextension.toLong
import org.mariotaku.ktextension.toTypedArray
import org.mariotaku.ktextension.useCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.TwitterUpload
@ -74,7 +76,10 @@ import java.io.File
import java.io.IOException
import java.util.concurrent.TimeUnit
class BackgroundOperationService : BaseIntentService("background_operation") {
/**
* Intent service for lengthy operations like update status/send DM.
*/
class LengthyOperationsService : BaseIntentService("lengthy_operations") {
private val handler: Handler by lazy { Handler(Looper.getMainLooper()) }
@ -83,26 +88,6 @@ class BackgroundOperationService : BaseIntentService("background_operation") {
return Service.START_STICKY
}
fun showErrorMessage(message: CharSequence, longMessage: Boolean) {
handler.post { Utils.showErrorMessage(this@BackgroundOperationService, message, longMessage) }
}
fun showErrorMessage(actionRes: Int, e: Exception?, longMessage: Boolean) {
handler.post { Utils.showErrorMessage(this@BackgroundOperationService, actionRes, e, longMessage) }
}
fun showErrorMessage(actionRes: Int, message: String, longMessage: Boolean) {
handler.post { Utils.showErrorMessage(this@BackgroundOperationService, actionRes, message, longMessage) }
}
fun showOkMessage(messageRes: Int, longMessage: Boolean) {
showToast(getString(messageRes), longMessage)
}
private fun showToast(message: CharSequence, longMessage: Boolean) {
handler.post { Toast.makeText(this@BackgroundOperationService, message, if (longMessage) Toast.LENGTH_LONG else Toast.LENGTH_SHORT).show() }
}
override fun onHandleIntent(intent: Intent?) {
if (intent == null) return
val action = intent.action ?: return
@ -122,23 +107,28 @@ class BackgroundOperationService : BaseIntentService("background_operation") {
}
}
private fun showErrorMessage(actionRes: Int, e: Exception?, longMessage: Boolean) {
handler.post { Utils.showErrorMessage(this@LengthyOperationsService, actionRes, e, longMessage) }
}
private fun showOkMessage(message: Int, longMessage: Boolean) {
handler.post { Toast.makeText(this@LengthyOperationsService, message, if (longMessage) Toast.LENGTH_LONG else Toast.LENGTH_SHORT).show() }
}
private fun handleSendDraftIntent(intent: Intent) {
val uri = intent.data ?: return
notificationManager.cancel(uri.toString(), NOTIFICATION_ID_DRAFTS)
val draftId = uri.lastPathSegment.toLong(-1)
if (draftId == -1L) return
val where = Expression.equals(Drafts._ID, draftId)
val cr = contentResolver
val c = cr.query(Drafts.CONTENT_URI, Drafts.COLUMNS, where.sql, null, null) ?: return
@Suppress("ConvertTryFinallyToUseCall")
val item: Draft = try {
val i = DraftCursorIndices(c)
if (!c.moveToFirst()) return
i.newObject(c)
} finally {
c.close()
}
cr.delete(Drafts.CONTENT_URI, where.sql, null)
@SuppressLint("Recycle")
val item: Draft = contentResolver.query(Drafts.CONTENT_URI, Drafts.COLUMNS, where.sql, null, null)?.useCursor {
val i = DraftCursorIndices(it)
if (!it.moveToFirst()) return@useCursor null
return@useCursor i.newObject(it)
} ?: return
contentResolver.delete(Drafts.CONTENT_URI, where.sql, null)
if (TextUtils.isEmpty(item.action_type)) {
item.action_type = Draft.Action.UPDATE_STATUS
}
@ -484,7 +474,7 @@ class BackgroundOperationService : BaseIntentService("background_operation") {
fun updateStatusesAsync(context: Context, @Draft.Action action: String,
vararg statuses: ParcelableStatusUpdate) {
val intent = Intent(context, BackgroundOperationService::class.java)
val intent = Intent(context, LengthyOperationsService::class.java)
intent.action = INTENT_ACTION_UPDATE_STATUS
intent.putExtra(EXTRA_STATUSES, statuses)
intent.putExtra(EXTRA_ACTION, action)

View File

@ -299,7 +299,8 @@ class StreamingService : Service() {
resolver.delete(Mentions.CONTENT_URI, where, whereArgs)
resolver.insert(Statuses.CONTENT_URI, values)
val rt = status.retweetedStatus
if (rt != null && rt.extendedText.contains("@" + account.user.screen_name) || rt == null && status.extendedText.contains("@" + account.user.screen_name)) {
if (rt != null && rt.extendedText.contains("@" + account.user.screen_name) ||
rt == null && status.extendedText.contains("@" + account.user.screen_name)) {
resolver.insert(Mentions.CONTENT_URI, values)
}
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.util.dagger
import android.app.Application
import android.content.Context
import android.os.Build
import android.os.Looper
import android.support.v4.text.BidiFormatter
import com.nostra13.universalimageloader.cache.disc.DiskCache
@ -52,6 +53,9 @@ import org.mariotaku.twidere.util.imageloader.URLFileNameGenerator
import org.mariotaku.twidere.util.media.TwidereMediaDownloader
import org.mariotaku.twidere.util.media.UILFileCache
import org.mariotaku.twidere.util.net.TwidereDns
import org.mariotaku.twidere.util.refresh.AutoRefreshController
import org.mariotaku.twidere.util.refresh.JobSchedulerAutoRefreshController
import org.mariotaku.twidere.util.refresh.LegacyAutoRefreshController
import java.io.IOException
import javax.inject.Singleton
@ -231,7 +235,8 @@ class ApplicationModule(private val application: Application) {
@Provides
fun autoRefreshController(kPreferences: KPreferences): AutoRefreshController {
if (application.resources.getBoolean(R.bool.use_job_refresh_service)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
application.resources.getBoolean(R.bool.use_job_refresh_service)) {
return JobSchedulerAutoRefreshController(application, kPreferences)
}
return LegacyAutoRefreshController(application, kPreferences)

View File

@ -37,8 +37,8 @@ import org.mariotaku.twidere.preference.KeyboardShortcutPreference
import org.mariotaku.twidere.provider.CacheProvider
import org.mariotaku.twidere.provider.TwidereDataProvider
import org.mariotaku.twidere.service.BaseIntentService
import org.mariotaku.twidere.service.JobRefreshService
import org.mariotaku.twidere.service.RefreshService
import org.mariotaku.twidere.service.JobTaskService
import org.mariotaku.twidere.service.LegacyTaskService
import org.mariotaku.twidere.task.*
import org.mariotaku.twidere.task.twitter.GetActivitiesTask
import org.mariotaku.twidere.task.twitter.GetStatusesTask
@ -62,7 +62,7 @@ interface GeneralComponent {
fun inject(obj: BaseDialogFragment)
fun inject(obj: RefreshService)
fun inject(obj: LegacyTaskService)
fun inject(obj: ComposeActivity)
@ -110,7 +110,7 @@ interface GeneralComponent {
fun inject(task: GetStatusesTask)
fun inject(service: JobRefreshService)
fun inject(service: JobTaskService)
fun inject(task: GetActivitiesTask)

View File

@ -1,4 +1,4 @@
package org.mariotaku.twidere.util
package org.mariotaku.twidere.util.refresh
import android.content.Context
import org.mariotaku.kpreferences.KPreferences

View File

@ -1,4 +1,4 @@
package org.mariotaku.twidere.util
package org.mariotaku.twidere.util.refresh
import android.annotation.TargetApi
import android.app.job.JobInfo
@ -9,7 +9,7 @@ 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 org.mariotaku.twidere.service.JobTaskService
import java.util.concurrent.TimeUnit
import android.Manifest.permission as AndroidPermissions
@ -22,16 +22,12 @@ class JobSchedulerAutoRefreshController(
context: Context,
kPreferences: KPreferences
) : AutoRefreshController(context, kPreferences) {
val scheduler: JobScheduler
init {
scheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
}
val scheduler: JobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
override fun appStarted() {
val allJobs = scheduler.allPendingJobs
AutoRefreshType.ALL.forEach { type ->
val jobId = JobRefreshService.getJobId(type)
val jobId = JobTaskService.getJobId(type)
if (allJobs.none { job -> job.id == jobId }) {
// Start non existing job
schedule(type)
@ -41,18 +37,18 @@ class JobSchedulerAutoRefreshController(
}
override fun schedule(@AutoRefreshType type: String) {
val jobId = JobRefreshService.getJobId(type)
val jobId = JobTaskService.getJobId(type)
scheduler.cancel(jobId)
scheduleJob(jobId)
}
override fun unschedule(type: String) {
val jobId = JobRefreshService.getJobId(type)
val jobId = JobTaskService.getJobId(type)
scheduler.cancel(jobId)
}
fun scheduleJob(jobId: Int, persisted: Boolean = true) {
val builder = JobInfo.Builder(jobId, ComponentName(context, JobRefreshService::class.java))
val builder = JobInfo.Builder(jobId, ComponentName(context, JobTaskService::class.java))
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
builder.setPeriodic(TimeUnit.MINUTES.toMillis(kPreferences[refreshIntervalKey]))
builder.setPersisted(persisted)

View File

@ -1,4 +1,4 @@
package org.mariotaku.twidere.util
package org.mariotaku.twidere.util.refresh
import android.app.AlarmManager
import android.app.PendingIntent
@ -9,7 +9,7 @@ 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 org.mariotaku.twidere.service.LegacyTaskService
import java.util.concurrent.TimeUnit
class LegacyAutoRefreshController(
@ -17,18 +17,13 @@ class LegacyAutoRefreshController(
kPreferences: KPreferences
) : AutoRefreshController(context, kPreferences) {
private val alarmManager: AlarmManager
private val pendingIntents: ArrayMap<String, PendingIntent>
private val alarmManager: AlarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
private val pendingIntents: ArrayMap<String, PendingIntent> = ArrayMap()
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)
val action = LegacyTaskService.getRefreshAction(type) ?: return@forEach
val intent = Intent(context, LegacyTaskService::class.java)
intent.action = action
pendingIntents[type] = PendingIntent.getService(context, 0, intent, 0)
}