Target SDK 26

* Broadcast restrictions
* Background restrictions
* Adaptive icon
pull/574/head
Alex Baker 7 years ago
parent ed295953f8
commit 8726855985

@ -8,9 +8,9 @@ android:
components: components:
- tools # https://github.com/travis-ci/travis-ci/issues/5049 - tools # https://github.com/travis-ci/travis-ci/issues/5049
- tools # https://github.com/travis-ci/travis-ci/issues/6040 - tools # https://github.com/travis-ci/travis-ci/issues/6040
- android-25 - android-26
- platform-tools - platform-tools
- build-tools-25.0.3 - build-tools-26.0.1
- extra-android-m2repository - extra-android-m2repository
- extra-google-m2repository - extra-google-m2repository
licenses: licenses:
@ -23,5 +23,5 @@ before_install:
- adb shell input keyevent 82 & - adb shell input keyevent 82 &
script: script:
- ./gradlew :app:lintGoogleplayDebug - ./gradlew :app:lintGoogleplayDebug
- ./gradlew :app:connectedGoogleplayDebugAndroidTest - ./gradlew :app:connectedGoogleplayDebugAndroidTest

@ -27,14 +27,14 @@ android {
textReport true textReport true
} }
compileSdkVersion 25 compileSdkVersion 26
buildToolsVersion "25.0.3" buildToolsVersion "26.0.1"
defaultConfig { defaultConfig {
applicationId "org.tasks" applicationId "org.tasks"
versionCode 458 versionCode 458
versionName "4.9.15" versionName "4.9.15"
targetSdkVersion 25 targetSdkVersion 26
minSdkVersion 15 minSdkVersion 15
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
@ -94,7 +94,7 @@ configurations {
final DAGGER_VERSION = '2.9' final DAGGER_VERSION = '2.9'
final BUTTERKNIFE_VERSION = '8.8.0' final BUTTERKNIFE_VERSION = '8.8.0'
final GPS_VERSION = '11.0.4' final GPS_VERSION = '11.0.4'
final SUPPORT_VERSION = '25.4.0' final SUPPORT_VERSION = '26.0.1'
final SUPPORT_ANNOTATIONS_VERSION = '26.0.0-alpha1' final SUPPORT_ANNOTATIONS_VERSION = '26.0.0-alpha1'
final STETHO_VERSION = '1.4.2' final STETHO_VERSION = '1.4.2'
final TESTING_SUPPORT_VERSION = '0.5' final TESTING_SUPPORT_VERSION = '0.5'

@ -12,6 +12,7 @@ import org.tasks.receivers.BootCompletedReceiver;
import org.tasks.receivers.CompleteTaskReceiver; import org.tasks.receivers.CompleteTaskReceiver;
import org.tasks.receivers.ListNotificationReceiver; import org.tasks.receivers.ListNotificationReceiver;
import org.tasks.receivers.MyPackageReplacedReceiver; import org.tasks.receivers.MyPackageReplacedReceiver;
import org.tasks.receivers.PushReceiver;
import org.tasks.receivers.TeslaUnreadReceiver; import org.tasks.receivers.TeslaUnreadReceiver;
import org.tasks.widget.TasksWidget; import org.tasks.widget.TasksWidget;
@ -44,4 +45,6 @@ public interface BroadcastComponent {
void inject(TasksWidget tasksWidget); void inject(TasksWidget tasksWidget);
void inject(TeslaUnreadReceiver teslaUnreadReceiver); void inject(TeslaUnreadReceiver teslaUnreadReceiver);
void inject(PushReceiver pushReceiver);
} }

@ -0,0 +1,27 @@
package org.tasks.receivers;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.data.Task;
import org.tasks.injection.BroadcastComponent;
import org.tasks.injection.InjectingBroadcastReceiver;
public class PushReceiver extends InjectingBroadcastReceiver {
public static void broadcast(Context context, Task task, ContentValues values) {
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
@Override
protected void inject(BroadcastComponent component) {
component.inject(this);
}
}

@ -16,7 +16,7 @@ import com.todoroo.astrid.test.DatabaseTestCase;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.Notifier; import org.tasks.Notifier;
import org.tasks.injection.TestComponent; import org.tasks.injection.TestComponent;
import org.tasks.notifications.NotificationManager; import org.tasks.notifications.NotificationManager;
@ -41,7 +41,7 @@ public class NotificationTests extends DatabaseTestCase {
@Module @Module
public static class NotificationTestsModule { public static class NotificationTestsModule {
private final NotificationManager notificationManager = mock(NotificationManager.class); private final NotificationManager notificationManager = mock(NotificationManager.class);
private final Broadcaster broadcaster = mock(Broadcaster.class); private final LocalBroadcastManager localBroadcastManager = mock(LocalBroadcastManager.class);
private final Context context; private final Context context;
public NotificationTestsModule(Context context) { public NotificationTestsModule(Context context) {
@ -54,8 +54,8 @@ public class NotificationTests extends DatabaseTestCase {
} }
@Provides @Provides
public Broadcaster getBroadcaster() { public LocalBroadcastManager getBroadcaster() {
return broadcaster; return localBroadcastManager;
} }
@Provides @Provides
@ -71,7 +71,7 @@ public class NotificationTests extends DatabaseTestCase {
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject NotificationManager notificationManager; @Inject NotificationManager notificationManager;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
@Inject Notifier notifier; @Inject Notifier notifier;
@Override @Override
@ -79,7 +79,7 @@ public class NotificationTests extends DatabaseTestCase {
super.tearDown(); super.tearDown();
verifyNoMoreInteractions(notificationManager); verifyNoMoreInteractions(notificationManager);
verifyNoMoreInteractions(broadcaster); verifyNoMoreInteractions(localBroadcastManager);
} }
@Test @Test

@ -12,7 +12,7 @@ import com.todoroo.astrid.test.DatabaseTestCase;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.data.TaskListDataProvider; import org.tasks.data.TaskListDataProvider;
import org.tasks.injection.TestComponent; import org.tasks.injection.TestComponent;
import org.tasks.makers.RemoteGtaskListMaker; import org.tasks.makers.RemoteGtaskListMaker;
@ -41,7 +41,7 @@ public class GtasksListServiceTest extends DatabaseTestCase {
@Inject TaskListDataProvider taskListDataProvider; @Inject TaskListDataProvider taskListDataProvider;
@Inject TaskDeleter taskDeleter; @Inject TaskDeleter taskDeleter;
@Inject MetadataDao metadataDao; @Inject MetadataDao metadataDao;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
private StoreObjectDao storeObjectDao; private StoreObjectDao storeObjectDao;
private GtasksListService gtasksListService; private GtasksListService gtasksListService;
@ -50,7 +50,8 @@ public class GtasksListServiceTest extends DatabaseTestCase {
public void setUp() { public void setUp() {
super.setUp(); super.setUp();
storeObjectDao = spy(new StoreObjectDao(database)); storeObjectDao = spy(new StoreObjectDao(database));
gtasksListService = new GtasksListService(storeObjectDao, taskListDataProvider, taskDeleter, metadataDao, broadcaster); gtasksListService = new GtasksListService(storeObjectDao, taskListDataProvider, taskDeleter,
metadataDao, localBroadcastManager);
} }
@Override @Override

@ -12,6 +12,7 @@ import org.tasks.receivers.BootCompletedReceiver;
import org.tasks.receivers.CompleteTaskReceiver; import org.tasks.receivers.CompleteTaskReceiver;
import org.tasks.receivers.ListNotificationReceiver; import org.tasks.receivers.ListNotificationReceiver;
import org.tasks.receivers.MyPackageReplacedReceiver; import org.tasks.receivers.MyPackageReplacedReceiver;
import org.tasks.receivers.PushReceiver;
import org.tasks.receivers.TeslaUnreadReceiver; import org.tasks.receivers.TeslaUnreadReceiver;
import org.tasks.widget.TasksWidget; import org.tasks.widget.TasksWidget;
@ -44,4 +45,6 @@ public interface BroadcastComponent {
void inject(TasksWidget tasksWidget); void inject(TasksWidget tasksWidget);
void inject(TeslaUnreadReceiver teslaUnreadReceiver); void inject(TeslaUnreadReceiver teslaUnreadReceiver);
void inject(PushReceiver pushReceiver);
} }

@ -0,0 +1,27 @@
package org.tasks.receivers;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.data.Task;
import org.tasks.injection.BroadcastComponent;
import org.tasks.injection.InjectingBroadcastReceiver;
public class PushReceiver extends InjectingBroadcastReceiver {
public static void broadcast(Context context, Task task, ContentValues values) {
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
@Override
protected void inject(BroadcastComponent component) {
component.inject(this);
}
}

@ -12,7 +12,7 @@ import com.todoroo.astrid.dao.StoreObjectDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.TaskDeleter; import com.todoroo.astrid.service.TaskDeleter;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.data.TaskListDataProvider; import org.tasks.data.TaskListDataProvider;
import java.util.HashSet; import java.util.HashSet;
@ -33,16 +33,17 @@ public class GtasksListService {
private final TaskListDataProvider taskListDataProvider; private final TaskListDataProvider taskListDataProvider;
private final TaskDeleter taskDeleter; private final TaskDeleter taskDeleter;
private final MetadataDao metadataDao; private final MetadataDao metadataDao;
private final Broadcaster broadcaster; private LocalBroadcastManager localBroadcastManager;
@Inject @Inject
public GtasksListService(StoreObjectDao storeObjectDao, TaskListDataProvider taskListDataProvider, public GtasksListService(StoreObjectDao storeObjectDao, TaskListDataProvider taskListDataProvider,
TaskDeleter taskDeleter, MetadataDao metadataDao, Broadcaster broadcaster) { TaskDeleter taskDeleter, MetadataDao metadataDao,
LocalBroadcastManager localBroadcastManager) {
this.storeObjectDao = storeObjectDao; this.storeObjectDao = storeObjectDao;
this.taskListDataProvider = taskListDataProvider; this.taskListDataProvider = taskListDataProvider;
this.taskDeleter = taskDeleter; this.taskDeleter = taskDeleter;
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.broadcaster = broadcaster; this.localBroadcastManager = localBroadcastManager;
} }
public List<GtasksList> getLists() { public List<GtasksList> getLists() {
@ -95,7 +96,7 @@ public class GtasksListService {
deleteList(storeObjectDao.getGtasksList(listId)); deleteList(storeObjectDao.getGtasksList(listId));
} }
broadcaster.refreshLists(); localBroadcastManager.broadcastRefreshList();
} }
public void deleteList(GtasksList gtasksList) { public void deleteList(GtasksList gtasksList) {

@ -8,7 +8,7 @@ import com.android.vending.billing.IabHelper;
import com.android.vending.billing.Inventory; import com.android.vending.billing.Inventory;
import com.android.vending.billing.Purchase; import com.android.vending.billing.Purchase;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
@ -26,17 +26,17 @@ public class InventoryHelper implements IabBroadcastReceiver.IabBroadcastListene
private final Context context; private final Context context;
private final Preferences preferences; private final Preferences preferences;
private final Broadcaster broadcaster; private final LocalBroadcastManager localBroadcastManager;
private final Executor executor; private final Executor executor;
private Inventory inventory; private Inventory inventory;
@Inject @Inject
public InventoryHelper(@ForApplication Context context, Preferences preferences, public InventoryHelper(@ForApplication Context context, Preferences preferences,
Broadcaster broadcaster, @Named("iab-executor") Executor executor) { LocalBroadcastManager localBroadcastManager, @Named("iab-executor") Executor executor) {
this.context = context; this.context = context;
this.preferences = preferences; this.preferences = preferences;
this.broadcaster = broadcaster; this.localBroadcastManager = localBroadcastManager;
this.executor = executor; this.executor = executor;
} }
@ -69,7 +69,7 @@ public class InventoryHelper implements IabBroadcastReceiver.IabBroadcastListene
checkPurchase(R.string.sku_tesla_unread, R.string.p_purchased_tesla_unread); checkPurchase(R.string.sku_tesla_unread, R.string.p_purchased_tesla_unread);
checkPurchase(R.string.sku_dashclock, R.string.p_purchased_dashclock); checkPurchase(R.string.sku_dashclock, R.string.p_purchased_dashclock);
checkPurchase(R.string.sku_themes, R.string.p_purchased_themes); checkPurchase(R.string.sku_themes, R.string.p_purchased_themes);
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} else { } else {
Timber.e("query inventory failed: %s", result.getMessage()); Timber.e("query inventory failed: %s", result.getMessage());
} }

@ -10,8 +10,8 @@ import com.android.vending.billing.IabResult;
import com.android.vending.billing.Purchase; import com.android.vending.billing.Purchase;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import org.tasks.Broadcaster;
import org.tasks.BuildConfig; import org.tasks.BuildConfig;
import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
@ -36,22 +36,23 @@ public class PurchaseHelper implements IabHelper.OnIabSetupFinishedListener {
private final Context context; private final Context context;
private final Preferences preferences; private final Preferences preferences;
private final Tracker tracker; private final Tracker tracker;
private final Broadcaster broadcaster;
private final InventoryHelper inventory; private final InventoryHelper inventory;
private final Executor executor; private final Executor executor;
private LocalBroadcastManager localBroadcastManager;
private PurchaseHelperCallback activityResultCallback; private PurchaseHelperCallback activityResultCallback;
private IabHelper iabHelper; private IabHelper iabHelper;
@Inject @Inject
public PurchaseHelper(@ForApplication Context context, Preferences preferences, Tracker tracker, public PurchaseHelper(@ForApplication Context context, Preferences preferences, Tracker tracker,
Broadcaster broadcaster, InventoryHelper inventory, @Named("iab-executor") Executor executor) { InventoryHelper inventory, @Named("iab-executor") Executor executor,
LocalBroadcastManager localBroadcastManager) {
this.context = context; this.context = context;
this.preferences = preferences; this.preferences = preferences;
this.tracker = tracker; this.tracker = tracker;
this.broadcaster = broadcaster;
this.inventory = inventory; this.inventory = inventory;
this.executor = executor; this.executor = executor;
this.localBroadcastManager = localBroadcastManager;
} }
@Override @Override
@ -150,7 +151,7 @@ public class PurchaseHelper implements IabHelper.OnIabSetupFinishedListener {
if (result1.isSuccess()) { if (result1.isSuccess()) {
if (!Strings.isNullOrEmpty(pref)) { if (!Strings.isNullOrEmpty(pref)) {
preferences.setBoolean(pref, true); preferences.setBoolean(pref, true);
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
inventory.refreshInventory(); inventory.refreshInventory();
} else if (result1.getResponse() != IabHelper.BILLING_RESPONSE_RESULT_USER_CANCELED && } else if (result1.getResponse() != IabHelper.BILLING_RESPONSE_RESULT_USER_CANCELED &&

@ -54,7 +54,7 @@ import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.gtasks.sync.GtasksTaskContainer; import com.todoroo.astrid.gtasks.sync.GtasksTaskContainer;
import com.todoroo.astrid.utility.Constants; import com.todoroo.astrid.utility.Constants;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.injection.InjectingAbstractThreadedSyncAdapter; import org.tasks.injection.InjectingAbstractThreadedSyncAdapter;
@ -90,7 +90,7 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
private static final String DEFAULT_LIST = "@default"; //$NON-NLS-1$ private static final String DEFAULT_LIST = "@default"; //$NON-NLS-1$
@Inject GtasksPreferenceService gtasksPreferenceService; @Inject GtasksPreferenceService gtasksPreferenceService;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
@Inject StoreObjectDao storeObjectDao; @Inject StoreObjectDao storeObjectDao;
@Inject GtasksSyncService gtasksSyncService; @Inject GtasksSyncService gtasksSyncService;
@Inject GtasksListService gtasksListService; @Inject GtasksListService gtasksListService;
@ -131,7 +131,7 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter
return; return;
} }
Timber.d("%s: start sync", account); Timber.d("%s: start sync", account);
RecordSyncStatusCallback callback = new RecordSyncStatusCallback(gtasksPreferenceService, broadcaster); RecordSyncStatusCallback callback = new RecordSyncStatusCallback(gtasksPreferenceService, localBroadcastManager);
try { try {
callback.started(); callback.started();
synchronize(); synchronize();

@ -13,6 +13,7 @@ import org.tasks.receivers.CompleteTaskReceiver;
import org.tasks.receivers.GoogleTaskPushReceiver; import org.tasks.receivers.GoogleTaskPushReceiver;
import org.tasks.receivers.ListNotificationReceiver; import org.tasks.receivers.ListNotificationReceiver;
import org.tasks.receivers.MyPackageReplacedReceiver; import org.tasks.receivers.MyPackageReplacedReceiver;
import org.tasks.receivers.PushReceiver;
import org.tasks.receivers.TeslaUnreadReceiver; import org.tasks.receivers.TeslaUnreadReceiver;
import org.tasks.widget.TasksWidget; import org.tasks.widget.TasksWidget;
@ -47,4 +48,6 @@ public interface BroadcastComponent {
void inject(TasksWidget tasksWidget); void inject(TasksWidget tasksWidget);
void inject(TeslaUnreadReceiver teslaUnreadReceiver); void inject(TeslaUnreadReceiver teslaUnreadReceiver);
void inject(PushReceiver pushReceiver);
} }

@ -51,7 +51,7 @@ public class GeofenceApi {
PendingResult<Status> result = LocationServices.GeofencingApi.addGeofences( PendingResult<Status> result = LocationServices.GeofencingApi.addGeofences(
client, client,
getRequests(geofences), getRequests(geofences),
PendingIntent.getService(context, 0, new Intent(context, GeofenceTransitionsIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT)); PendingIntent.getBroadcast(context, 0, new Intent(context, GeofenceTransitionsIntentService.Broadcast.class), PendingIntent.FLAG_UPDATE_CURRENT));
result.setResultCallback(status -> { result.setResultCallback(status -> {
if (status.isSuccess()) { if (status.isSuccess()) {
Timber.i("Registered %s", geofences); Timber.i("Registered %s", geofences);

@ -1,6 +1,9 @@
package org.tasks.location; package org.tasks.location;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v4.app.JobIntentService;
import com.google.android.gms.location.GeofencingEvent; import com.google.android.gms.location.GeofencingEvent;
import com.todoroo.astrid.dao.MetadataDao; import com.todoroo.astrid.dao.MetadataDao;
@ -8,8 +11,9 @@ import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
import org.tasks.Notifier; import org.tasks.Notifier;
import org.tasks.injection.InjectingIntentService; import org.tasks.injection.InjectingJobIntentService;
import org.tasks.injection.IntentServiceComponent; import org.tasks.injection.IntentServiceComponent;
import org.tasks.jobs.JobManager;
import java.util.List; import java.util.List;
@ -17,17 +21,21 @@ import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;
public class GeofenceTransitionsIntentService extends InjectingIntentService { public class GeofenceTransitionsIntentService extends InjectingJobIntentService {
public static class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
JobIntentService.enqueueWork(context, GeofenceTransitionsIntentService.class, JobManager.JOB_ID_GEOFENCE_TRANSITION, intent);
}
}
@Inject MetadataDao metadataDao; @Inject MetadataDao metadataDao;
@Inject Notifier notifier; @Inject Notifier notifier;
public GeofenceTransitionsIntentService() { @Override
super(GeofenceTransitionsIntentService.class.getSimpleName()); protected void onHandleWork(Intent intent) {
} super.onHandleWork(intent);
protected void onHandleIntent(Intent intent) {
super.onHandleIntent(intent);
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) { if (geofencingEvent.hasError()) {

@ -3,6 +3,7 @@ package org.tasks.receivers;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Parcelable;
import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.Property;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
@ -17,6 +18,13 @@ import javax.inject.Inject;
public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver { public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver {
public static void broadcast(Context context, Task task, ContentValues values) {
Intent intent = new Intent(context, GoogleTaskPushReceiver.class);
intent.putExtra(AstridApiConstants.EXTRAS_TASK, task);
intent.putExtra(AstridApiConstants.EXTRAS_VALUES, values);
context.sendBroadcast(intent);
}
private static final Property<?>[] TASK_PROPERTIES = { Task.ID, Task.TITLE, private static final Property<?>[] TASK_PROPERTIES = { Task.ID, Task.TITLE,
Task.NOTES, Task.DUE_DATE, Task.COMPLETION_DATE, Task.DELETION_DATE }; Task.NOTES, Task.DUE_DATE, Task.COMPLETION_DATE, Task.DELETION_DATE };

@ -0,0 +1,36 @@
package org.tasks.receivers;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.data.Task;
import org.tasks.injection.BroadcastComponent;
import org.tasks.injection.InjectingBroadcastReceiver;
public class PushReceiver extends InjectingBroadcastReceiver {
public static void broadcast(Context context, Task task, ContentValues values) {
Intent intent = new Intent(context, PushReceiver.class);
intent.putExtra(AstridApiConstants.EXTRAS_TASK, task);
intent.putExtra(AstridApiConstants.EXTRAS_VALUES, values);
context.sendBroadcast(intent);
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
GoogleTaskPushReceiver.broadcast(
context,
intent.getParcelableExtra(AstridApiConstants.EXTRAS_TASK),
intent.getParcelableExtra(AstridApiConstants.EXTRAS_VALUES));
}
@Override
protected void inject(BroadcastComponent component) {
component.inject(this);
}
}

@ -212,6 +212,8 @@
<!-- ======================================================= Receivers = --> <!-- ======================================================= Receivers = -->
<receiver android:name=".receivers.PushReceiver" />
<receiver <receiver
android:name=".receivers.ListNotificationReceiver" android:name=".receivers.ListNotificationReceiver"
android:exported="true" /> android:exported="true" />
@ -224,7 +226,6 @@
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.todoroo.astrid.widget.TasksWidget.COMPLETE_TASK"/> <action android:name="com.todoroo.astrid.widget.TasksWidget.COMPLETE_TASK"/>
<action android:name="com.todoroo.astrid.widget.TasksWidget.EDIT_TASK"/> <action android:name="com.todoroo.astrid.widget.TasksWidget.EDIT_TASK"/>
<action android:name="org.tasks.REFRESH"/>
</intent-filter> </intent-filter>
<meta-data <meta-data
@ -332,12 +333,7 @@
android:theme="@style/Tasks"/> android:theme="@style/Tasks"/>
<!-- alarms --> <!-- alarms -->
<receiver android:name="com.todoroo.astrid.alarms.AlarmTaskRepeatListener"> <receiver android:name="com.todoroo.astrid.alarms.AlarmTaskRepeatListener" />
<intent-filter>
<action android:name="org.tasks.TASK_REPEATED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- actfm --> <!-- actfm -->
@ -347,20 +343,10 @@
<!-- repeats --> <!-- repeats -->
<receiver android:name="com.todoroo.astrid.repeats.RepeatTaskCompleteListener"> <receiver android:name="com.todoroo.astrid.repeats.RepeatTaskCompleteListener" />
<intent-filter android:priority="1">
<action android:name="org.tasks.TASK_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- calendar --> <!-- calendar -->
<receiver android:name="com.todoroo.astrid.gcal.GCalTaskCompleteListener"> <receiver android:name="com.todoroo.astrid.gcal.GCalTaskCompleteListener" />
<intent-filter android:priority="2">
<action android:name="org.tasks.TASK_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity <activity
android:name=".activities.CalendarSelectionActivity" android:name=".activities.CalendarSelectionActivity"
@ -399,12 +385,7 @@
android:name=".files.FileExplore" android:name=".files.FileExplore"
android:theme="@style/TranslucentDialog"/> android:theme="@style/TranslucentDialog"/>
<receiver android:name="com.todoroo.astrid.timers.TimerTaskCompleteListener"> <receiver android:name="com.todoroo.astrid.timers.TimerTaskCompleteListener" />
<intent-filter>
<action android:name="org.tasks.TASK_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- reminders --> <!-- reminders -->
<activity <activity
@ -440,38 +421,57 @@
<service <service
android:name=".scheduling.GeofenceSchedulingIntentService" android:name=".scheduling.GeofenceSchedulingIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<service <service
android:name=".scheduling.SchedulerIntentService" android:name=".scheduling.SchedulerIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<service <service
android:name=".scheduling.NotificationSchedulerIntentService" android:name=".scheduling.NotificationSchedulerIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<receiver android:name=".scheduling.CalendarNotificationIntentService$Broadcast" />
<service <service
android:name=".scheduling.CalendarNotificationIntentService" android:name=".scheduling.CalendarNotificationIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<service
android:name=".jobs.AlarmJob" <receiver android:name=".jobs.BackupJob$Broadcast" />
android:exported="false" />
<service <service
android:name=".jobs.BackupJob" android:name=".jobs.BackupJob"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<receiver android:name=".jobs.MidnightRefreshJob$Broadcast" />
<service <service
android:name=".jobs.MidnightRefreshJob" android:name=".jobs.MidnightRefreshJob"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<receiver android:name=".jobs.RefreshJob$Broadcast" />
<service <service
android:name=".jobs.RefreshJob" android:name=".jobs.RefreshJob"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<receiver android:name=".jobs.AlarmJob$Broadcast" />
<service <service
android:name=".jobs.ReminderJob" android:name=".jobs.AlarmJob"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<receiver <receiver android:name=".jobs.ReminderJob$Broadcast" />
android:name=".jobs.AlarmJobBroadcast" <service
android:name=".jobs.ReminderJob"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<receiver <receiver android:name=".location.GeofenceTransitionsIntentService$Broadcast" />
android:name=".jobs.ReminderJobBroadcast" <service
android:name=".location.GeofenceTransitionsIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" /> android:exported="false" />
<!-- Uses Library --> <!-- Uses Library -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

@ -213,6 +213,10 @@ public class AndroidUtilities {
return !atLeastLollipop(); return !atLeastLollipop();
} }
public static boolean preJellybean() {
return !atLeastJellybean();
}
public static boolean atLeastJellybeanMR1() { public static boolean atLeastJellybeanMR1() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1; return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
} }
@ -233,6 +237,10 @@ public class AndroidUtilities {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
} }
public static boolean atLeastO() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}
/** /**
* Sleep, ignoring interruption. Before using this method, think carefully * Sleep, ignoring interruption. Before using this method, think carefully
* about why you are ignoring interruptions. * about why you are ignoring interruptions.
@ -275,19 +283,6 @@ public class AndroidUtilities {
} }
} }
/**
* Wraps a call to Activity.unregisterReceiver in a try/catch block to prevent
* exceptions being thrown if receiver was never registered with that activity
*/
public static void tryUnregisterReceiver(Activity activity, BroadcastReceiver receiver) {
try {
activity.unregisterReceiver(receiver);
} catch (IllegalArgumentException e) {
// Receiver wasn't registered for some reason
Timber.e(e, e.getMessage());
}
}
/** /**
* Returns the final word characters after the last '.' * Returns the final word characters after the last '.'
*/ */

@ -33,7 +33,7 @@ import com.todoroo.astrid.timers.TimerPlugin;
import com.todoroo.astrid.ui.EditTitleControlSet; import com.todoroo.astrid.ui.EditTitleControlSet;
import com.todoroo.astrid.utility.Flags; import com.todoroo.astrid.utility.Flags;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
@ -86,7 +86,7 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject Tracker tracker; @Inject Tracker tracker;
@Inject TimerPlugin timerPlugin; @Inject TimerPlugin timerPlugin;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
@BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.comments) LinearLayout comments; @BindView(R.id.comments) LinearLayout comments;
@ -212,7 +212,7 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
taskDao.save(model); taskDao.save(model);
if (Flags.check(Flags.TAGS_CHANGED)) { if (Flags.check(Flags.TAGS_CHANGED)) {
broadcaster.refreshLists(); localBroadcastManager.broadcastRefreshList();
} }
if (isNewTask) { if (isNewTask) {

@ -8,12 +8,9 @@ package com.todoroo.astrid.activity;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.view.ActionMode; import android.support.v7.view.ActionMode;
@ -22,7 +19,6 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.GtasksFilter; import com.todoroo.astrid.api.GtasksFilter;
@ -42,7 +38,7 @@ import com.todoroo.astrid.subtasks.SubtasksListFragment;
import com.todoroo.astrid.subtasks.SubtasksTagListFragment; import com.todoroo.astrid.subtasks.SubtasksTagListFragment;
import com.todoroo.astrid.timers.TimerControlSet; import com.todoroo.astrid.timers.TimerControlSet;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.activities.TagSettingsActivity; import org.tasks.activities.TagSettingsActivity;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
@ -95,12 +91,12 @@ public class TaskListActivity extends InjectingAppCompatActivity implements
@Inject GtasksListService gtasksListService; @Inject GtasksListService gtasksListService;
@Inject TagDataDao tagDataDao; @Inject TagDataDao tagDataDao;
@Inject Theme theme; @Inject Theme theme;
@Inject Broadcaster broadcaster;
@Inject ThemeCache themeCache; @Inject ThemeCache themeCache;
@Inject SyncAdapterHelper syncAdapterHelper; @Inject SyncAdapterHelper syncAdapterHelper;
@Inject Tracker tracker; @Inject Tracker tracker;
@Inject TaskCreator taskCreator; @Inject TaskCreator taskCreator;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject LocalBroadcastManager localBroadcastManager;
@BindView(R.id.drawer_layout) DrawerLayout drawerLayout; @BindView(R.id.drawer_layout) DrawerLayout drawerLayout;
@BindView(R.id.master) FrameLayout master; @BindView(R.id.master) FrameLayout master;
@ -262,9 +258,7 @@ public class TaskListActivity extends InjectingAppCompatActivity implements
return; return;
} }
registerReceiver( localBroadcastManager.registerRepeatReceiver(repeatConfirmationReceiver);
repeatConfirmationReceiver,
new IntentFilter(AstridApiConstants.BROADCAST_EVENT_TASK_REPEATED));
syncAdapterHelper.checkPlayServices(getTaskListFragment()); syncAdapterHelper.checkPlayServices(getTaskListFragment());
} }
@ -290,7 +284,7 @@ public class TaskListActivity extends InjectingAppCompatActivity implements
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
AndroidUtilities.tryUnregisterReceiver(this, repeatConfirmationReceiver); localBroadcastManager.unregisterReceiver(repeatConfirmationReceiver);
} }
@Override @Override
@ -493,7 +487,7 @@ public class TaskListActivity extends InjectingAppCompatActivity implements
@Override @Override
public void sortChanged() { public void sortChanged() {
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
reloadCurrentFilter(); reloadCurrentFilter();
} }

@ -9,7 +9,6 @@ import android.app.Activity;
import android.content.BroadcastReceiver; 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.database.Cursor; import android.database.Cursor;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
@ -32,9 +31,7 @@ import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.QueryTemplate; import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.adapter.TaskAdapter; import com.todoroo.astrid.adapter.TaskAdapter;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.CustomFilter; import com.todoroo.astrid.api.CustomFilter;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.core.BuiltInFilterExposer; import com.todoroo.astrid.core.BuiltInFilterExposer;
@ -46,7 +43,7 @@ import com.todoroo.astrid.service.TaskDuplicator;
import com.todoroo.astrid.timers.TimerPlugin; import com.todoroo.astrid.timers.TimerPlugin;
import com.todoroo.astrid.voice.VoiceInputAssistant; import com.todoroo.astrid.voice.VoiceInputAssistant;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.activities.FilterSettingsActivity; import org.tasks.activities.FilterSettingsActivity;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
@ -110,11 +107,11 @@ public class TaskListFragment extends InjectingFragment implements
@Inject CheckBoxes checkBoxes; @Inject CheckBoxes checkBoxes;
@Inject VoiceInputAssistant voiceInputAssistant; @Inject VoiceInputAssistant voiceInputAssistant;
@Inject TaskCreator taskCreator; @Inject TaskCreator taskCreator;
@Inject Broadcaster broadcaster;
@Inject protected TaskListDataProvider taskListDataProvider; @Inject protected TaskListDataProvider taskListDataProvider;
@Inject TimerPlugin timerPlugin; @Inject TimerPlugin timerPlugin;
@Inject ViewHolderFactory viewHolderFactory; @Inject ViewHolderFactory viewHolderFactory;
@Inject protected Tracker tracker; @Inject protected Tracker tracker;
@Inject LocalBroadcastManager localBroadcastManager;
@BindView(R.id.swipe_layout) SwipeRefreshLayout swipeRefreshLayout; @BindView(R.id.swipe_layout) SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.swipe_layout_empty) SwipeRefreshLayout emptyRefreshLayout; @BindView(R.id.swipe_layout_empty) SwipeRefreshLayout emptyRefreshLayout;
@ -288,13 +285,13 @@ public class TaskListFragment extends InjectingFragment implements
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
preferences.setBoolean(R.string.p_show_hidden_tasks, item.isChecked()); preferences.setBoolean(R.string.p_show_hidden_tasks, item.isChecked());
reconstructCursor(); reconstructCursor();
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
return true; return true;
case R.id.menu_show_completed: case R.id.menu_show_completed:
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
preferences.setBoolean(R.string.p_show_completed_tasks, item.isChecked()); preferences.setBoolean(R.string.p_show_completed_tasks, item.isChecked());
reconstructCursor(); reconstructCursor();
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
return true; return true;
case R.id.menu_filter_settings: case R.id.menu_filter_settings:
Intent intent = new Intent(getActivity(), FilterSettingsActivity.class); Intent intent = new Intent(getActivity(), FilterSettingsActivity.class);
@ -356,7 +353,7 @@ public class TaskListFragment extends InjectingFragment implements
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
getActivity().registerReceiver(refreshReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH)); localBroadcastManager.registerRefreshReceiver(refreshReceiver);
refresh(); refresh();
} }
@ -372,7 +369,7 @@ public class TaskListFragment extends InjectingFragment implements
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
AndroidUtilities.tryUnregisterReceiver(getActivity(), refreshReceiver); localBroadcastManager.unregisterReceiver(refreshReceiver);
} }
/** /**
@ -384,10 +381,6 @@ public class TaskListFragment extends InjectingFragment implements
protected class RefreshReceiver extends BroadcastReceiver { protected class RefreshReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (intent == null || !AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(intent.getAction())) {
return;
}
refresh(); refresh();
} }
} }

@ -9,7 +9,6 @@ import android.app.Activity;
import android.content.BroadcastReceiver; 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.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -19,7 +18,6 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.todoroo.astrid.activity.TaskListActivity; import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.CustomFilterActivity; import com.todoroo.astrid.core.CustomFilterActivity;
@ -74,6 +72,10 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
this.themeCache = themeCache; this.themeCache = themeCache;
} }
public FilterListUpdateReceiver getFilterListUpdateReceiver() {
return filterListUpdateReceiver;
}
@Override @Override
public boolean hasStableIds() { public boolean hasStableIds() {
return true; return true;
@ -268,22 +270,6 @@ public class FilterAdapter extends ArrayAdapter<FilterListItem> {
filterCounter.refreshFilterCounts(this::notifyDataSetChanged); filterCounter.refreshFilterCounts(this::notifyDataSetChanged);
} }
/**
* Call this method from your activity's onResume() method
*/
public void registerRecevier() {
activity.registerReceiver(filterListUpdateReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH));
populateList();
}
/**
* Call this method from your activity's onResume() method
*/
public void unregisterRecevier() {
activity.unregisterReceiver(filterListUpdateReceiver);
}
/* ====================================================================== /* ======================================================================
* ================================================================ views * ================================================================ views
* ====================================================================== */ * ====================================================================== */

@ -21,6 +21,14 @@ import javax.inject.Inject;
public class AlarmTaskRepeatListener extends InjectingBroadcastReceiver { public class AlarmTaskRepeatListener extends InjectingBroadcastReceiver {
public static void broadcast(Context context, long taskId, long oldDueDate, long newDueDate) {
Intent intent = new Intent(context, AlarmTaskRepeatListener.class);
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
intent.putExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, oldDueDate);
intent.putExtra(AstridApiConstants.EXTRAS_NEW_DUE_DATE, newDueDate);
context.sendBroadcast(intent);
}
@Inject AlarmService alarmService; @Inject AlarmService alarmService;
@Override @Override

@ -56,28 +56,4 @@ public class AstridApiConstants {
* Extras name for new task due date * Extras name for new task due date
*/ */
public static final String EXTRAS_NEW_DUE_DATE = "newDueDate"; public static final String EXTRAS_NEW_DUE_DATE = "newDueDate";
// --- Events API
/**
* Action name for broadcast intent notifying Astrid task list to refresh
*/
public static final String BROADCAST_EVENT_REFRESH = BuildConfig.APPLICATION_ID + ".REFRESH";
public static final String BROADCAST_EVENT_REFRESH_LISTS = BuildConfig.APPLICATION_ID + ".REFRESH_LISTS";
/**
* Action name for broadcast intent notifying that task was completed
* <li> EXTRAS_TASK_ID id of the task
*/
public static final String BROADCAST_EVENT_TASK_COMPLETED = BuildConfig.APPLICATION_ID + ".TASK_COMPLETED";
/**
* Action name for broadcast intent notifying that task was created from repeating template
* <li> EXTRAS_TASK_ID id of the task
* <li> EXTRAS_OLD_DUE_DATE task old due date (could be 0)
* <li> EXTRAS_NEW_DUE_DATE task new due date (will not be 0)
*/
public static final String BROADCAST_EVENT_TASK_REPEATED = BuildConfig.APPLICATION_ID + ".TASK_REPEATED";
public static final String BROADCAST_EVENT_TASK_SAVED = BuildConfig.APPLICATION_ID + ".TASK_SAVED";
} }

@ -30,6 +30,7 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.UserActivity; import com.todoroo.astrid.data.UserActivity;
import com.todoroo.astrid.tags.TaskToTagMetadata; import com.todoroo.astrid.tags.TaskToTagMetadata;
import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
@ -51,6 +52,7 @@ public class TasksXmlImporter {
private final UserActivityDao userActivityDao; private final UserActivityDao userActivityDao;
private final DialogBuilder dialogBuilder; private final DialogBuilder dialogBuilder;
private final TaskDao taskDao; private final TaskDao taskDao;
private LocalBroadcastManager localBroadcastManager;
private Activity activity; private Activity activity;
private Handler handler; private Handler handler;
@ -67,12 +69,13 @@ public class TasksXmlImporter {
@Inject @Inject
public TasksXmlImporter(TagDataDao tagDataDao, MetadataDao metadataDao, UserActivityDao userActivityDao, public TasksXmlImporter(TagDataDao tagDataDao, MetadataDao metadataDao, UserActivityDao userActivityDao,
DialogBuilder dialogBuilder, TaskDao taskDao) { DialogBuilder dialogBuilder, TaskDao taskDao, LocalBroadcastManager localBroadcastManager) {
this.tagDataDao = tagDataDao; this.tagDataDao = tagDataDao;
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.userActivityDao = userActivityDao; this.userActivityDao = userActivityDao;
this.dialogBuilder = dialogBuilder; this.dialogBuilder = dialogBuilder;
this.taskDao = taskDao; this.taskDao = taskDao;
this.localBroadcastManager = localBroadcastManager;
} }
public void importTasks(Activity activity, String input, ProgressDialog progressDialog) { public void importTasks(Activity activity, String input, ProgressDialog progressDialog) {
@ -120,8 +123,7 @@ public class TasksXmlImporter {
} }
} }
} finally { } finally {
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH); localBroadcastManager.broadcastRefresh();
activity.sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
handler.post(() -> { handler.post(() -> {
if(progressDialog.isShowing()) { if(progressDialog.isShowing()) {
DialogUtilities.dismissDialog(activity, progressDialog); DialogUtilities.dismissDialog(activity, progressDialog);

@ -6,6 +6,7 @@
package com.todoroo.astrid.dao; package com.todoroo.astrid.dao;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteConstraintException;
import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.AbstractModel;
@ -23,14 +24,19 @@ import com.todoroo.astrid.data.RemoteModel;
import com.todoroo.astrid.data.SyncFlags; import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.TaskApiDao; import com.todoroo.astrid.data.TaskApiDao;
import com.todoroo.astrid.gcal.GCalTaskCompleteListener;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
import com.todoroo.astrid.repeats.RepeatTaskCompleteListener;
import com.todoroo.astrid.timers.TimerTaskCompleteListener;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.injection.ForApplication;
import org.tasks.location.GeofenceService; import org.tasks.location.GeofenceService;
import org.tasks.notifications.NotificationManager; import org.tasks.notifications.NotificationManager;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.receivers.PushReceiver;
import org.tasks.scheduling.RefreshScheduler; import org.tasks.scheduling.RefreshScheduler;
import java.util.List; import java.util.List;
@ -52,26 +58,29 @@ public class TaskDao {
private final RemoteModelDao<Task> dao; private final RemoteModelDao<Task> dao;
private final RefreshScheduler refreshScheduler; private final RefreshScheduler refreshScheduler;
private final LocalBroadcastManager localBroadcastManager;
private final MetadataDao metadataDao; private final MetadataDao metadataDao;
private final Broadcaster broadcaster;
private final ReminderService reminderService; private final ReminderService reminderService;
private final NotificationManager notificationManager; private final NotificationManager notificationManager;
private final Preferences preferences; private final Preferences preferences;
private Context context;
private final GeofenceService geofenceService; private final GeofenceService geofenceService;
@Inject @Inject
public TaskDao(Database database, MetadataDao metadataDao, final Broadcaster broadcaster, public TaskDao(@ForApplication Context context, Database database, MetadataDao metadataDao,
ReminderService reminderService, NotificationManager notificationManager, ReminderService reminderService, NotificationManager notificationManager,
Preferences preferences, GeofenceService geofenceService, RefreshScheduler refreshScheduler) { Preferences preferences, GeofenceService geofenceService,
RefreshScheduler refreshScheduler, LocalBroadcastManager localBroadcastManager) {
this.context = context;
this.geofenceService = geofenceService; this.geofenceService = geofenceService;
this.preferences = preferences; this.preferences = preferences;
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.broadcaster = broadcaster;
this.reminderService = reminderService; this.reminderService = reminderService;
this.notificationManager = notificationManager; this.notificationManager = notificationManager;
dao = new RemoteModelDao<>(database, Task.class); dao = new RemoteModelDao<>(database, Task.class);
this.refreshScheduler = refreshScheduler; this.refreshScheduler = refreshScheduler;
this.localBroadcastManager = localBroadcastManager;
} }
public TodorooCursor<Task> query(Query query) { public TodorooCursor<Task> query(Query query) {
@ -206,7 +215,7 @@ public class TaskDao {
// delete all metadata // delete all metadata
metadataDao.deleteWhere(MetadataCriteria.byTask(id)); metadataDao.deleteWhere(MetadataCriteria.byTask(id));
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
return true; return true;
} }
@ -223,7 +232,7 @@ public class TaskDao {
if (modifiedValues != null) { if (modifiedValues != null) {
afterSave(task, modifiedValues); afterSave(task, modifiedValues);
} else if (task.checkTransitory(SyncFlags.FORCE_SYNC)) { } else if (task.checkTransitory(SyncFlags.FORCE_SYNC)) {
broadcaster.taskUpdated(task, null); PushReceiver.broadcast(context, task, null);
} }
} }
@ -427,17 +436,19 @@ public class TaskDao {
} }
if(values.containsKey(Task.COMPLETION_DATE.name) && task.isCompleted()) { if(values.containsKey(Task.COMPLETION_DATE.name) && task.isCompleted()) {
broadcaster.taskCompleted(task.getId()); RepeatTaskCompleteListener.broadcast(context, task.getId());
GCalTaskCompleteListener.broadcast(context, task.getId());
TimerTaskCompleteListener.broadcast(context, task.getId());
} }
broadcaster.taskUpdated(task, values); PushReceiver.broadcast(context, task, values);
refreshScheduler.scheduleRefresh(task); refreshScheduler.scheduleRefresh(task);
broadcastRefresh(task); broadcastRefresh(task);
} }
private void broadcastRefresh(Task task) { private void broadcastRefresh(Task task) {
if (!task.checkAndClearTransitory(TRANS_SUPPRESS_REFRESH)) { if (!task.checkAndClearTransitory(TRANS_SUPPRESS_REFRESH)) {
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
} }

@ -27,6 +27,12 @@ import timber.log.Timber;
public class GCalTaskCompleteListener extends InjectingBroadcastReceiver { public class GCalTaskCompleteListener extends InjectingBroadcastReceiver {
public static void broadcast(Context context, long taskId) {
Intent intent = new Intent(context, GCalTaskCompleteListener.class);
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
context.sendBroadcast(intent);
}
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Override @Override

@ -15,6 +15,7 @@ import android.preference.Preference;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.provider.Settings; import android.provider.Settings;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import org.tasks.R; import org.tasks.R;
import org.tasks.activities.ColorPickerActivity; import org.tasks.activities.ColorPickerActivity;
@ -22,6 +23,7 @@ import org.tasks.activities.TimePickerActivity;
import org.tasks.dialogs.ColorPickerDialog; import org.tasks.dialogs.ColorPickerDialog;
import org.tasks.injection.ActivityComponent; import org.tasks.injection.ActivityComponent;
import org.tasks.injection.InjectingPreferenceActivity; import org.tasks.injection.InjectingPreferenceActivity;
import org.tasks.jobs.JobManager;
import org.tasks.preferences.ActivityPermissionRequestor; import org.tasks.preferences.ActivityPermissionRequestor;
import org.tasks.preferences.Device; import org.tasks.preferences.Device;
import org.tasks.preferences.PermissionChecker; import org.tasks.preferences.PermissionChecker;
@ -103,7 +105,7 @@ public class ReminderPreferences extends InjectingPreferenceActivity {
private void resetGeofencesOnChange(int... resIds) { private void resetGeofencesOnChange(int... resIds) {
for (int resId : resIds) { for (int resId : resIds) {
findPreference(getString(resId)).setOnPreferenceChangeListener((preference, newValue) -> { findPreference(getString(resId)).setOnPreferenceChangeListener((preference, newValue) -> {
startService(new Intent(ReminderPreferences.this, GeofenceSchedulingIntentService.class)); JobIntentService.enqueueWork(this, GeofenceSchedulingIntentService.class, JobManager.JOB_ID_GEOFENCE_SCHEDULING, new Intent());
return true; return true;
}); });
} }

@ -17,11 +17,13 @@ import com.google.ical.values.Frequency;
import com.google.ical.values.RRule; import com.google.ical.values.RRule;
import com.google.ical.values.WeekdayNum; import com.google.ical.values.WeekdayNum;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.alarms.AlarmTaskRepeatListener;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gcal.GCalHelper; import com.todoroo.astrid.gcal.GCalHelper;
import org.tasks.LocalBroadcastManager;
import org.tasks.injection.BroadcastComponent; import org.tasks.injection.BroadcastComponent;
import org.tasks.injection.InjectingBroadcastReceiver; import org.tasks.injection.InjectingBroadcastReceiver;
import org.tasks.time.DateTime; import org.tasks.time.DateTime;
@ -42,8 +44,15 @@ import static org.tasks.date.DateTimeUtils.newDateUtc;
public class RepeatTaskCompleteListener extends InjectingBroadcastReceiver { public class RepeatTaskCompleteListener extends InjectingBroadcastReceiver {
public static void broadcast(Context context, long taskId) {
Intent intent = new Intent(context, RepeatTaskCompleteListener.class);
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
context.sendBroadcast(intent);
}
@Inject GCalHelper gcalHelper; @Inject GCalHelper gcalHelper;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject LocalBroadcastManager localBroadcastManager;
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
@ -83,12 +92,9 @@ public class RepeatTaskCompleteListener extends InjectingBroadcastReceiver {
rescheduleTask(gcalHelper, taskDao, task, newDueDate); rescheduleTask(gcalHelper, taskDao, task, newDueDate);
// send a broadcast AlarmTaskRepeatListener.broadcast(context, taskId, oldDueDate, newDueDate);
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_REPEATED);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId()); localBroadcastManager.broadcastRepeat(task.getId(), oldDueDate, newDueDate);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, oldDueDate);
broadcastIntent.putExtra(AstridApiConstants.EXTRAS_NEW_DUE_DATE, newDueDate);
context.sendOrderedBroadcast(broadcastIntent, null);
} }
} }

@ -24,8 +24,8 @@ import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.tags.TagService; import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.TaskToTagMetadata; import com.todoroo.astrid.tags.TaskToTagMetadata;
import org.tasks.Broadcaster;
import org.tasks.BuildConfig; import org.tasks.BuildConfig;
import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking; import org.tasks.analytics.Tracking;
@ -45,32 +45,30 @@ public class StartupService {
private static final int V4_8_0 = 380; private static final int V4_8_0 = 380;
private static final int V4_9_5 = 434; private static final int V4_9_5 = 434;
private final Context context;
private final Database database; private final Database database;
private final Preferences preferences; private final Preferences preferences;
private final TaskDeleter taskDeleter; private final TaskDeleter taskDeleter;
private final Broadcaster broadcaster;
private final Tracker tracker; private final Tracker tracker;
private final TagDataDao tagDataDao; private final TagDataDao tagDataDao;
private final TagService tagService; private final TagService tagService;
private final MetadataDao metadataDao; private final MetadataDao metadataDao;
private final BackgroundScheduler backgroundScheduler; private final BackgroundScheduler backgroundScheduler;
private final LocalBroadcastManager localBroadcastManager;
@Inject @Inject
public StartupService(@ForApplication Context context, Database database, Preferences preferences, public StartupService(Database database, Preferences preferences, TaskDeleter taskDeleter,
TaskDeleter taskDeleter, Broadcaster broadcaster, Tracker tracker, Tracker tracker, TagDataDao tagDataDao, TagService tagService,
TagDataDao tagDataDao, TagService tagService, MetadataDao metadataDao, MetadataDao metadataDao, BackgroundScheduler backgroundScheduler,
BackgroundScheduler backgroundScheduler) { LocalBroadcastManager localBroadcastManager) {
this.context = context;
this.database = database; this.database = database;
this.preferences = preferences; this.preferences = preferences;
this.taskDeleter = taskDeleter; this.taskDeleter = taskDeleter;
this.broadcaster = broadcaster;
this.tracker = tracker; this.tracker = tracker;
this.tagDataDao = tagDataDao; this.tagDataDao = tagDataDao;
this.tagService = tagService; this.tagService = tagService;
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.backgroundScheduler = backgroundScheduler; this.backgroundScheduler = backgroundScheduler;
this.localBroadcastManager = localBroadcastManager;
} }
/** Called when this application is started up */ /** Called when this application is started up */
@ -120,7 +118,7 @@ public class StartupService {
} }
preferences.setCurrentVersion(to); preferences.setCurrentVersion(to);
} finally { } finally {
context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH)); localBroadcastManager.broadcastRefresh();
} }
} }
@ -148,7 +146,7 @@ public class StartupService {
removeDuplicateTagData(tagsByUuid.get(uuid)); removeDuplicateTagData(tagsByUuid.get(uuid));
removeDuplicateTagMetadata(uuid); removeDuplicateTagMetadata(uuid);
} }
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
private void removeDuplicateTagData(List<TagData> tagData) { private void removeDuplicateTagData(List<TagData> tagData) {

@ -10,7 +10,7 @@ import com.todoroo.astrid.gcal.GCalHelper;
import com.todoroo.astrid.gtasks.GtasksMetadata; import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.tags.TaskToTagMetadata; import com.todoroo.astrid.tags.TaskToTagMetadata;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -24,15 +24,15 @@ public class TaskDuplicator {
private final GCalHelper gcalHelper; private final GCalHelper gcalHelper;
private final MetadataDao metadataDao; private final MetadataDao metadataDao;
private final TaskDao taskDao; private final TaskDao taskDao;
private final Broadcaster broadcaster; private final LocalBroadcastManager localBroadcastManager;
@Inject @Inject
public TaskDuplicator(GCalHelper gcalHelper, MetadataDao metadataDao, TaskDao taskDao, public TaskDuplicator(GCalHelper gcalHelper, MetadataDao metadataDao, TaskDao taskDao,
Broadcaster broadcaster) { LocalBroadcastManager localBroadcastManager) {
this.gcalHelper = gcalHelper; this.gcalHelper = gcalHelper;
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.taskDao = taskDao; this.taskDao = taskDao;
this.broadcaster = broadcaster; this.localBroadcastManager = localBroadcastManager;
} }
public List<Task> duplicate(List<Task> tasks) { public List<Task> duplicate(List<Task> tasks) {
@ -40,7 +40,7 @@ public class TaskDuplicator {
for (Task task : tasks) { for (Task task : tasks) {
result.add(clone(taskDao.fetch(task.getId(), Task.PROPERTIES), true)); result.add(clone(taskDao.fetch(task.getId(), Task.PROPERTIES), true));
} }
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
return result; return result;
} }

@ -19,6 +19,12 @@ import javax.inject.Inject;
public class TimerTaskCompleteListener extends InjectingBroadcastReceiver { public class TimerTaskCompleteListener extends InjectingBroadcastReceiver {
public static void broadcast(Context context, long taskId) {
Intent intent = new Intent(context, TimerTaskCompleteListener.class);
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, taskId);
context.sendBroadcast(intent);
}
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject TimerPlugin timerPlugin; @Inject TimerPlugin timerPlugin;

@ -1,59 +0,0 @@
package org.tasks;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.data.Task;
import org.tasks.injection.ForApplication;
import org.tasks.receivers.CompleteTaskReceiver;
import javax.inject.Inject;
public class Broadcaster {
private final Context context;
@Inject
public Broadcaster(@ForApplication Context context) {
this.context = context;
}
public void toggleCompletedState(long taskId) {
completeTask(taskId, true);
}
public void completeTask(long taskId) {
completeTask(taskId, false);
}
private void completeTask(final long taskId, final boolean flipState) {
Intent intent = new Intent(context, CompleteTaskReceiver.class);
intent.putExtra(CompleteTaskReceiver.TASK_ID, taskId);
intent.putExtra(CompleteTaskReceiver.TOGGLE_STATE, flipState);
context.sendBroadcast(intent);
}
public void taskCompleted(final long id) {
Intent intent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_COMPLETED);
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, id);
context.sendOrderedBroadcast(intent, null);
}
public void refresh() {
context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
}
public void refreshLists() {
context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH_LISTS));
}
public void taskUpdated(final Task task, final ContentValues values) {
Intent intent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_SAVED);
intent.putExtra(AstridApiConstants.EXTRAS_TASK, task);
intent.putExtra(AstridApiConstants.EXTRAS_VALUES, values);
context.sendBroadcast(intent);
}
}

@ -0,0 +1,68 @@
package org.tasks;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import com.todoroo.astrid.api.AstridApiConstants;
import org.tasks.injection.ForApplication;
import org.tasks.widget.AppWidgetManager;
import javax.inject.Inject;
public class LocalBroadcastManager {
public static final String REFRESH = BuildConfig.APPLICATION_ID + ".REFRESH";
public static final String REFRESH_LIST = BuildConfig.APPLICATION_ID + ".REFRESH_LIST";
private static final String REPEAT = BuildConfig.APPLICATION_ID + ".REPEAT";
private final android.support.v4.content.LocalBroadcastManager localBroadcastManager;
private final AppWidgetManager appWidgetManager;
@Inject
public LocalBroadcastManager(@ForApplication Context context, AppWidgetManager appWidgetManager) {
this.appWidgetManager = appWidgetManager;
localBroadcastManager = android.support.v4.content.LocalBroadcastManager.getInstance(context);
}
public void registerRefreshReceiver(BroadcastReceiver broadcastReceiver) {
localBroadcastManager.registerReceiver(broadcastReceiver, new IntentFilter(REFRESH));
}
public void registerRefreshListReceiver(BroadcastReceiver broadcastReceiver) {
localBroadcastManager.registerReceiver(broadcastReceiver, new IntentFilter(REFRESH_LIST));
}
public void registerRepeatReceiver(BroadcastReceiver broadcastReceiver) {
localBroadcastManager.registerReceiver(broadcastReceiver, new IntentFilter(REPEAT));
}
public void broadcastRefresh() {
localBroadcastManager.sendBroadcast(new Intent(REFRESH));
appWidgetManager.updateWidgets();
}
public void broadcastRefreshList() {
localBroadcastManager.sendBroadcast(new Intent(REFRESH_LIST));
}
/**
* Action name for broadcast intent notifying that task was created from repeating template
* <li> EXTRAS_TASK_ID id of the task
* <li> EXTRAS_OLD_DUE_DATE task old due date (could be 0)
* <li> EXTRAS_NEW_DUE_DATE task new due date (will not be 0)
*/
public void broadcastRepeat(long id, long oldDueDate, long newDueDate) {
Intent intent = new Intent(REPEAT);
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, id);
intent.putExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, oldDueDate);
intent.putExtra(AstridApiConstants.EXTRAS_NEW_DUE_DATE, newDueDate);
localBroadcastManager.sendBroadcast(intent);
}
public void unregisterReceiver(BroadcastReceiver broadcastReceiver) {
localBroadcastManager.unregisterReceiver(broadcastReceiver);
}
}

@ -60,13 +60,12 @@ public class Notifier {
private final AudioManager audioManager; private final AudioManager audioManager;
private final VoiceOutputAssistant voiceOutputAssistant; private final VoiceOutputAssistant voiceOutputAssistant;
private final Preferences preferences; private final Preferences preferences;
private final ThemeCache themeCache;
@Inject @Inject
public Notifier(@ForApplication Context context, TaskDao taskDao, public Notifier(@ForApplication Context context, TaskDao taskDao,
NotificationManager notificationManager, TelephonyManager telephonyManager, NotificationManager notificationManager, TelephonyManager telephonyManager,
AudioManager audioManager, VoiceOutputAssistant voiceOutputAssistant, AudioManager audioManager, VoiceOutputAssistant voiceOutputAssistant,
Preferences preferences, ThemeCache themeCache) { Preferences preferences) {
this.context = context; this.context = context;
this.taskDao = taskDao; this.taskDao = taskDao;
this.notificationManager = notificationManager; this.notificationManager = notificationManager;
@ -74,7 +73,6 @@ public class Notifier {
this.audioManager = audioManager; this.audioManager = audioManager;
this.voiceOutputAssistant = voiceOutputAssistant; this.voiceOutputAssistant = voiceOutputAssistant;
this.preferences = preferences; this.preferences = preferences;
this.themeCache = themeCache;
} }
public void triggerMissedCallNotification(final String name, final String number, long contactId) { public void triggerMissedCallNotification(final String name, final String number, long contactId) {
@ -86,7 +84,7 @@ public class Notifier {
missedCallDialog.putExtra(MissedCallActivity.EXTRA_NAME, name); missedCallDialog.putExtra(MissedCallActivity.EXTRA_NAME, name);
missedCallDialog.putExtra(MissedCallActivity.EXTRA_TITLE, title); missedCallDialog.putExtra(MissedCallActivity.EXTRA_TITLE, title);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context) NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationManager.DEFAULT_NOTIFICATION_CHANNEL)
.setSmallIcon(R.drawable.ic_check_white_24dp) .setSmallIcon(R.drawable.ic_check_white_24dp)
.setTicker(title) .setTicker(title)
.setContentTitle(title) .setContentTitle(title)
@ -155,7 +153,7 @@ public class Notifier {
intent.putExtra(TaskListActivity.OPEN_FILTER, filter); intent.putExtra(TaskListActivity.OPEN_FILTER, filter);
PendingIntent pendingIntent = PendingIntent.getActivity(context, (title + query).hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getActivity(context, (title + query).hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(context) Notification notification = new NotificationCompat.Builder(context, NotificationManager.DEFAULT_NOTIFICATION_CHANNEL)
.setSmallIcon(R.drawable.ic_check_white_24dp) .setSmallIcon(R.drawable.ic_check_white_24dp)
.setCategory(NotificationCompat.CATEGORY_REMINDER) .setCategory(NotificationCompat.CATEGORY_REMINDER)
.setTicker(title) .setTicker(title)
@ -236,7 +234,7 @@ public class Notifier {
ringTimes = 1; ringTimes = 1;
} }
NotificationCompat.Builder builder = new NotificationCompat.Builder(context) NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationManager.DEFAULT_NOTIFICATION_CHANNEL)
.setSmallIcon(R.drawable.ic_check_white_24dp) .setSmallIcon(R.drawable.ic_check_white_24dp)
.setCategory(NotificationCompat.CATEGORY_REMINDER) .setCategory(NotificationCompat.CATEGORY_REMINDER)
.setTicker(taskTitle) .setTicker(taskTitle)
@ -290,13 +288,11 @@ public class Notifier {
if (preferences.getBoolean(R.string.p_rmd_persistent, true)) { if (preferences.getBoolean(R.string.p_rmd_persistent, true)) {
notification.flags |= Notification.FLAG_NO_CLEAR; notification.flags |= Notification.FLAG_NO_CLEAR;
} }
if (preferences.getBoolean(R.string.p_led_notification, true)) { if (preferences.isLEDNotificationEnabled()) {
int accent = preferences.getInt(R.string.p_led_color, 4);
LEDColor ledColor = themeCache.getLEDColor(accent);
notification.flags |= Notification.FLAG_SHOW_LIGHTS; notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.ledOffMS = 5000; notification.ledOffMS = 5000;
notification.ledOnMS = 700; notification.ledOnMS = 700;
notification.ledARGB = ledColor.getColor(); notification.ledARGB = preferences.getLEDColor();
} else { } else {
notification.ledOffMS = 0; notification.ledOffMS = 0;
notification.ledOnMS = 0; notification.ledOnMS = 0;
@ -358,7 +354,7 @@ public class Notifier {
} }
} }
if (preferences.getBoolean(R.string.p_rmd_vibrate, true) && soundIntervalOk) { if (preferences.isVibrationEnabled() && soundIntervalOk) {
notification.vibrate = preferences.getVibrationPattern(); notification.vibrate = preferences.getVibrationPattern();
} else { } else {
notification.vibrate = null; notification.vibrate = null;

@ -12,6 +12,7 @@ import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.injection.InjectingApplication; import org.tasks.injection.InjectingApplication;
import org.tasks.preferences.DefaultFilterProvider; import org.tasks.preferences.DefaultFilterProvider;
@ -28,6 +29,7 @@ public class DashClockExtension extends com.google.android.apps.dashclock.api.Da
@Inject DefaultFilterProvider defaultFilterProvider; @Inject DefaultFilterProvider defaultFilterProvider;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject LocalBroadcastManager localBroadcastManager;
private final BroadcastReceiver refreshReceiver = new BroadcastReceiver() { private final BroadcastReceiver refreshReceiver = new BroadcastReceiver() {
@Override @Override
@ -44,14 +46,14 @@ public class DashClockExtension extends com.google.android.apps.dashclock.api.Da
.getComponent() .getComponent()
.inject(this); .inject(this);
registerReceiver(refreshReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH)); localBroadcastManager.registerRefreshReceiver(refreshReceiver);
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
unregisterReceiver(refreshReceiver); localBroadcastManager.unregisterReceiver(refreshReceiver);
} }
@Override @Override

@ -6,7 +6,7 @@ import android.os.Bundle;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.activities.FilterSelectionActivity; import org.tasks.activities.FilterSelectionActivity;
import org.tasks.billing.PurchaseHelper; import org.tasks.billing.PurchaseHelper;
@ -27,7 +27,7 @@ public class DashClockSettings extends InjectingPreferenceActivity implements Pu
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject DefaultFilterProvider defaultFilterProvider; @Inject DefaultFilterProvider defaultFilterProvider;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
@Inject PurchaseHelper purchaseHelper; @Inject PurchaseHelper purchaseHelper;
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@ -80,7 +80,7 @@ public class DashClockSettings extends InjectingPreferenceActivity implements Pu
String filterPreference = defaultFilterProvider.getFilterPreferenceValue(filter); String filterPreference = defaultFilterProvider.getFilterPreferenceValue(filter);
preferences.setString(R.string.p_dashclock_filter, filterPreference); preferences.setString(R.string.p_dashclock_filter, filterPreference);
refreshPreferences(); refreshPreferences();
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
} else if (requestCode == REQUEST_PURCHASE) { } else if (requestCode == REQUEST_PURCHASE) {
purchaseHelper.handleActivityResult(this, requestCode, resultCode, data); purchaseHelper.handleActivityResult(this, requestCode, resultCode, data);
@ -99,7 +99,7 @@ public class DashClockSettings extends InjectingPreferenceActivity implements Pu
@Override @Override
public void purchaseCompleted(boolean success, String sku) { public void purchaseCompleted(boolean success, String sku) {
if (success) { if (success) {
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} else { } else {
finish(); finish();
} }

@ -1,20 +1,18 @@
package org.tasks.injection; package org.tasks.injection;
import android.app.IntentService;
import android.content.Intent; import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
public abstract class InjectingIntentService extends IntentService { public abstract class InjectingJobIntentService extends JobIntentService {
protected InjectingIntentService(String name) {
super(name);
}
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleWork(@NonNull Intent intent) {
inject(((InjectingApplication) getApplication()) inject(((InjectingApplication) getApplication())
.getComponent() .getComponent()
.plus(new IntentServiceModule())); .plus(new IntentServiceModule()));
} }
protected abstract void inject(IntentServiceComponent component); protected abstract void inject(IntentServiceComponent component);
} }

@ -1,6 +1,9 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v4.app.JobIntentService;
import com.todoroo.astrid.alarms.AlarmService; import com.todoroo.astrid.alarms.AlarmService;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
@ -13,7 +16,14 @@ import org.tasks.preferences.Preferences;
import javax.inject.Inject; import javax.inject.Inject;
public class AlarmJob extends WakefulJob { public class AlarmJob extends Job {
public static class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
JobIntentService.enqueueWork(context, AlarmJob.class, JobManager.JOB_ID_ALARM, intent);
}
}
public static final String TAG = "job_alarm"; public static final String TAG = "job_alarm";
@ -22,10 +32,6 @@ public class AlarmJob extends WakefulJob {
@Inject Notifier notifier; @Inject Notifier notifier;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
public AlarmJob() {
super(AlarmJob.class.getSimpleName());
}
@Override @Override
protected void run() { protected void run() {
if (!preferences.isCurrentlyQuietHours()) { if (!preferences.isCurrentlyQuietHours()) {
@ -48,9 +54,4 @@ public class AlarmJob extends WakefulJob {
protected void inject(IntentServiceComponent component) { protected void inject(IntentServiceComponent component) {
component.inject(this); component.inject(this);
} }
@Override
protected void completeWakefulIntent(Intent intent) {
AlarmJobBroadcast.completeWakefulIntent(intent);
}
} }

@ -1,12 +0,0 @@
package org.tasks.jobs;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
public class AlarmJobBroadcast extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
startWakefulService(context, new Intent(context, AlarmJob.class));
}
}

@ -1,6 +1,9 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.support.v4.app.JobIntentService;
import com.todoroo.astrid.backup.TasksXmlExporter; import com.todoroo.astrid.backup.TasksXmlExporter;
@ -18,6 +21,13 @@ import timber.log.Timber;
public class BackupJob extends MidnightJob { public class BackupJob extends MidnightJob {
public static class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
JobIntentService.enqueueWork(context, BackupJob.class, JobManager.JOB_ID_BACKUP, intent);
}
}
public static final String TAG = "job_backup"; public static final String TAG = "job_backup";
public static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.xml"; //$NON-NLS-1$ public static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.xml"; //$NON-NLS-1$
@ -28,13 +38,12 @@ public class BackupJob extends MidnightJob {
@Inject TasksXmlExporter tasksXmlExporter; @Inject TasksXmlExporter tasksXmlExporter;
@Inject Preferences preferences; @Inject Preferences preferences;
@SuppressWarnings("unused")
public BackupJob() { public BackupJob() {
super(BackupJob.class.getSimpleName());
} }
BackupJob(Context context, JobManager jobManager, TasksXmlExporter tasksXmlExporter, Preferences preferences) { BackupJob(Context context, JobManager jobManager, TasksXmlExporter tasksXmlExporter, Preferences preferences) {
this();
this.context = context; this.context = context;
this.jobManager = jobManager; this.jobManager = jobManager;
this.tasksXmlExporter = tasksXmlExporter; this.tasksXmlExporter = tasksXmlExporter;

@ -1,26 +1,22 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.content.Intent; import android.content.Intent;
import android.support.annotation.NonNull;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.injection.InjectingIntentService; import org.tasks.injection.InjectingJobIntentService;
import javax.inject.Inject; import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;
public abstract class Job extends InjectingIntentService { public abstract class Job extends InjectingJobIntentService {
@Inject Tracker tracker; @Inject Tracker tracker;
public Job(String name) {
super(name);
setIntentRedelivery(true);
}
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleWork(@NonNull Intent intent) {
super.onHandleIntent(intent); super.onHandleWork(intent);
Timber.d("onHandleIntent(%s)", intent); Timber.d("onHandleIntent(%s)", intent);

@ -19,6 +19,17 @@ import static org.tasks.time.DateTimeUtils.printTimestamp;
@ApplicationScope @ApplicationScope
public class JobManager { public class JobManager {
static final int JOB_ID_REFRESH = 1;
static final int JOB_ID_REMINDER = 2;
static final int JOB_ID_ALARM = 3;
public static final int JOB_ID_GEOFENCE_TRANSITION = 4;
public static final int JOB_ID_GEOFENCE_SCHEDULING = 5;
static final int JOB_ID_MIDNIGHT_REFRESH = 6;
static final int JOB_ID_BACKUP = 7;
public static final int JOB_ID_SCHEDULER = 8;
public static final int JOB_ID_NOTIFICATION_SCHEDULER = 9;
public static final int JOB_ID_CALENDAR_NOTIFICATION = 10;
private Context context; private Context context;
private AlarmManager alarmManager; private AlarmManager alarmManager;
@ -35,19 +46,19 @@ public class JobManager {
public void scheduleRefresh(long time) { public void scheduleRefresh(long time) {
Timber.d("%s: %s", RefreshJob.TAG, printTimestamp(time)); Timber.d("%s: %s", RefreshJob.TAG, printTimestamp(time));
alarmManager.noWakeup(adjust(time), getPendingService(RefreshJob.class)); alarmManager.noWakeup(adjust(time), getPendingBroadcast(RefreshJob.Broadcast.class));
} }
public void scheduleMidnightRefresh() { public void scheduleMidnightRefresh() {
long time = nextMidnight(); long time = nextMidnight();
Timber.d("%s: %s", MidnightRefreshJob.TAG, printTimestamp(time)); Timber.d("%s: %s", MidnightRefreshJob.TAG, printTimestamp(time));
alarmManager.noWakeup(adjust(time), getPendingService(MidnightRefreshJob.class)); alarmManager.noWakeup(adjust(time), getPendingBroadcast(MidnightRefreshJob.class));
} }
public void scheduleMidnightBackup() { public void scheduleMidnightBackup() {
long time = nextMidnight(); long time = nextMidnight();
Timber.d("%s: %s", BackupJob.TAG, printTimestamp(time)); Timber.d("%s: %s", BackupJob.TAG, printTimestamp(time));
alarmManager.noWakeup(adjust(time), getPendingService(BackupJob.class)); alarmManager.noWakeup(adjust(time), getPendingBroadcast(BackupJob.class));
} }
public void cancel(String tag) { public void cancel(String tag) {
@ -62,11 +73,11 @@ public class JobManager {
private PendingIntent getPendingIntent(String tag) { private PendingIntent getPendingIntent(String tag) {
switch (tag) { switch (tag) {
case ReminderJob.TAG: case ReminderJob.TAG:
return getPendingBroadcast(ReminderJobBroadcast.class); return getPendingBroadcast(ReminderJob.Broadcast.class);
case AlarmJob.TAG: case AlarmJob.TAG:
return getPendingBroadcast(AlarmJobBroadcast.class); return getPendingBroadcast(AlarmJob.Broadcast.class);
case RefreshJob.TAG: case RefreshJob.TAG:
return getPendingService(RefreshJob.class); return getPendingBroadcast(RefreshJob.Broadcast.class);
default: default:
throw new RuntimeException("Unexpected tag: " + tag); throw new RuntimeException("Unexpected tag: " + tag);
} }
@ -75,8 +86,4 @@ public class JobManager {
private <T> PendingIntent getPendingBroadcast(Class<T> c) { private <T> PendingIntent getPendingBroadcast(Class<T> c) {
return PendingIntent.getBroadcast(context, 0, new Intent(context, c), 0); return PendingIntent.getBroadcast(context, 0, new Intent(context, c), 0);
} }
private <T> PendingIntent getPendingService(Class<T> c) {
return PendingIntent.getService(context, 0, new Intent(context, c), 0);
}
} }

@ -1,7 +1,4 @@
package org.tasks.jobs; package org.tasks.jobs;
public abstract class MidnightJob extends Job { public abstract class MidnightJob extends Job {
public MidnightJob(String name) {
super(name);
}
} }

@ -1,24 +1,32 @@
package org.tasks.jobs; package org.tasks.jobs;
import org.tasks.Broadcaster; import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.JobIntentService;
import org.tasks.LocalBroadcastManager;
import org.tasks.injection.IntentServiceComponent; import org.tasks.injection.IntentServiceComponent;
import javax.inject.Inject; import javax.inject.Inject;
public class MidnightRefreshJob extends MidnightJob { public class MidnightRefreshJob extends MidnightJob {
public static class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
JobIntentService.enqueueWork(context, MidnightRefreshJob.class, JobManager.JOB_ID_MIDNIGHT_REFRESH, intent);
}
}
public static final String TAG = "job_midnight_refresh"; public static final String TAG = "job_midnight_refresh";
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
@Inject JobManager jobManager; @Inject JobManager jobManager;
public MidnightRefreshJob() {
super(MidnightRefreshJob.class.getSimpleName());
}
@Override @Override
protected void run() { protected void run() {
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
@Override @Override

@ -1,6 +1,11 @@
package org.tasks.jobs; package org.tasks.jobs;
import org.tasks.Broadcaster; import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.JobIntentService;
import org.tasks.LocalBroadcastManager;
import org.tasks.injection.IntentServiceComponent; import org.tasks.injection.IntentServiceComponent;
import org.tasks.scheduling.RefreshScheduler; import org.tasks.scheduling.RefreshScheduler;
@ -8,14 +13,17 @@ import javax.inject.Inject;
public class RefreshJob extends Job { public class RefreshJob extends Job {
public static class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
JobIntentService.enqueueWork(context, RefreshJob.class, JobManager.JOB_ID_REFRESH, intent);
}
}
public static final String TAG = "job_refresh"; public static final String TAG = "job_refresh";
@Inject RefreshScheduler refreshScheduler; @Inject RefreshScheduler refreshScheduler;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
public RefreshJob() {
super(RefreshJob.class.getSimpleName());
}
@Override @Override
protected void inject(IntentServiceComponent component) { protected void inject(IntentServiceComponent component) {
@ -24,7 +32,7 @@ public class RefreshJob extends Job {
@Override @Override
protected void run() { protected void run() {
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
@Override @Override

@ -1,6 +1,9 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v4.app.JobIntentService;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
@ -10,7 +13,14 @@ import org.tasks.preferences.Preferences;
import javax.inject.Inject; import javax.inject.Inject;
public class ReminderJob extends WakefulJob { public class ReminderJob extends Job {
public static class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
JobIntentService.enqueueWork(context, ReminderJob.class, JobManager.JOB_ID_REMINDER, intent);
}
}
public static final String TAG = "job_reminder"; public static final String TAG = "job_reminder";
@ -18,10 +28,6 @@ public class ReminderJob extends WakefulJob {
@Inject ReminderService reminderService; @Inject ReminderService reminderService;
@Inject Notifier notifier; @Inject Notifier notifier;
public ReminderJob() {
super(ReminderJob.class.getSimpleName());
}
@Override @Override
protected void inject(IntentServiceComponent component) { protected void inject(IntentServiceComponent component) {
component.inject(this); component.inject(this);
@ -41,9 +47,4 @@ public class ReminderJob extends WakefulJob {
protected void scheduleNext() { protected void scheduleNext() {
reminderService.scheduleNextJob(); reminderService.scheduleNextJob();
} }
@Override
protected void completeWakefulIntent(Intent intent) {
ReminderJobBroadcast.completeWakefulIntent(intent);
}
} }

@ -1,12 +0,0 @@
package org.tasks.jobs;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
public class ReminderJobBroadcast extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
startWakefulService(context, new Intent(context, ReminderJob.class));
}
}

@ -1,18 +0,0 @@
package org.tasks.jobs;
import android.content.Intent;
public abstract class WakefulJob extends Job {
public WakefulJob(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
super.onHandleIntent(intent);
completeWakefulIntent(intent);
}
protected abstract void completeWakefulIntent(Intent intent);
}

@ -1,6 +1,7 @@
package org.tasks.notifications; package org.tasks.notifications;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel;
import android.content.Context; import android.content.Context;
import org.tasks.R; import org.tasks.R;
@ -9,16 +10,28 @@ import org.tasks.preferences.Preferences;
import javax.inject.Inject; import javax.inject.Inject;
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastO;
public class NotificationManager { public class NotificationManager {
private final android.app.NotificationManager notificationManager; private final android.app.NotificationManager notificationManager;
private final Preferences preferences; private final Preferences preferences;
public static final String DEFAULT_NOTIFICATION_CHANNEL = "my_channel_01";
@Inject @Inject
public NotificationManager(@ForApplication Context context, Preferences preferences) { public NotificationManager(@ForApplication Context context, Preferences preferences) {
this.preferences = preferences; this.preferences = preferences;
notificationManager = (android.app.NotificationManager) notificationManager = (android.app.NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE); context.getSystemService(Context.NOTIFICATION_SERVICE);
if (atLeastO()) {
String channelName = context.getString(R.string.notifications);
NotificationChannel notificationChannel = new NotificationChannel(DEFAULT_NOTIFICATION_CHANNEL, channelName, android.app.NotificationManager.IMPORTANCE_HIGH);
notificationChannel.enableLights(preferences.isLEDNotificationEnabled());
notificationChannel.enableVibration(preferences.isVibrationEnabled());
notificationChannel.setLightColor(preferences.getLEDColor());
notificationChannel.setVibrationPattern(preferences.getVibrationPattern());
notificationManager.createNotificationChannel(notificationChannel);
}
} }
public void cancel(long id) { public void cancel(long id) {

@ -7,7 +7,7 @@ import android.preference.Preference;
import com.todoroo.astrid.activity.BeastModePreferences; import com.todoroo.astrid.activity.BeastModePreferences;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.activities.FilterSelectionActivity; import org.tasks.activities.FilterSelectionActivity;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
@ -37,7 +37,7 @@ public class AppearancePreferences extends InjectingPreferenceActivity implement
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject DefaultFilterProvider defaultFilterProvider; @Inject DefaultFilterProvider defaultFilterProvider;
@Inject Tracker tracker; @Inject Tracker tracker;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
@Inject Locale locale; @Inject Locale locale;
private Bundle result; private Bundle result;
@ -113,7 +113,7 @@ public class AppearancePreferences extends InjectingPreferenceActivity implement
Filter filter = data.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER); Filter filter = data.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER);
defaultFilterProvider.setDefaultFilter(filter); defaultFilterProvider.setDefaultFilter(filter);
findPreference(getString(R.string.p_default_list)).setSummary(filter.listingTitle); findPreference(getString(R.string.p_default_list)).setSummary(filter.listingTitle);
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
} else { } else {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);

@ -1,8 +1,10 @@
package org.tasks.preferences; package org.tasks.preferences;
import android.Manifest; import android.Manifest;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
@ -13,6 +15,8 @@ import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastKitKat;
import static com.todoroo.andlib.utility.AndroidUtilities.preJellybean;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
@ -45,9 +49,11 @@ public class PermissionChecker {
return checkPermission(Manifest.permission.RECORD_AUDIO); return checkPermission(Manifest.permission.RECORD_AUDIO);
} }
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public boolean canAccessMissedCallPermissions() { public boolean canAccessMissedCallPermissions() {
return checkPermission(Manifest.permission.READ_CONTACTS) && return checkPermission(Manifest.permission.READ_CONTACTS) &&
checkPermission(Manifest.permission.READ_PHONE_STATE); checkPermission(Manifest.permission.READ_PHONE_STATE) &&
(preJellybean() || checkPermission(Manifest.permission.READ_CALL_LOG));
} }
private boolean checkPermission(String permission) { private boolean checkPermission(String permission) {

@ -2,6 +2,8 @@ package org.tasks.preferences;
import android.Manifest; import android.Manifest;
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastJellybean;
public abstract class PermissionRequestor { public abstract class PermissionRequestor {
public static final int REQUEST_FILE_WRITE = 50; public static final int REQUEST_FILE_WRITE = 50;
public static final int REQUEST_CALENDAR = 51; public static final int REQUEST_CALENDAR = 51;
@ -66,7 +68,10 @@ public abstract class PermissionRequestor {
if (permissionChecker.canAccessMissedCallPermissions()) { if (permissionChecker.canAccessMissedCallPermissions()) {
return true; return true;
} }
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.READ_PHONE_STATE}, REQUEST_CONTACTS); String[] permissions = atLeastJellybean()
? new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_CALL_LOG}
: new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.READ_PHONE_STATE};
requestPermissions(permissions, REQUEST_CONTACTS);
return false; return false;
} }

@ -15,6 +15,8 @@ import com.todoroo.astrid.data.TaskAttachment;
import org.tasks.R; import org.tasks.R;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.themes.LEDColor;
import org.tasks.themes.ThemeCache;
import org.tasks.time.DateTime; import org.tasks.time.DateTime;
import java.io.File; import java.io.File;
@ -39,15 +41,14 @@ public class Preferences {
private final PermissionChecker permissionChecker; private final PermissionChecker permissionChecker;
private final SharedPreferences prefs; private final SharedPreferences prefs;
private final SharedPreferences publicPrefs; private final SharedPreferences publicPrefs;
private final ThemeCache themeCache;
public Preferences(Context context) {
this(context, new PermissionChecker(context));
}
@Inject @Inject
public Preferences(@ForApplication Context context, PermissionChecker permissionChecker) { public Preferences(@ForApplication Context context, PermissionChecker permissionChecker,
ThemeCache themeCache) {
this.context = context; this.context = context;
this.permissionChecker = permissionChecker; this.permissionChecker = permissionChecker;
this.themeCache = themeCache;
prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs = PreferenceManager.getDefaultSharedPreferences(context);
publicPrefs = context.getSharedPreferences(AstridApiConstants.PUBLIC_PREFS, Context.MODE_PRIVATE); publicPrefs = context.getSharedPreferences(AstridApiConstants.PUBLIC_PREFS, Context.MODE_PRIVATE);
} }
@ -90,6 +91,19 @@ public class Preferences {
return time; return time;
} }
public boolean isVibrationEnabled() {
return getBoolean(R.string.p_rmd_vibrate, true);
}
public boolean isLEDNotificationEnabled() {
return getBoolean(R.string.p_led_notification, true);
}
public int getLEDColor() {
int accent = getInt(R.string.p_led_color, 4);
return themeCache.getLEDColor(accent).getColor();
}
public boolean quietHoursEnabled() { public boolean quietHoursEnabled() {
return getBoolean(R.string.p_rmd_enable_quiet, false); return getBoolean(R.string.p_rmd_enable_quiet, false);
} }

@ -10,8 +10,8 @@ import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import org.tasks.Broadcaster;
import org.tasks.BuildConfig; import org.tasks.BuildConfig;
import org.tasks.LocalBroadcastManager;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.injection.BroadcastComponent; import org.tasks.injection.BroadcastComponent;
@ -33,18 +33,18 @@ public class TeslaUnreadReceiver extends InjectingBroadcastReceiver {
private final DefaultFilterProvider defaultFilterProvider; private final DefaultFilterProvider defaultFilterProvider;
private final TaskDao taskDao; private final TaskDao taskDao;
private final Tracker tracker; private final Tracker tracker;
private final Broadcaster broadcaster; private final LocalBroadcastManager localBroadcastManager;
private boolean enabled; private boolean enabled;
@Inject @Inject
public TeslaUnreadReceiver(@ForApplication Context context, DefaultFilterProvider defaultFilterProvider, public TeslaUnreadReceiver(@ForApplication Context context, DefaultFilterProvider defaultFilterProvider,
TaskDao taskDao, Tracker tracker, Broadcaster broadcaster) { TaskDao taskDao, Tracker tracker, LocalBroadcastManager localBroadcastManager) {
this.context = context; this.context = context;
this.defaultFilterProvider = defaultFilterProvider; this.defaultFilterProvider = defaultFilterProvider;
this.taskDao = taskDao; this.taskDao = taskDao;
this.tracker = tracker; this.tracker = tracker;
this.broadcaster = broadcaster; this.localBroadcastManager = localBroadcastManager;
} }
@Override @Override
@ -63,10 +63,10 @@ public class TeslaUnreadReceiver extends InjectingBroadcastReceiver {
public void setEnabled(boolean newValue) { public void setEnabled(boolean newValue) {
try { try {
if (newValue) { if (newValue) {
context.registerReceiver(this, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_REFRESH)); localBroadcastManager.registerRefreshReceiver(this);
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} else if (enabled) { } else if (enabled) {
context.unregisterReceiver(this); localBroadcastManager.unregisterReceiver(this);
publishCount(0); publishCount(0);
} }
enabled = newValue; enabled = newValue;

@ -1,14 +1,14 @@
package org.tasks.reminders; package org.tasks.reminders;
import android.support.v4.app.FragmentManager;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import org.tasks.Broadcaster;
import org.tasks.injection.ActivityComponent; import org.tasks.injection.ActivityComponent;
import org.tasks.injection.InjectingAppCompatActivity; import org.tasks.injection.InjectingAppCompatActivity;
import org.tasks.intents.TaskIntents; import org.tasks.intents.TaskIntents;
import org.tasks.notifications.NotificationManager; import org.tasks.notifications.NotificationManager;
import org.tasks.receivers.CompleteTaskReceiver;
import javax.inject.Inject; import javax.inject.Inject;
@ -21,8 +21,8 @@ public class NotificationActivity extends InjectingAppCompatActivity implements
public static final String EXTRA_TITLE = "extra_title"; public static final String EXTRA_TITLE = "extra_title";
public static final String EXTRA_TASK_ID = "extra_task_id"; public static final String EXTRA_TASK_ID = "extra_task_id";
@Inject Broadcaster broadcaster;
@Inject NotificationManager notificationManager; @Inject NotificationManager notificationManager;
private long taskId; private long taskId;
@Override @Override
@ -82,7 +82,10 @@ public class NotificationActivity extends InjectingAppCompatActivity implements
@Override @Override
public void complete() { public void complete() {
broadcaster.completeTask(taskId); Intent intent = new Intent(this, CompleteTaskReceiver.class);
intent.putExtra(CompleteTaskReceiver.TASK_ID, taskId);
intent.putExtra(CompleteTaskReceiver.TOGGLE_STATE, false);
sendBroadcast(intent);
finish(); finish();
} }
} }

@ -2,8 +2,10 @@ package org.tasks.scheduling;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v4.app.JobIntentService;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.jobs.JobManager;
import javax.inject.Inject; import javax.inject.Inject;
@ -16,13 +18,13 @@ public class BackgroundScheduler {
} }
public void scheduleEverything() { public void scheduleEverything() {
context.startService(new Intent(context, GeofenceSchedulingIntentService.class)); JobIntentService.enqueueWork(context, GeofenceSchedulingIntentService.class, JobManager.JOB_ID_GEOFENCE_SCHEDULING, new Intent());
context.startService(new Intent(context, SchedulerIntentService.class)); JobIntentService.enqueueWork(context, SchedulerIntentService.class, JobManager.JOB_ID_SCHEDULER, new Intent());
context.startService(new Intent(context, NotificationSchedulerIntentService.class)); JobIntentService.enqueueWork(context, NotificationSchedulerIntentService.class, JobManager.JOB_ID_NOTIFICATION_SCHEDULER, new Intent());
scheduleCalendarNotifications(); scheduleCalendarNotifications();
} }
public void scheduleCalendarNotifications() { public void scheduleCalendarNotifications() {
context.startService(new Intent(context, CalendarNotificationIntentService.class)); JobIntentService.enqueueWork(context, CalendarNotificationIntentService.class, JobManager.JOB_ID_CALENDAR_NOTIFICATION, new Intent());
} }
} }

@ -1,9 +1,11 @@
package org.tasks.scheduling; package org.tasks.scheduling;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.support.v4.app.JobIntentService;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.gcal.CalendarAlarmReceiver; import com.todoroo.astrid.gcal.CalendarAlarmReceiver;
@ -13,6 +15,7 @@ import org.tasks.calendars.AndroidCalendarEvent;
import org.tasks.calendars.CalendarEventProvider; import org.tasks.calendars.CalendarEventProvider;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.injection.IntentServiceComponent; import org.tasks.injection.IntentServiceComponent;
import org.tasks.jobs.JobManager;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -23,6 +26,13 @@ import timber.log.Timber;
public class CalendarNotificationIntentService extends RecurringIntervalIntentService { public class CalendarNotificationIntentService extends RecurringIntervalIntentService {
public static class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
JobIntentService.enqueueWork(context, CalendarNotificationIntentService.class, JobManager.JOB_ID_CALENDAR_NOTIFICATION, new Intent());
}
}
private static final long FIFTEEN_MINUTES = TimeUnit.MINUTES.toMillis(15); private static final long FIFTEEN_MINUTES = TimeUnit.MINUTES.toMillis(15);
private static final String URI_PREFIX = "cal-reminder"; private static final String URI_PREFIX = "cal-reminder";
@ -33,8 +43,9 @@ public class CalendarNotificationIntentService extends RecurringIntervalIntentSe
@Inject @ForApplication Context context; @Inject @ForApplication Context context;
@Inject AlarmManager alarmManager; @Inject AlarmManager alarmManager;
public CalendarNotificationIntentService() { @Override
super(CalendarNotificationIntentService.class.getSimpleName()); Class<Broadcast> getBroadcastClass() {
return Broadcast.class;
} }
@Override @Override

@ -2,7 +2,7 @@ package org.tasks.scheduling;
import android.content.Intent; import android.content.Intent;
import org.tasks.injection.InjectingIntentService; import org.tasks.injection.InjectingJobIntentService;
import org.tasks.injection.IntentServiceComponent; import org.tasks.injection.IntentServiceComponent;
import org.tasks.location.GeofenceService; import org.tasks.location.GeofenceService;
@ -10,17 +10,13 @@ import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;
public class GeofenceSchedulingIntentService extends InjectingIntentService { public class GeofenceSchedulingIntentService extends InjectingJobIntentService {
@Inject GeofenceService geofenceService; @Inject GeofenceService geofenceService;
public GeofenceSchedulingIntentService() {
super(GeofenceSchedulingIntentService.class.getSimpleName());
}
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleWork(Intent intent) {
super.onHandleIntent(intent); super.onHandleWork(intent);
Timber.d("onHandleIntent(%s)", intent); Timber.d("onHandleIntent(%s)", intent);

@ -6,26 +6,22 @@ import com.todoroo.astrid.alarms.AlarmService;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
import org.tasks.injection.InjectingIntentService; import org.tasks.injection.InjectingJobIntentService;
import org.tasks.injection.IntentServiceComponent; import org.tasks.injection.IntentServiceComponent;
import javax.inject.Inject; import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;
public class NotificationSchedulerIntentService extends InjectingIntentService { public class NotificationSchedulerIntentService extends InjectingJobIntentService {
@Inject AlarmService alarmService; @Inject AlarmService alarmService;
@Inject ReminderService reminderService; @Inject ReminderService reminderService;
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
public NotificationSchedulerIntentService() {
super(NotificationSchedulerIntentService.class.getSimpleName());
}
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleWork(Intent intent) {
super.onHandleIntent(intent); super.onHandleWork(intent);
Timber.d("onHandleIntent(%s)", intent); Timber.d("onHandleIntent(%s)", intent);

@ -1,9 +1,10 @@
package org.tasks.scheduling; package org.tasks.scheduling;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Intent; import android.content.Intent;
import org.tasks.injection.InjectingIntentService; import org.tasks.injection.InjectingJobIntentService;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import javax.inject.Inject; import javax.inject.Inject;
@ -14,20 +15,16 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static org.tasks.time.DateTimeUtils.currentTimeMillis; import static org.tasks.time.DateTimeUtils.currentTimeMillis;
import static org.tasks.time.DateTimeUtils.printTimestamp; import static org.tasks.time.DateTimeUtils.printTimestamp;
public abstract class RecurringIntervalIntentService extends InjectingIntentService { public abstract class RecurringIntervalIntentService extends InjectingJobIntentService {
private static final long PADDING = SECONDS.toMillis(1); private static final long PADDING = SECONDS.toMillis(1);
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject AlarmManager alarmManager; @Inject AlarmManager alarmManager;
RecurringIntervalIntentService(String name) {
super(name);
}
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleWork(Intent intent) {
super.onHandleIntent(intent); super.onHandleWork(intent);
long interval = intervalMillis(); long interval = intervalMillis();
@ -52,10 +49,12 @@ public abstract class RecurringIntervalIntentService extends InjectingIntentServ
Timber.d("will run at %s [lastRun=%s]", printTimestamp(nextRun), printTimestamp(lastRun)); Timber.d("will run at %s [lastRun=%s]", printTimestamp(nextRun), printTimestamp(lastRun));
} }
PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, getBroadcastClass()), PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.wakeup(nextRun, pendingIntent); alarmManager.wakeup(nextRun, pendingIntent);
} }
abstract Class<? extends BroadcastReceiver> getBroadcastClass();
abstract void run(); abstract void run();
abstract long intervalMillis(); abstract long intervalMillis();

@ -6,7 +6,7 @@ import com.todoroo.andlib.sql.Criterion;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import org.tasks.injection.InjectingIntentService; import org.tasks.injection.InjectingJobIntentService;
import org.tasks.injection.IntentServiceComponent; import org.tasks.injection.IntentServiceComponent;
import org.tasks.jobs.JobManager; import org.tasks.jobs.JobManager;
@ -16,19 +16,15 @@ import timber.log.Timber;
import static java.lang.System.currentTimeMillis; import static java.lang.System.currentTimeMillis;
public class SchedulerIntentService extends InjectingIntentService { public class SchedulerIntentService extends InjectingJobIntentService {
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject JobManager jobManager; @Inject JobManager jobManager;
@Inject RefreshScheduler refreshScheduler; @Inject RefreshScheduler refreshScheduler;
public SchedulerIntentService() {
super(SchedulerIntentService.class.getSimpleName());
}
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleWork(Intent intent) {
super.onHandleIntent(intent); super.onHandleWork(intent);
Timber.d("onHandleIntent(%s)", intent); Timber.d("onHandleIntent(%s)", intent);

@ -3,27 +3,28 @@ package org.tasks.sync;
import com.todoroo.astrid.gtasks.GtasksPreferenceService; import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.sync.SyncResultCallback; import com.todoroo.astrid.sync.SyncResultCallback;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
public class RecordSyncStatusCallback implements SyncResultCallback { public class RecordSyncStatusCallback implements SyncResultCallback {
private final GtasksPreferenceService gtasksPreferenceService; private final GtasksPreferenceService gtasksPreferenceService;
private final Broadcaster broadcaster; private final LocalBroadcastManager localBroadcastManager;
public RecordSyncStatusCallback(GtasksPreferenceService gtasksPreferenceService, Broadcaster broadcaster) { public RecordSyncStatusCallback(GtasksPreferenceService gtasksPreferenceService,
LocalBroadcastManager localBroadcastManager) {
this.gtasksPreferenceService = gtasksPreferenceService; this.gtasksPreferenceService = gtasksPreferenceService;
this.broadcaster = broadcaster; this.localBroadcastManager = localBroadcastManager;
} }
@Override @Override
public void started() { public void started() {
gtasksPreferenceService.recordSyncStart(); gtasksPreferenceService.recordSyncStart();
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
@Override @Override
public void finished() { public void finished() {
gtasksPreferenceService.stopOngoing(); gtasksPreferenceService.stopOngoing();
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
} }
} }

@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.BroadcastReceiver; 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.Bundle; import android.os.Bundle;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
@ -15,10 +14,10 @@ import android.widget.ListView;
import com.todoroo.astrid.activity.TaskListActivity; import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.adapter.FilterAdapter; import com.todoroo.astrid.adapter.FilterAdapter;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.api.FilterListItem;
import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.filters.FilterCounter; import org.tasks.filters.FilterCounter;
import org.tasks.filters.FilterProvider; import org.tasks.filters.FilterProvider;
@ -67,6 +66,7 @@ public class NavigationDrawerFragment extends InjectingFragment {
@Inject Theme theme; @Inject Theme theme;
@Inject ThemeCache themeCache; @Inject ThemeCache themeCache;
@Inject Locale locale; @Inject Locale locale;
@Inject LocalBroadcastManager localBroadcastManager;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -156,10 +156,10 @@ public class NavigationDrawerFragment extends InjectingFragment {
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
if(adapter != null) { if(adapter != null) {
adapter.unregisterRecevier(); localBroadcastManager.unregisterReceiver(adapter.getFilterListUpdateReceiver());
} }
try { try {
getActivity().unregisterReceiver(refreshReceiver); localBroadcastManager.unregisterReceiver(refreshReceiver);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Might not have fully initialized // Might not have fully initialized
Timber.e(e, e.getMessage()); Timber.e(e, e.getMessage());
@ -238,13 +238,12 @@ public class NavigationDrawerFragment extends InjectingFragment {
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if(adapter != null) { if(adapter != null) {
adapter.registerRecevier(); localBroadcastManager.registerRefreshReceiver(adapter.getFilterListUpdateReceiver());
adapter.populateList();
} }
IntentFilter intentFilter = new IntentFilter(); localBroadcastManager.registerRefreshReceiver(refreshReceiver);
intentFilter.addAction(AstridApiConstants.BROADCAST_EVENT_REFRESH); localBroadcastManager.registerRefreshListReceiver(refreshReceiver);
intentFilter.addAction(AstridApiConstants.BROADCAST_EVENT_REFRESH_LISTS);
getActivity().registerReceiver(refreshReceiver, intentFilter);
repopulateList(); repopulateList();
} }
@ -262,9 +261,9 @@ public class NavigationDrawerFragment extends InjectingFragment {
return; return;
} }
String action = intent.getAction(); String action = intent.getAction();
if (AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(action)) { if (LocalBroadcastManager.REFRESH.equals(action)) {
adapter.refreshFilterCount(); adapter.refreshFilterCount();
} else if (AstridApiConstants.BROADCAST_EVENT_REFRESH_LISTS.equals(action)) { } else if (LocalBroadcastManager.REFRESH_LIST.equals(action)) {
repopulateList(); repopulateList();
} }
} }

@ -0,0 +1,25 @@
package org.tasks.widget;
import android.content.ComponentName;
import android.content.Context;
import org.tasks.R;
import org.tasks.injection.ForApplication;
import javax.inject.Inject;
public class AppWidgetManager {
private final android.appwidget.AppWidgetManager appWidgetManager;
private Context context;
@Inject
public AppWidgetManager(@ForApplication Context context) {
this.context = context;
appWidgetManager = android.appwidget.AppWidgetManager.getInstance(context);
}
public void updateWidgets() {
int[] widgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, TasksWidget.class));
appWidgetManager.notifyAppWidgetViewDataChanged(widgetIds, R.id.list_view);
}
}

@ -3,7 +3,10 @@ package org.tasks.widget;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
@ -44,11 +47,20 @@ public class ShortcutConfigActivity extends InjectingAppCompatActivity {
Filter filter = data.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER); Filter filter = data.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER);
String filterId = defaultFilterProvider.getFilterPreferenceValue(filter); String filterId = defaultFilterProvider.getFilterPreferenceValue(filter);
Intent shortcutIntent = TaskIntents.getTaskListByIdIntent(this, filterId); Intent shortcutIntent = TaskIntents.getTaskListByIdIntent(this, filterId);
Bitmap bitmap = ((BitmapDrawable) ContextCompat.getDrawable(this, R.mipmap.ic_launcher)).getBitmap();
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, filter.listingTitle); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, filter.listingTitle);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap); Drawable launcher = ContextCompat.getDrawable(this, R.mipmap.ic_launcher);
if (launcher instanceof BitmapDrawable) {
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, ((BitmapDrawable) launcher).getBitmap());
} else if (launcher instanceof AdaptiveIconDrawable) {
Bitmap bitmap = Bitmap.createBitmap(launcher.getIntrinsicWidth(), launcher.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
launcher.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
launcher.draw(canvas);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
}
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
setResult(RESULT_OK, intent); setResult(RESULT_OK, intent);
} }

@ -11,9 +11,9 @@ import android.net.Uri;
import android.view.View; import android.view.View;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import com.google.common.base.Strings;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import org.tasks.Broadcaster;
import org.tasks.R; import org.tasks.R;
import org.tasks.injection.BroadcastComponent; import org.tasks.injection.BroadcastComponent;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
@ -22,6 +22,7 @@ import org.tasks.intents.TaskIntents;
import org.tasks.locale.Locale; import org.tasks.locale.Locale;
import org.tasks.preferences.DefaultFilterProvider; import org.tasks.preferences.DefaultFilterProvider;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.receivers.CompleteTaskReceiver;
import org.tasks.themes.ThemeCache; import org.tasks.themes.ThemeCache;
import org.tasks.themes.ThemeColor; import org.tasks.themes.ThemeColor;
import org.tasks.themes.WidgetTheme; import org.tasks.themes.WidgetTheme;
@ -34,14 +35,12 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastJellybeanMR1; import static com.todoroo.andlib.utility.AndroidUtilities.atLeastJellybeanMR1;
import static com.todoroo.astrid.api.AstridApiConstants.BROADCAST_EVENT_REFRESH;
import static org.tasks.intents.TaskIntents.getEditTaskIntent; import static org.tasks.intents.TaskIntents.getEditTaskIntent;
public class TasksWidget extends InjectingAppWidgetProvider { public class TasksWidget extends InjectingAppWidgetProvider {
private static final int flags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP; private static final int flags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP;
@Inject Broadcaster broadcaster;
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject DefaultFilterProvider defaultFilterProvider; @Inject DefaultFilterProvider defaultFilterProvider;
@Inject ThemeCache themeCache; @Inject ThemeCache themeCache;
@ -58,9 +57,18 @@ public class TasksWidget extends InjectingAppWidgetProvider {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent); super.onReceive(context, intent);
switch(intent.getAction()) { String action = intent.getAction();
if (Strings.isNullOrEmpty(action)) {
return;
}
switch(action) {
case COMPLETE_TASK: case COMPLETE_TASK:
broadcaster.toggleCompletedState(intent.getLongExtra(EXTRA_ID, 0)); Intent completionIntent = new Intent(context, CompleteTaskReceiver.class);
completionIntent.putExtra(CompleteTaskReceiver.TASK_ID, intent.getLongExtra(EXTRA_ID, 0));
completionIntent.putExtra(CompleteTaskReceiver.TOGGLE_STATE, true);
context.sendBroadcast(completionIntent);
break; break;
case EDIT_TASK: case EDIT_TASK:
long taskId = intent.getLongExtra(EXTRA_ID, 0); long taskId = intent.getLongExtra(EXTRA_ID, 0);
@ -69,11 +77,6 @@ public class TasksWidget extends InjectingAppWidgetProvider {
editTaskIntent.setFlags(flags); editTaskIntent.setFlags(flags);
context.startActivity(editTaskIntent); context.startActivity(editTaskIntent);
break; break;
case BROADCAST_EVENT_REFRESH:
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] widgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, TasksWidget.class));
appWidgetManager.notifyAppWidgetViewDataChanged(widgetIds, R.id.list_view);
break;
} }
} }

@ -8,7 +8,7 @@ import android.preference.Preference;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import org.tasks.Broadcaster; import org.tasks.LocalBroadcastManager;
import org.tasks.R; import org.tasks.R;
import org.tasks.activities.ColorPickerActivity; import org.tasks.activities.ColorPickerActivity;
import org.tasks.activities.FilterSelectionActivity; import org.tasks.activities.FilterSelectionActivity;
@ -42,7 +42,7 @@ public class WidgetConfigActivity extends InjectingPreferenceActivity implements
@Inject Tracker tracker; @Inject Tracker tracker;
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject Broadcaster broadcaster; @Inject LocalBroadcastManager localBroadcastManager;
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject DefaultFilterProvider defaultFilterProvider; @Inject DefaultFilterProvider defaultFilterProvider;
@Inject ThemeCache themeCache; @Inject ThemeCache themeCache;
@ -154,7 +154,7 @@ public class WidgetConfigActivity extends InjectingPreferenceActivity implements
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
broadcaster.refresh(); localBroadcastManager.broadcastRefresh();
// force update after setting preferences // force update after setting preferences
Intent intent = new Intent(this, TasksWidget.class); Intent intent = new Intent(this, TasksWidget.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#607D8B</color>
</resources>

@ -7,7 +7,7 @@
android:minHeight="110dp" android:minHeight="110dp"
android:minResizeWidth="110dp" android:minResizeWidth="110dp"
android:minResizeHeight="110dp" android:minResizeHeight="110dp"
android:updatePeriodMillis="86400000" android:updatePeriodMillis="1800000"
android:initialLayout="@layout/scrollable_widget" android:initialLayout="@layout/scrollable_widget"
android:initialKeyguardLayout="@layout/scrollable_widget" android:initialKeyguardLayout="@layout/scrollable_widget"
android:resizeMode="horizontal|vertical" /> android:resizeMode="horizontal|vertical" />

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Loading…
Cancel
Save