Merge pull request #184 from sbosley/120518_sb_user_reengagement

120518 sb user reengagement
pull/14/head
sbosley 12 years ago
commit 8e2302310c

@ -209,6 +209,12 @@
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
<receiver android:name="com.todoroo.astrid.reminders.ReengagementReceiver">
<intent-filter>
<action android:name="com.timsu.astrid.SHOW_REENGAGEMENT"/>
</intent-filter>
</receiver>
<!-- ======================================================== Services = -->

@ -43,7 +43,6 @@ import com.todoroo.astrid.activity.DisposableTaskListFragment;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.repeats.RepeatControlSet;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.ui.NumberPicker;
@ -66,13 +65,6 @@ public class NotificationFragment extends DisposableTaskListFragment implements
private long taskId;
@Override
public void onCreate(Bundle savedInstanceState) {
StartupService.bypassInitialization();
super.onCreate(savedInstanceState);
}
/* (non-Javadoc)
* @see com.todoroo.astrid.activity.TaskListActivity#onActivityCreated(android.os.Bundle)
*/

@ -0,0 +1,59 @@
package com.todoroo.astrid.reminders;
import android.content.res.Resources;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import com.timsu.astrid.R;
import com.todoroo.astrid.activity.DisposableTaskListFragment;
import com.todoroo.astrid.service.ThemeService;
public class ReengagementFragment extends DisposableTaskListFragment {
public static final String EXTRA_TEXT = "dialogText"; //$NON-NLS-1$
@Override
protected void initializeData() {
// hide quick add
getView().findViewById(R.id.taskListFooter).setVisibility(View.GONE);
Resources r = getActivity().getResources();
super.initializeData();
TextView snooze = (TextView) getView().findViewById(R.id.reminder_snooze);
snooze.setBackgroundColor(r.getColor(ThemeService.getThemeColor()));
TextView reminder = (TextView) getView().findViewById(R.id.reminder_message);
if (taskAdapter.getCount() == 0) {
snooze.setText(R.string.rmd_reengage_add_tasks);
snooze.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
quickAddBar.performButtonClick();
}
});
} else {
snooze.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
}
reminder.setText(extras.getString(EXTRA_TEXT));
}
@Override
protected View getListBody(ViewGroup root) {
ViewGroup parent = (ViewGroup) getActivity().getLayoutInflater().inflate(R.layout.task_list_body_reengagement, root, false);
View taskListView = super.getListBody(parent);
parent.addView(taskListView, 0);
return parent;
}
}

@ -0,0 +1,125 @@
package com.todoroo.astrid.reminders;
import org.json.JSONObject;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.NotificationManager;
import com.todoroo.andlib.service.NotificationManager.AndroidNotificationManager;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.api.FilterWithCustomIntent;
import com.todoroo.astrid.core.SortHelper;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.TaskApiDao.TaskCriteria;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.service.abtesting.ABChooser;
import com.todoroo.astrid.service.abtesting.ABTests;
import com.todoroo.astrid.utility.Constants;
public class ReengagementReceiver extends BroadcastReceiver {
@Autowired ActFmPreferenceService actFmPreferenceService;
@Autowired TaskService taskService;
private static final int TASK_LIMIT = 3;
@Override
public void onReceive(Context context, Intent intent) {
DependencyInjectionService.getInstance().inject(this);
if (ABChooser.readChoiceForTest(ABTests.AB_TEST_REENGAGEMENT_ENABLED) == 0)
return;
int reengagementReminders = Preferences.getInt(ReengagementService.PREF_REENGAGEMENT_COUNT, 1);
Preferences.setInt(ReengagementService.PREF_REENGAGEMENT_COUNT, reengagementReminders + 1);
Intent notifIntent = new Intent(context, TaskListActivity.class);
QueryTemplate template = new QueryTemplate().where(TaskCriteria.activeVisibleMine());
String sql = SortHelper.adjustQueryForFlagsAndSort(template.toString(), 0, SortHelper.SORT_AUTO) + " LIMIT " + TASK_LIMIT; //$NON-NLS-1$
boolean hasTasks = false;
TodorooCursor<Task> tasks = taskService.query(Query.select(Task.ID).where(TaskCriteria.activeVisibleMine()).limit(TASK_LIMIT));
try {
hasTasks = tasks.getCount() > 0;
} finally {
tasks.close();
}
String title = Notifications.getRandomReminder(context.getResources().getStringArray(R.array.rmd_reengage_notif_titles));
if (title.contains("%s")) { //$NON-NLS-1$
String name = ""; //$NON-NLS-1$
if (actFmPreferenceService.isLoggedIn()) {
JSONObject thisUser = ActFmPreferenceService.thisUser();
name = thisUser.optString("first_name"); //$NON-NLS-1$
if (TextUtils.isEmpty(name))
name = thisUser.optString("name"); //$NON-NLS-1$
if (TextUtils.isEmpty(name))
name = context.getString(R.string.rmd_reengage_name_default);
}
title = String.format(title, name);
}
String text = Notifications.getRandomReminder(context.getResources().getStringArray(hasTasks ? R.array.rmd_reengage_dialog_options : R.array.rmd_reengage_dialog_empty_options));
FilterWithCustomIntent filter = new FilterWithCustomIntent(context.getString(R.string.rmd_NoA_filter),
context.getString(R.string.rmd_NoA_filter),
sql,
null);
filter.customTaskList = new ComponentName(context, ReengagementFragment.class);
filter.customExtras = new Bundle();
filter.customExtras.putString(ReengagementFragment.EXTRA_TEXT, text);
notifIntent.setAction("NOTIFY_reengagement"); //$NON-NLS-1$
notifIntent.putExtra(TaskListFragment.TOKEN_FILTER, filter);
notifIntent.putExtra(ReengagementFragment.EXTRA_TEXT, text);
notifIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
notifIntent.putExtra(TaskListActivity.TOKEN_SOURCE, Constants.SOURCE_REENGAGEMENT);
NotificationManager manager = new AndroidNotificationManager(context);
Notification notification = new Notification(R.drawable.notif_astrid,
text, System.currentTimeMillis());
PendingIntent pendingIntent = PendingIntent.getActivity(context,
0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(context,
title,
text,
pendingIntent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
if(Preferences.getBoolean(R.string.p_rmd_persistent, true)) {
notification.flags |= Notification.FLAG_NO_CLEAR |
Notification.FLAG_SHOW_LIGHTS;
notification.ledOffMS = 5000;
notification.ledOnMS = 700;
notification.ledARGB = Color.YELLOW;
} else {
notification.defaults = Notification.DEFAULT_LIGHTS;
}
manager.notify(0, notification);
ReengagementService.scheduleReengagementAlarm(context);
}
}

@ -0,0 +1,50 @@
package com.todoroo.astrid.reminders;
import java.util.Date;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.utility.Constants;
public final class ReengagementService {
private static final int REQUEST_CODE = 10;
private static final int DAYS_INTERVAL = 2;
public static final String PREF_REENGAGEMENT_COUNT = "pref_reengagement_count"; //$NON-NLS-1$
public static final String BROADCAST_SHOW_REENGAGEMENT = Constants.PACKAGE + ".SHOW_REENGAGEMENT"; //$NON-NLS-1$
public static void scheduleReengagementAlarm(Context context) {
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(BROADCAST_SHOW_REENGAGEMENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, 0);
am.cancel(pendingIntent);
long time = getNextReminderTime();
am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
}
private static long getNextReminderTime() {
int reengagementReminders = Preferences.getInt(PREF_REENGAGEMENT_COUNT, 1);
int days;
if (reengagementReminders >= 4)
days = DAYS_INTERVAL * 4;
else
days = DAYS_INTERVAL * reengagementReminders;
Date date = new Date(DateUtilities.now() + DateUtilities.ONE_DAY * days / 1000L * 1000L);
date.setHours(18);
date.setMinutes(0);
date.setSeconds(0);
return date.getTime();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 B

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 B

After

Width:  |  Height:  |  Size: 2.3 KiB

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="100">
<!-- List body goes here -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/speech_bubble_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginLeft="2dip"
android:layout_marginRight="5dip"
android:layout_marginBottom="10dip"
android:gravity="bottom">
<ImageView
android:id="@+id/astridIcon"
android:layout_width="75dip"
android:layout_height="75dip"
android:layout_marginBottom="5dip"
android:src="@drawable/icon"
android:scaleType="fitCenter"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"/>
<LinearLayout
android:id="@+id/speech_bubble_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginRight="5dip"
android:layout_marginBottom="5dip"
android:minHeight="60dip"
android:layout_alignParentBottom="true"
android:gravity="center_vertical"
android:background="@drawable/speech_bubble_reminder"
android:layout_toRightOf="@id/astridIcon">
<TextView
android:id="@+id/reminder_message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.TLA_Reminder"
android:gravity="center_vertical"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/reminder_snooze"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginBottom="10dip"
android:textColor="@android:color/white"
android:textSize="24sp"
android:text="@string/rmd_NoA_snooze"
android:background="#707070"/>
</LinearLayout>
</LinearLayout>

@ -60,6 +60,39 @@
<!-- Prefix for reminder dialog title -->
<string name="rmd_NoA_dlg_title">Reminder:</string>
<!-- ==================================================== user reengagement == -->
<string-array name="rmd_reengage_notif_titles">
<item>A note from Astrid</item>
<item>Memo for %s.</item> <!-- %s -> first name -->
<item>Your Astrid digest</item>
<item>Reminders from Astrid</item>
</string-array>
<string name="rmd_reengage_name_default">you</string>
<string name="rmd_reengage_snooze">Snooze all</string>
<string name="rmd_reengage_add_tasks">Add a task</string>
<string-array name="rmd_reengage_dialog_options">
<item>Time to shorten your to-do list!</item>
<item>Dear sir or madam, some tasks await your inspection!</item>
<item>Hi there, could you take a look at these?</item>
<item>I\'ve got some tasks with your name on them!</item>
<item>A fresh batch of tasks for you today!</item>
<item>You look fabulous! Ready to get started?</item>
<item>A lovely day for getting some work done, I think!</item>
</string-array>
<string-array name="rmd_reengage_dialog_empty_options">
<item>Don\'t you want to get organized?</item>
<item>I\'m Astrid! I\'m here to help you do more!</item>
<item>You look busy! Let me take some of those tasks off of your plate.</item>
<item>I can help you keep track of all of the details in your life.</item>
<item>You\'re serious about getting more done? So am I!</item>
<item>Pleasure to make your acquaintance!</item>
</string-array>
<!-- ============================================= reminder preferences == -->
<!-- Reminder Preference Screen Title -->

@ -668,6 +668,8 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
case Constants.SOURCE_C2DM:
StatisticsService.reportEvent(StatisticsConstants.LAUNCH_FROM_C2DM);
break;
case Constants.SOURCE_REENGAGEMENT:
StatisticsService.reportEvent(StatisticsConstants.LAUNCH_FROM_REENGAGEMENT);
}
getIntent().putExtra(TOKEN_SOURCE, Constants.SOURCE_DEFAULT); // Only report source once
}

@ -40,6 +40,7 @@ import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.reminders.ReengagementService;
import com.todoroo.astrid.reminders.ReminderStartupReceiver;
import com.todoroo.astrid.service.abtesting.ABChooser;
import com.todoroo.astrid.service.abtesting.ABTestInvoker;
@ -105,6 +106,7 @@ public class StartupService {
if(hasStartedUp || context == null)
return;
// sets up context manager
ContextManager.setContext(context);
@ -193,6 +195,7 @@ public class StartupService {
am.setInexactRepeating(AlarmManager.RTC, 0,
Constants.WIDGET_UPDATE_INTERVAL, pendingIntent);
ReengagementService.scheduleReengagementAlarm(context);
taskService.cleanup();
// if sync ongoing flag was set, clear it

@ -24,6 +24,7 @@ public class StatisticsConstants {
public static final String LAUNCH_FROM_PPW = "launch-from-ppw";
public static final String LAUNCH_FROM_WIDGET = "launch-from-widget";
public static final String LAUNCH_FROM_C2DM = "launch-from-c2dm";
public static final String LAUNCH_FROM_REENGAGEMENT = "launch-from-reengagement";
public static final String LOCALE_EDIT_ALERTS_NO_PLUGIN = "locale-edit-alerts-no-plugin";
public static final String LOCALE_EDIT_ALERTS = "locale-edit-alerts";
public static final String WIDGET_CONFIG = "widget-config";

@ -115,11 +115,14 @@ public class ABTests {
}
private void initialize() { // Set up
addTest(AB_TEST_PRODUCTEEV_ENABLED, new int[] { 1, 1 },
new int[] { 1, 0 }, new String[] { "producteev-disabled", "producteev-enabled" }); //$NON-NLS-1$ //$NON-NLS-2$
addTest(AB_TEST_REENGAGEMENT_ENABLED, new int[] { 1, 9 },
new int[] { 1, 9 }, new String[] { "reengagement-disabled", "reengagement-enabled" }); //$NON-NLS-1$ //$NON-NLS-2$
}
public static final String AB_TEST_PRODUCTEEV_ENABLED = "producteev"; //$NON-NLS-1$
public static final String AB_TEST_REENGAGEMENT_ENABLED = "reengagement"; ////$NON-NLS-1$
}

@ -51,6 +51,7 @@ public final class Constants {
public static final int SOURCE_WIDGET = 2;
public static final int SOURCE_PPWIDGET = 3;
public static final int SOURCE_C2DM = 4;
public static final int SOURCE_REENGAGEMENT = 5;
// --- notification id's

Loading…
Cancel
Save