A/B Testing and Feature flipping infrastructure. AB testing of new user experience.

pull/14/head
Sam Bosley 13 years ago
parent 58fe374d20
commit 7c364a4ff7

@ -36,14 +36,20 @@ public class HttpRestClient implements RestClient {
private static final int TIMEOUT_MILLIS = 30000;
private static WeakReference<HttpClient> httpClient = null;
private WeakReference<HttpClient> httpClient = null;
protected boolean debug = false;
private int timeout = TIMEOUT_MILLIS;
public HttpRestClient() {
DependencyInjectionService.getInstance().inject(this);
}
public HttpRestClient(int timeout) {
super();
this.timeout = timeout;
}
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the
@ -72,11 +78,11 @@ public class HttpRestClient implements RestClient {
return sb.toString();
}
private synchronized static HttpClient getClient() {
private synchronized HttpClient getClient() {
if (httpClient == null || httpClient.get() == null) {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_MILLIS);
HttpConnectionParams.setSoTimeout(params, TIMEOUT_MILLIS);
HttpConnectionParams.setConnectionTimeout(params, timeout);
HttpConnectionParams.setSoTimeout(params, timeout);
HttpClient client = new DefaultHttpClient(params);
httpClient = new WeakReference<HttpClient>(client);
return client;

@ -73,16 +73,19 @@
<!-- ====================================================== Activities = -->
<!-- Activity that displays task list -->
<activity android:name="com.todoroo.astrid.welcome.WelcomeLogin"
android:windowSoftInputMode="stateHidden">
</activity>
<activity android:name="com.todoroo.astrid.welcome.WelcomeScreen"
<activity android:name="com.todoroo.astrid.welcome.SplashScreenLauncher"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.todoroo.astrid.welcome.WelcomeLogin"
android:windowSoftInputMode="stateHidden">
</activity>
<activity android:name="com.todoroo.astrid.welcome.WelcomeGraphic"
android:windowSoftInputMode="stateHidden">
</activity>
<activity android:name="com.todoroo.astrid.activity.TaskListActivity"
android:windowSoftInputMode="stateHidden">
<intent-filter>

@ -69,6 +69,7 @@ import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncProvider;
import com.todoroo.astrid.gtasks.auth.ModernAuthManager;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TaskService;
@ -82,9 +83,12 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
public static final String APP_ID = "183862944961271"; //$NON-NLS-1$
@Autowired protected ExceptionService exceptionService;
@Autowired protected TaskService taskService;
@Autowired protected ActFmPreferenceService actFmPreferenceService;
@Autowired
protected ExceptionService exceptionService;
@Autowired
protected TaskService taskService;
@Autowired
protected ActFmPreferenceService actFmPreferenceService;
private final ActFmInvoker actFmInvoker = new ActFmInvoker();
private Facebook facebook;
@ -136,11 +140,8 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
errors = (TextView) findViewById(R.id.error);
LoginButton loginButton = (LoginButton) findViewById(R.id.fb_login);
loginButton.init(this, facebook, this, new String[] {
"email",
"offline_access",
"publish_stream"
});
loginButton.init(this, facebook, this, new String[] { "email",
"offline_access", "publish_stream" });
initializeUI();
@ -152,8 +153,26 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
setResult(RESULT_CANCELED);
}
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
}
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
}
@Override
protected void onStop() {
StatisticsService.sessionStop(this);
super.onStop();
}
protected void recordPageView() {
StatisticsService.reportEvent("actfm-login-show"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_SHOW);
}
protected void initializeUI() {
@ -168,12 +187,14 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
@Override
@SuppressWarnings("nls")
public void onClick(View arg0) {
Intent intent = new Intent(ActFmLoginActivity.this, OAuthLoginActivity.class);
Intent intent = new Intent(ActFmLoginActivity.this,
OAuthLoginActivity.class);
try {
String url = actFmInvoker.createFetchUrl("user_oauth", "provider", "google");
String url = actFmInvoker.createFetchUrl("user_oauth",
"provider", "google");
intent.putExtra(OAuthLoginActivity.URL_TOKEN, url);
startActivityForResult(intent, REQUEST_CODE_OAUTH);
StatisticsService.reportEvent("actfm-login-gl-start"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_GL_START);
} catch (UnsupportedEncodingException e) {
handleError(e);
} catch (NoSuchAlgorithmException e) {
@ -189,7 +210,8 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
body.setOrientation(LinearLayout.VERTICAL);
body.setPadding(10, 0, 10, 0);
final EditText name = addEditField(body, R.string.actfm_ALA_name_label);
final EditText name = addEditField(body,
R.string.actfm_ALA_name_label);
final AtomicReference<AlertDialog> dialog = new AtomicReference<AlertDialog>();
final AtomicBoolean isNew = new AtomicBoolean(true);
@ -200,10 +222,11 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
isNew.set(!isNew.get());
int nameIndex = body.indexOfChild(name);
int visibility = isNew.get() ? View.VISIBLE : View.GONE;
toggleNew.setText(isNew.get() ? R.string.actfm_ALA_pw_returning :
R.string.actfm_ALA_pw_new);
dialog.get().setTitle(isNew.get() ? R.string.actfm_ALA_signup_title :
R.string.actfm_ALA_login_title);
toggleNew.setText(isNew.get() ? R.string.actfm_ALA_pw_returning
: R.string.actfm_ALA_pw_new);
dialog.get().setTitle(
isNew.get() ? R.string.actfm_ALA_signup_title
: R.string.actfm_ALA_login_title);
body.getChildAt(nameIndex - 1).setVisibility(visibility);
body.getChildAt(nameIndex).setVisibility(visibility);
}
@ -211,38 +234,38 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
toggleNew.setText(R.string.actfm_ALA_pw_returning);
body.addView(toggleNew, 0);
final EditText email = addEditField(body, R.string.actfm_ALA_email_label);
final EditText email = addEditField(body,
R.string.actfm_ALA_email_label);
getCredentials(new OnGetCredentials() {
@Override
public void getCredentials(String[] accounts) {
if(accounts != null && accounts.length > 0)
if (accounts != null && accounts.length > 0)
email.setText(accounts[0]);
}
});
final EditText password = addEditField(body, R.string.actfm_ALA_password_label);
final EditText password = addEditField(body,
R.string.actfm_ALA_password_label);
password.setTransformationMethod(new PasswordTransformationMethod());
dialog.set(new AlertDialog.Builder(ActFmLoginActivity.this)
.setView(body)
.setIcon(R.drawable.icon_32)
.setTitle(R.string.actfm_ALA_signup_title)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dlg, int which) {
String nameString = isNew.get() ? name.getText().toString() : null;
authenticate(email.getText().toString(), nameString,
ActFmInvoker.PROVIDER_PASSWORD, password.getText().toString());
if(isNew.get())
StatisticsService.reportEvent("actfm-login-pw"); //$NON-NLS-1$
else
StatisticsService.reportEvent("actfm-signup-pw"); //$NON-NLS-1$
}
})
.setNegativeButton(android.R.string.cancel, null)
.show());
dialog.set(new AlertDialog.Builder(ActFmLoginActivity.this).setView(
body).setIcon(R.drawable.icon_32).setTitle(
R.string.actfm_ALA_signup_title).setPositiveButton(
android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dlg, int which) {
String nameString = isNew.get() ? name.getText().toString()
: null;
authenticate(email.getText().toString(),
nameString, ActFmInvoker.PROVIDER_PASSWORD,
password.getText().toString());
if (isNew.get())
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_PW);
else
StatisticsService.reportEvent(StatisticsConstants.ACTFM_SIGNUP_PW);
}
}).setNegativeButton(android.R.string.cancel, null).show());
dialog.get().setOwnerActivity(ActFmLoginActivity.this);
}
@ -297,7 +320,7 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
authenticate(email, name, ActFmInvoker.PROVIDER_FACEBOOK,
facebook.getAccessToken());
StatisticsService.reportEvent("actfm-login-fb"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_FB);
} catch (FacebookError e) {
handleError(e);
} catch (JSONException e) {
@ -331,13 +354,21 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
// --- utilities
public void authenticate(String email, String name, String provider, String secret) {
if(progressDialog == null)
progressDialog = DialogUtilities.progressDialog(this, getString(R.string.DLG_please_wait));
@SuppressWarnings("nls")
public void authenticate(String email, String name, String provider,
String secret) {
if (progressDialog == null)
progressDialog = DialogUtilities.progressDialog(this,
getString(R.string.DLG_please_wait));
try {
JSONObject result = actFmInvoker.authenticate(email, name, provider, secret);
JSONObject result = actFmInvoker.authenticate(email, name,
provider, secret);
String token = actFmInvoker.getToken();
if (result.optBoolean("new")) { // Report new user statistic
StatisticsService.reportEvent(StatisticsConstants.ACTFM_NEW_USER, "provider", provider);
}
postAuthenticate(result, token);
} catch (IOException e) {
handleError(e);
@ -352,14 +383,17 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
Preferences.setLong(ActFmPreferenceService.PREF_USER_ID,
result.optLong("id"));
Preferences.setString(ActFmPreferenceService.PREF_NAME, result.optString("name"));
Preferences.setString(ActFmPreferenceService.PREF_EMAIL, result.optString("email"));
Preferences.setString(ActFmPreferenceService.PREF_PICTURE, result.optString("picture"));
Preferences.setString(ActFmPreferenceService.PREF_NAME,
result.optString("name"));
Preferences.setString(ActFmPreferenceService.PREF_EMAIL,
result.optString("email"));
Preferences.setString(ActFmPreferenceService.PREF_PICTURE,
result.optString("picture"));
setResult(RESULT_OK);
finishAndShowNext();
if(!noSync) {
if (!noSync) {
new ActFmSyncProvider().synchronize(this);
}
@ -388,17 +422,17 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
@SuppressWarnings("nls")
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == RESULT_CANCELED)
if (resultCode == RESULT_CANCELED)
return;
if(requestCode == REQUEST_CODE_GOOGLE_ACCOUNTS){
String accounts[] = data.getExtras().getStringArray(GoogleLoginServiceConstants.ACCOUNTS_KEY);
if (requestCode == REQUEST_CODE_GOOGLE_ACCOUNTS) {
String accounts[] = data.getExtras().getStringArray(
GoogleLoginServiceConstants.ACCOUNTS_KEY);
credentialsListener.getCredentials(accounts);
} else if(requestCode == LoginButton.REQUEST_CODE_FACEBOOK) {
if(data == null)
} else if (requestCode == LoginButton.REQUEST_CODE_FACEBOOK) {
if (data == null)
return;
String error = data.getStringExtra("error");
@ -406,26 +440,27 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
error = data.getStringExtra("error_type");
}
String token = data.getStringExtra("access_token");
if(error != null) {
if (error != null) {
onFBAuthFail(error);
} else if(token == null) {
} else if (token == null) {
onFBAuthFail("Something went wrong! Please try again.");
} else {
facebook.setAccessToken(token);
onFBAuthSucceed();
}
errors.setVisibility(View.GONE);
} else if(requestCode == REQUEST_CODE_OAUTH) {
} else if (requestCode == REQUEST_CODE_OAUTH) {
String result = data.getStringExtra(OAuthLoginActivity.DATA_RESPONSE);
try {
JSONObject json = new JSONObject(result);
postAuthenticate(json, json.getString("token"));
StatisticsService.reportEvent("actfm-login-gl-success"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_GL_SUCCESS);
} catch (JSONException e) {
handleError(e);
}
}
}
public interface OnGetCredentials {
public void getCredentials(String[] accounts);
}
@ -434,10 +469,11 @@ public class ActFmLoginActivity extends Activity implements AuthListener {
public void getCredentials(OnGetCredentials onGetCredentials) {
credentialsListener = onGetCredentials;
if(Integer.parseInt(Build.VERSION.SDK) >= 7)
if (Integer.parseInt(Build.VERSION.SDK) >= 7)
credentialsListener.getCredentials(ModernAuthManager.getAccounts(this));
else
GoogleLoginServiceHelper.getAccount(this, REQUEST_CODE_GOOGLE_ACCOUNTS, false);
GoogleLoginServiceHelper.getAccount(this,
REQUEST_CODE_GOOGLE_ACCOUNTS, false);
}
}

@ -47,6 +47,7 @@ import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TagDataService;
import com.todoroo.astrid.service.TaskService;
@ -503,7 +504,7 @@ public class EditPeopleControlSet implements TaskEditControlSet {
saveToast += "\n" +
activity.getString(R.string.actfm_EPA_emailed_toast,
activity.getResources().getQuantityString(R.plurals.Npeople, count, count));
StatisticsService.reportEvent("actfm-task-shared"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_TASK_SHARED);
}
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH);

@ -71,6 +71,7 @@ import com.todoroo.astrid.dao.UpdateDao;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.Update;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TagDataService;
import com.todoroo.astrid.tags.TagFilterExposer;
@ -668,6 +669,10 @@ public class TagViewActivity extends TaskListActivity implements OnTabChangeList
return;
}
int oldMemberCount = tagData.getValue(TagData.MEMBER_COUNT);
if (members.length() > oldMemberCount) {
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LIST_SHARED);
}
tagData.setValue(TagData.MEMBERS, members.toString());
tagData.setValue(TagData.MEMBER_COUNT, members.length());
tagData.setFlag(TagData.FLAGS, TagData.FLAG_SILENT, isSilent.isChecked());
@ -777,7 +782,7 @@ public class TagViewActivity extends TaskListActivity implements OnTabChangeList
addCommentField.setText(""); //$NON-NLS-1$
refreshUpdatesList();
StatisticsService.reportEvent("actfm-tag-comment"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_TAG_COMMENT);
}
@Override

@ -35,6 +35,7 @@ import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.notes.NoteMetadata;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.sync.SyncProvider;
import com.todoroo.astrid.sync.SyncProviderUtilities;
@ -153,7 +154,7 @@ public class ActFmSyncProvider extends SyncProvider<ActFmTaskContainer> {
} catch (Exception e) {
handleException("actfm-sync", e, true); //$NON-NLS-1$
} finally {
StatisticsService.reportEvent("actfm-sync-finished",
StatisticsService.reportEvent(StatisticsConstants.ACTFM_SYNC_FINISHED,
"success", Boolean.toString(syncSuccess)); //$NON-NLS-1$
}
}
@ -298,7 +299,7 @@ public class ActFmSyncProvider extends SyncProvider<ActFmTaskContainer> {
if(task.task.isSaved()) {
Task local = PluginServices.getTaskService().fetchById(task.task.getId(), Task.COMPLETION_DATE);
if(task.task.isCompleted() && !local.isCompleted())
StatisticsService.reportEvent("actfm-task-completed"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_TASK_COMPLETED);
} else { // Set default reminders for remotely created tasks
TaskDao.setDefaultReminders(task.task);
}

@ -56,6 +56,7 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.Update;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TagDataService;
import com.todoroo.astrid.service.TaskService;
@ -633,9 +634,9 @@ public final class ActFmSyncService {
if(remote.getValue(Task.USER_ID) == 0) {
if(!remote.isSaved())
StatisticsService.reportEvent("actfm-task-created");
StatisticsService.reportEvent(StatisticsConstants.ACTFM_TASK_CREATED);
else if(remote.isCompleted())
StatisticsService.reportEvent("actfm-task-completed");
StatisticsService.reportEvent(StatisticsConstants.ACTFM_TASK_COMPLETED);
}

@ -241,7 +241,6 @@ public class CustomFilterActivity extends ListActivity {
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override
@ -253,6 +252,7 @@ public class CustomFilterActivity extends ListActivity {
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
registerReceiver(filterCriteriaReceiver, new IntentFilter(AstridApiConstants.BROADCAST_SEND_CUSTOM_FILTER_CRITERIA));
populateCriteria();
}

@ -29,6 +29,7 @@ import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.TaskEditActivity.TaskEditControlSet;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gcal.Calendars.CalendarResult;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
/**
@ -150,7 +151,7 @@ public class GCalControlSet implements TaskEditControlSet {
if (((Preferences.getBoolean(R.string.p_default_addtocalendar_key, false) && !task.isSaved())
|| addToCalendar.isChecked()) &&
calendarUri == null) {
StatisticsService.reportEvent("create-calendar-event");
StatisticsService.reportEvent(StatisticsConstants.CREATE_CALENDAR_EVENT);
try{
Uri uri = Calendars.getCalendarContentUri(Calendars.CALENDAR_CONTENT_EVENTS);

@ -161,9 +161,20 @@ public class GtasksLoginActivity extends ListActivity {
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
}
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
}
@Override
protected void onStop() {
super.onStop();

@ -59,6 +59,7 @@ import com.todoroo.astrid.gtasks.api.UpdateRequest;
import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity;
import com.todoroo.astrid.gtasks.auth.GtasksTokenValidator;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.sync.SyncContainer;
import com.todoroo.astrid.sync.SyncProvider;
@ -204,7 +205,7 @@ public class GtasksSyncProvider extends SyncProvider<GtasksTaskContainer> {
} catch (IOException e) {
handleException("gtasks-sync", e, true); //$NON-NLS-1$
} finally {
StatisticsService.reportEvent("gtasks-sync-finished",
StatisticsService.reportEvent(StatisticsConstants.GTASKS_SYNC_FINISHED,
"success", Boolean.toString(syncSuccess)); //$NON-NLS-1$
}
}
@ -607,7 +608,7 @@ public class GtasksSyncProvider extends SyncProvider<GtasksTaskContainer> {
Task local = PluginServices.getTaskService().fetchById(task.task.getId(), Task.DUE_DATE, Task.COMPLETION_DATE);
mergeDates(task.task, local);
if(task.task.isCompleted() && !local.isCompleted())
StatisticsService.reportEvent("gtasks-task-completed"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.GTASKS_TASK_COMPLETED);
} else { // Set default reminders for remotely created tasks
TaskDao.setDefaultReminders(task.task);
}

@ -23,6 +23,7 @@ import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.twofortyfouram.SharedResources;
@ -189,9 +190,9 @@ public final class LocaleEditAlerts extends ExpandableListActivity {
.setPositiveButton(android.R.string.ok,
AddOnActivity.createAddOnClicker(LocaleEditAlerts.this, true))
.show();
StatisticsService.reportEvent("locale-edit-alerts-no-plugin"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LOCALE_EDIT_ALERTS_NO_PLUGIN);
} else {
StatisticsService.reportEvent("locale-edit-alerts"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LOCALE_EDIT_ALERTS);
}
}
@ -291,19 +292,20 @@ public final class LocaleEditAlerts extends ExpandableListActivity {
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
adapter.registerRecevier();
}
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
adapter.unregisterRecevier();
}
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override

@ -48,6 +48,7 @@ import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.Update;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.utility.Flags;
@ -271,7 +272,7 @@ public class EditNoteActivity extends ListActivity {
commentField.setText(""); //$NON-NLS-1$
setUpListAdapter();
StatisticsService.reportEvent("actfm-task-comment"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.ACTFM_TASK_COMMENT);
}
private final OnClickListener dismissCommentsListener = new OnClickListener() {

@ -42,6 +42,7 @@ import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.producteev.api.ApiAuthenticationException;
import com.todoroo.astrid.producteev.api.ProducteevInvoker;
import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
/**
@ -157,7 +158,7 @@ public class ProducteevLoginActivity extends Activity {
Preferences.setString(R.string.producteev_PPr_password, password);
ProducteevUtilities.INSTANCE.setToken(invoker.getToken());
StatisticsService.reportEvent("producteev-login"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.PRODUCTEEV_LOGIN);
synchronize();
} catch (ApiAuthenticationException e) {
@ -198,7 +199,7 @@ public class ProducteevLoginActivity extends Activity {
Preferences.setString(R.string.producteev_PPr_password, password);
ProducteevUtilities.INSTANCE.setToken(invoker.getToken());
StatisticsService.reportEvent("producteev-signup"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.PRODUCTEEV_SIGNUP);
synchronize();
} catch (Exception e) {
@ -230,9 +231,20 @@ public class ProducteevLoginActivity extends Activity {
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
}
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
}
@Override
protected void onStop() {
super.onStop();

@ -50,6 +50,7 @@ import com.todoroo.astrid.producteev.api.ApiServiceException;
import com.todoroo.astrid.producteev.api.ApiUtilities;
import com.todoroo.astrid.producteev.api.ProducteevInvoker;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.sync.SyncContainer;
import com.todoroo.astrid.sync.SyncProvider;
@ -250,7 +251,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
} catch (Exception e) {
handleException("pdv-sync", e, true); //$NON-NLS-1$
} finally {
StatisticsService.reportEvent("pdv-sync-finished",
StatisticsService.reportEvent(StatisticsConstants.PDV_SYNC_FINISHED,
"success", Boolean.toString(syncSuccess)); //$NON-NLS-1$
}
}
@ -610,7 +611,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
Task local = PluginServices.getTaskService().fetchById(task.task.getId(), Task.COMPLETION_DATE, Task.FLAGS);
task.task.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, local.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION));
if(task.task.isCompleted() && !local.isCompleted())
StatisticsService.reportEvent("pdv-task-completed"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.PDV_TASK_COMPLETED);
} else { // Set default reminders for remotely created tasks
TaskDao.setDefaultReminders(task.task);
}

@ -50,6 +50,7 @@ import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
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;
@ -81,7 +82,7 @@ public class NotificationActivity extends TaskListActivity implements OnTimeSetL
@Override
protected void onTaskCompleted(Task item) {
StatisticsService.reportEvent("task-completed-notification"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TASK_COMPLETED_NOTIFICATION);
}
@Override
@ -242,7 +243,7 @@ public class NotificationActivity extends TaskListActivity implements OnTimeSetL
task.setValue(Task.REMINDER_SNOOZE, time);
PluginServices.getTaskService().save(task);
finish();
StatisticsService.reportEvent("task-snooze"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TASK_SNOOZE);
}
}

@ -30,6 +30,7 @@ import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.astrid.activity.TaskEditActivity.TaskEditControlSet;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.ui.NumberPicker;
import com.todoroo.astrid.ui.NumberPickerDialog;
@ -250,7 +251,7 @@ public class RepeatControlSet implements TaskEditControlSet {
result = ""; //$NON-NLS-1$
else {
if(TextUtils.isEmpty(task.getValue(Task.RECURRENCE))) {
StatisticsService.reportEvent("repeat-task-create"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.REPEAT_TASK_CREATE);
}
RRule rrule = new RRule();

@ -27,6 +27,7 @@ import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.utility.Flags;
@ -61,7 +62,7 @@ public class RepeatTaskCompleteListener extends BroadcastReceiver {
return;
}
StatisticsService.reportEvent("v2-task-repeat"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.V2_TASK_REPEAT);
long hideUntil = task.getValue(Task.HIDE_UNTIL);
if(hideUntil > 0 && task.getValue(Task.DUE_DATE) > 0) {

@ -19,6 +19,7 @@ import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.utility.Constants;
@ -47,7 +48,7 @@ public class TimerPlugin extends BroadcastReceiver {
if(start) {
if(task.getValue(Task.TIMER_START) == 0) {
task.setValue(Task.TIMER_START, DateUtilities.now());
StatisticsService.reportEvent("timer-start"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TIMER_START);
}
} else {
if(task.getValue(Task.TIMER_START) > 0) {
@ -55,7 +56,7 @@ public class TimerPlugin extends BroadcastReceiver {
task.setValue(Task.TIMER_START, 0L);
task.setValue(Task.ELAPSED_SECONDS,
task.getValue(Task.ELAPSED_SECONDS) + newElapsed);
StatisticsService.reportEvent("timer-stop"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TIMER_STOP);
}
}
PluginServices.getTaskService().save(task);

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="4dip"
android:paddingRight="4dip"
android:background="@drawable/astrid_com_gradient"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="@+id/logo"
android:layout_width="fill_parent"
android:layout_height="110dip"
android:scaleType="fitCenter"
android:src="@drawable/astrid_com_logo" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="20dip"
android:text="@string/DLG_loading" />
</LinearLayout>

@ -40,7 +40,7 @@
<!-- NEW USER EXPERIENCE -->
<!-- NEW USER EXPERIENCE, help bubbles -->
<!-- help bubbles -->
<!-- Shown the first time a user sees the task list activity -->
<string name="help_popover_add_task">Add a task here</string>

@ -26,6 +26,7 @@ import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TaskService;
@ -107,7 +108,7 @@ public final class Eula {
((EulaCallback)activity).eulaAccepted();
}
Preferences.setBoolean(PREFERENCE_EULA_ACCEPTED, true);
StatisticsService.reportEvent("eula-accepted"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.EULA_ACCEPTED);
}
private static void refuse(Activity activity) {

@ -34,6 +34,7 @@ import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
@ -57,6 +58,7 @@ import com.todoroo.astrid.api.IntentFilter;
import com.todoroo.astrid.core.SearchFilter;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.ThemeService;
@ -69,6 +71,9 @@ import com.todoroo.astrid.service.ThemeService;
*/
public class FilterListActivity extends ExpandableListActivity {
// -- extra codes
public static final String SHOW_BACK_BUTTON = "show_back"; //$NON-NLS-1$
// --- menu codes
private static final int MENU_SEARCH_ID = Menu.FIRST + 0;
@ -106,9 +111,14 @@ public class FilterListActivity extends ExpandableListActivity {
ThemeService.applyTheme(this);
setContentView(R.layout.filter_list_activity);
ImageView backButton = (ImageView) findViewById(R.id.back);
if (!getIntent().getBooleanExtra(SHOW_BACK_BUTTON, true)) {
backButton.setVisibility(View.GONE);
findViewById(R.id.listLabel).setPadding(0, 0, 0, 0);
}
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
findViewById(R.id.back).setOnClickListener(new OnClickListener() {
backButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
@ -183,7 +193,6 @@ public class FilterListActivity extends ExpandableListActivity {
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override
@ -195,6 +204,7 @@ public class FilterListActivity extends ExpandableListActivity {
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
if(adapter != null)
adapter.registerRecevier();
}
@ -241,11 +251,11 @@ public class FilterListActivity extends ExpandableListActivity {
AndroidUtilities.callApiMethod(5, this, "overridePendingTransition", //$NON-NLS-1$
new Class<?>[] { Integer.TYPE, Integer.TYPE },
R.anim.slide_left_in, R.anim.slide_left_out);
StatisticsService.reportEvent("filter-list"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.FILTER_LIST);
return true;
} else if(item instanceof SearchFilter) {
onSearchRequested();
StatisticsService.reportEvent("filter-search"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.FILTER_SEARCH);
} else if(item instanceof IntentFilter) {
try {
((IntentFilter)item).intent.send();

@ -72,6 +72,7 @@ import com.todoroo.astrid.repeats.RepeatControlSet;
import com.todoroo.astrid.service.AddOnService;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.service.ThemeService;
@ -447,13 +448,13 @@ public final class TaskEditActivity extends TabActivity {
}
if(model.getValue(Task.TITLE).length() == 0) {
StatisticsService.reportEvent("create-task");
StatisticsService.reportEvent(StatisticsConstants.CREATE_TASK);
isNewTask = true;
// set deletion date until task gets a title
model.setValue(Task.DELETION_DATE, DateUtilities.now());
} else {
StatisticsService.reportEvent("edit-task");
StatisticsService.reportEvent(StatisticsConstants.EDIT_TASK);
}
if(model == null) {
@ -680,6 +681,7 @@ public final class TaskEditActivity extends TabActivity {
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
unregisterReceiver(controlReceiver);
if(shouldSaveState)
@ -689,6 +691,7 @@ public final class TaskEditActivity extends TabActivity {
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
registerReceiver(controlReceiver,
new IntentFilter(AstridApiConstants.BROADCAST_SEND_EDIT_CONTROLS));
populateFields();
@ -727,7 +730,6 @@ public final class TaskEditActivity extends TabActivity {
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override

@ -95,6 +95,7 @@ import com.todoroo.astrid.service.AddOnService;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.MetadataService;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.service.ThemeService;
@ -241,19 +242,19 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
if(getIntent().hasExtra(TOKEN_SOURCE)) {
switch(getIntent().getIntExtra(TOKEN_SOURCE, Constants.SOURCE_DEFAULT)) {
case Constants.SOURCE_NOTIFICATION:
StatisticsService.reportEvent("launch-from-notification"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LAUNCH_FROM_NOTIFICATION);
break;
case Constants.SOURCE_OTHER:
StatisticsService.reportEvent("launch-from-other"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LAUNCH_FROM_OTHER);
break;
case Constants.SOURCE_PPWIDGET:
StatisticsService.reportEvent("launch-from-ppw"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LAUNCH_FROM_PPW);
break;
case Constants.SOURCE_WIDGET:
StatisticsService.reportEvent("launch-from-widget"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LAUNCH_FROM_WIDGET);
break;
case Constants.SOURCE_C2DM:
StatisticsService.reportEvent("launch-from-c2dm"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LAUNCH_FROM_C2DM);
break;
}
}
@ -487,7 +488,6 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override
@ -499,6 +499,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
if (addOnService.hasPowerPack() &&
Preferences.getBoolean(R.string.p_voiceInputEnabled, true) &&
voiceInputAssistant.isVoiceInputAvailable()) {
@ -522,8 +523,8 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
@Override
protected void onPause() {
StatisticsService.sessionPause();
super.onPause();
StatisticsService.sessionPause();
try {
unregisterReceiver(detailReceiver);
unregisterReceiver(refreshReceiver);
@ -816,12 +817,11 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
* A task was completed from the task adapter
* @param item task that was completed
*/
@SuppressWarnings("nls")
protected void onTaskCompleted(Task item) {
if(isInbox)
StatisticsService.reportEvent("task-completed-inbox");
StatisticsService.reportEvent(StatisticsConstants.TASK_COMPLETED_INBOX);
else
StatisticsService.reportEvent("task-completed-filter");
StatisticsService.reportEvent(StatisticsConstants.TASK_COMPLETED_FILTER);
}
/**
@ -845,7 +845,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
selectCustomId(task.getId());
}
StatisticsService.reportEvent("task-created-tasklist");
StatisticsService.reportEvent(StatisticsConstants.TASK_CREATED_TASKLIST);
return task;
} catch (Exception e) {
exceptionService.displayAndReportError(this, "quick-add-task", e);
@ -1073,31 +1073,31 @@ public class TaskListActivity extends ListActivity implements OnScrollListener,
// handle my own menus
switch (item.getItemId()) {
case MENU_LISTS_ID:
StatisticsService.reportEvent("tla-menu-lists"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TLA_MENU_LISTS);
showFilterListActivity();
return true;
case MENU_ADDONS_ID:
StatisticsService.reportEvent("tla-menu-addons"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TLA_MENU_ADDONS);
intent = new Intent(this, AddOnActivity.class);
startActivityForResult(intent, ACTIVITY_ADDONS);
return true;
case MENU_SETTINGS_ID:
StatisticsService.reportEvent("tla-menu-settings"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TLA_MENU_SETTINGS);
intent = new Intent(this, EditPreferences.class);
startActivityForResult(intent, ACTIVITY_SETTINGS);
return true;
case MENU_SORT_ID:
StatisticsService.reportEvent("tla-menu-sort"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TLA_MENU_SORT);
AlertDialog dialog = SortSelectionActivity.createDialog(this,
this, sortFlags, sortSort);
dialog.show();
return true;
case MENU_SYNC_ID:
StatisticsService.reportEvent("tla-menu-sync"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TLA_MENU_SYNC);
performSyncAction();
return true;
case MENU_HELP_ID:
StatisticsService.reportEvent("tla-menu-help"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TLA_MENU_HELP);
intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(Constants.HELP_URL));
startActivity(intent);

@ -72,6 +72,7 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.helper.TaskAdapterAddOnManager;
import com.todoroo.astrid.notes.NotesDecorationExposer;
import com.todoroo.astrid.notes.NotesPlugin;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.timers.TimerDecorationExposer;
@ -1036,7 +1037,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable {
onCompletedTaskListener.onCompletedTask(task, newState);
if(newState)
StatisticsService.reportEvent("task-completed-v2"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.TASK_COMPLETED_V2);
}
}

@ -21,6 +21,7 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.TaskApiDao;
import com.todoroo.astrid.reminders.Notifications;
import com.todoroo.astrid.reminders.ReminderService;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.utility.AstridPreferences;
import com.todoroo.astrid.utility.Flags;
@ -205,7 +206,7 @@ public class TaskDao extends DatabaseDao<Task> {
boolean result = super.createNew(item);
if(result) {
if(Preferences.getBoolean(AstridPreferences.P_FIRST_ACTION, false)) {
StatisticsService.reportEvent("user-first-task"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.USER_FIRST_TASK);
Preferences.setBoolean(AstridPreferences.P_FIRST_ACTION, false);
}
afterSave(item, values);

@ -25,6 +25,7 @@ import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.tags.TagService;
@ -268,7 +269,7 @@ public class Astrid2TaskProvider extends ContentProvider {
task.setValue(Task.COMPLETION_DATE,
values.getAsBoolean(COMPLETED) ? DateUtilities.now() : 0);
if(task.isCompleted())
StatisticsService.reportEvent("task-completed-api2");
StatisticsService.reportEvent(StatisticsConstants.TASK_COMPLETED_API2);
}
// map selection criteria

@ -23,6 +23,8 @@ import com.todoroo.astrid.gtasks.GtasksMetadataService;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.sync.GtasksSyncOnSaveService;
import com.todoroo.astrid.service.abtesting.ABChooser;
import com.todoroo.astrid.service.abtesting.ABOptions;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.utility.Constants;
@ -91,6 +93,10 @@ public class AstridDependencyInjector extends AbstractDependencyInjector {
injectables.put("gtasksTaskListUpdater", GtasksTaskListUpdater.class);
injectables.put("gtasksSyncOnSaveService", GtasksSyncOnSaveService.class);
// AB testing
injectables.put("abChooser", ABChooser.class);
injectables.put("abOptions", new ABOptions());
// com.todoroo.astrid.tags
injectables.put("tagService", TagService.class);

@ -41,6 +41,7 @@ import com.todoroo.astrid.gtasks.sync.GtasksSyncOnSaveService;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.reminders.ReminderStartupReceiver;
import com.todoroo.astrid.service.abtesting.FeatureFlipper;
import com.todoroo.astrid.utility.AstridPreferences;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.widget.TasksWidget.WidgetUpdateService;
@ -179,6 +180,9 @@ public class StartupService {
// get and display update messages
new UpdateMessageService().processUpdates(context);
// Check for feature flips
new FeatureFlipper().updateFeatures();
}
}).start();
@ -252,7 +256,7 @@ public class StartupService {
if(children.length > 0) {
StatisticsService.sessionStart(context);
TasksXmlImporter.importTasks(context, children[0].getAbsolutePath(), null);
StatisticsService.reportEvent("lost-tasks-restored"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.LOST_TASKS_RESTORED);
}
}
} catch (Exception e) {

@ -0,0 +1,60 @@
package com.todoroo.astrid.service;
@SuppressWarnings("nls")
public class StatisticsConstants {
public static final String EULA_ACCEPTED = "eula-accepted";
public static final String ACTFM_TAG_COMMENT = "actfm-tag-comment";
public static final String ACTFM_TASK_COMMENT = "actfm-task-comment";
public static final String ACTFM_NEW_USER = "actfm-new-user";
public static final String TASK_COMPLETED_V2 = "task-completed-v2";
public static final String USER_FIRST_TASK = "user-first-task";
public static final String LOST_TASKS_RESTORED = "lost-tasks-restored";
public static final String CREATE_TASK = "create-task";
public static final String EDIT_TASK = "edit-task";
public static final String ACTFM_TASK_CREATED = "actfm-task-created";
public static final String ACTFM_TASK_COMPLETED = "actfm-task-completed";
public static final String ACTFM_LOGIN_GL_SUCCESS = "actfm-login-gl-success";
public static final String ACTFM_LOGIN_PW = "actfm-login-pw";
public static final String ACTFM_SIGNUP_PW = "actfm-signup-pw";
public static final String ACTFM_LOGIN_GL_START = "actfm-login-gl-start";
public static final String ACTFM_LOGIN_FB = "actfm-login-fb";
public static final String LAUNCH_FROM_NOTIFICATION = "launch-from-notification";
public static final String LAUNCH_FROM_OTHER = "launch-from-other";
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 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";
public static final String FILTER_LIST = "filter-list";
public static final String FILTER_SEARCH = "filter-search";
public static final String TLA_MENU_LISTS = "tla-menu-lists";
public static final String TLA_MENU_ADDONS = "tla-menu-addons";
public static final String TLA_MENU_SETTINGS = "tla-menu-settings";
public static final String TLA_MENU_SORT = "tla-menu-sort";
public static final String TLA_MENU_SYNC = "tla-menu-sync";
public static final String TLA_MENU_HELP = "tla-menu-help";
public static final String V2_TASK_REPEAT = "v2-task-repeat";
public static final String TASK_COMPLETED_INBOX = "task-completed-inbox";
public static final String TASK_COMPLETED_FILTER = "task-completed-filter";
public static final String TASK_COMPLETED_NOTIFICATION = "task-completed-notification";
public static final String ACTFM_SYNC_FINISHED = "actfm-sync-finished";
public static final String GTASKS_SYNC_FINISHED = "gtasks-sync-finished";
public static final String PDV_SYNC_FINISHED = "pdv-sync-finished";
public static final String TASK_CREATED_TASKLIST = "task-created-tasklist";
public static final String ACTFM_LOGIN_SHOW = "actfm-login-show";
public static final String ACTFM_TASK_SHARED = "actfm-task-shared";
public static final String PRODUCTEEV_LOGIN = "producteev-login";
public static final String PRODUCTEEV_SIGNUP = "producteev-signup";
public static final String TASK_SNOOZE = "task-snooze";
public static final String TASK_COMPLETED_API2 = "task-completed-api2";
public static final String TIMER_START = "timer-start";
public static final String TIMER_STOP = "timer-stop";
public static final String GTASKS_TASK_COMPLETED = "gtasks-task-completed";
public static final String PDV_TASK_COMPLETED = "pdv-task-completed";
public static final String CREATE_CALENDAR_EVENT = "create-calendar-event";
public static final String REPEAT_TASK_CREATE = "repeat-task-create";
public static final String ACTFM_LIST_SHARED = "actfm-list-shared";
}

@ -11,12 +11,21 @@ import android.content.Context;
import com.localytics.android.LocalyticsSession;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.service.abtesting.ABOptions;
import com.todoroo.astrid.utility.Constants;
public class StatisticsService {
private static LocalyticsSession localyticsSession;
private static class StatisticsDependencies {
@Autowired ABOptions abOptions;
public StatisticsDependencies() {
DependencyInjectionService.getInstance().inject(this);
}
}
/**
* Indicate session started
@ -84,10 +93,13 @@ public class StatisticsService {
return;
if(localyticsSession != null) {
if(attributes.length > 0) {
String[] abAttributes = new StatisticsDependencies().abOptions.getLocalyticsAttributeArrayForEvent(event);
if(attributes.length > 0 || abAttributes.length > 0) {
HashMap<String, String> attrMap = new HashMap<String, String>();
for(int i = 1; i < attributes.length; i += 2)
attrMap.put(attributes[i-1], attributes[i]);
for (int i = 1; i < abAttributes.length; i += 2)
attrMap.put(abAttributes[i-1], abAttributes[i]);
localyticsSession.tagEvent(event, attrMap);
} else
localyticsSession.tagEvent(event);

@ -0,0 +1,92 @@
package com.todoroo.astrid.service.abtesting;
import java.util.Random;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.service.StatisticsService;
/**
* Helper class to facilitate A/B testing by randomly choosing an option
* based on probabilities that can be supplied from local defaults
* @author Sam Bosley <sam@astrid.com>
*
*/
public class ABChooser {
public static final int NO_OPTION = -1;
@Autowired
private ABOptions abOptions;
private final Random random;
public ABChooser() {
DependencyInjectionService.getInstance().inject(this);
random = new Random();
}
/**
* Retrieves the choice for the specified feature if already made,
* or chooses one randomly from the distribution of feature probabilities
* if not.
*
* The statistics session needs to be open here in order to collect statistics
*
* @param optionKey - the preference key string of the option (defined in ABOptions)
* @return
*/
public int getChoiceForOption(String optionKey) {
int pref = readChoiceForOption(optionKey);
if (pref > NO_OPTION) return pref;
int chosen = NO_OPTION;
if (abOptions.isValidKey(optionKey)) {
int[] optionProbs = abOptions.getProbsForKey(optionKey);
chosen = chooseOption(optionProbs);
setChoiceForOption(optionKey, chosen);
StatisticsService.reportEvent(abOptions.getDescriptionForOption(optionKey, chosen)); // Session should be open
}
return chosen;
}
/**
* Returns the chosen option if set or NO_OPTION if unset
* @param optionKey
* @return
*/
public static int readChoiceForOption(String optionKey) {
return Preferences.getInt(optionKey, NO_OPTION);
}
/**
* Changes the choice of an A/B feature in the preferences. Useful for
* the feature flipper (can manually override previous choice)
* @param optionKey
* @param choiceIndex
*/
public void setChoiceForOption(String optionKey, int choiceIndex) {
if (abOptions.isValidKey(optionKey))
Preferences.setInt(optionKey, choiceIndex);
}
/*
* Helper method to choose an option from an int[] corresponding to the
* relative weights of each option. Returns the index of the chosen option.
*/
private int chooseOption(int[] optionProbs) {
int sum = 0;
for (int opt : optionProbs) // Compute sum
sum += opt;
double rand = random.nextDouble() * sum; // Get uniformly distributed double between [0, sum)
sum = 0;
for (int i = 0; i < optionProbs.length; i++) {
sum += optionProbs[i];
if (rand <= sum) return i;
}
return optionProbs.length - 1;
}
}

@ -0,0 +1,196 @@
package com.todoroo.astrid.service.abtesting;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.todoroo.astrid.service.StatisticsConstants;
/**
* Helper class to define options with their probabilities and descriptions
* @author Sam Bosley <sam@astrid.com>
*
*/
@SuppressWarnings("nls")
public class ABOptions {
public ABOptions() {
bundles = new HashMap<String, ABOptionBundle>();
events = new HashMap<String, List<String>>();
initialize();
}
/**
* Gets the integer array of weighted probabilities for an option key
* @param key
* @return
*/
public synchronized int[] getProbsForKey(String key) {
if (bundles.containsKey(key)) {
ABOptionBundle bundle = bundles.get(key);
return bundle.weightedProbs;
} else {
return null;
}
}
/**
* Updates the weighted probability array for a given key. Returns true
* on success, false if they key doesn't exist or if the array is the wrong
* length.
* @param key
* @param newProbs
* @return
*/
public synchronized boolean setProbsForKey(String key, int[] newProbs) {
if (bundles.containsKey(newProbs)) {
ABOptionBundle bundle = bundles.get(key);
if (bundle.descriptions == null || newProbs.length == bundle.descriptions.length) {
bundle.weightedProbs = newProbs;
return true;
}
}
return false;
}
/**
* Gets the string array of option descriptions for an option key
* @param key
* @return
*/
public String[] getDescriptionsForKey(String key) {
if (bundles.containsKey(key)) {
ABOptionBundle bundle = bundles.get(key);
return bundle.descriptions;
} else {
return null;
}
}
/**
* Returns the description for a particular choice of the given option
* @param key
* @param optionIndex
* @return
*/
public String getDescriptionForOption(String key, int optionIndex) {
if (bundles.containsKey(key)) {
ABOptionBundle bundle = bundles.get(key);
if (bundle.descriptions != null && optionIndex < bundle.descriptions.length) {
return bundle.descriptions[optionIndex];
}
}
return null;
}
/**
* Maps keys (i.e. preference key identifiers) to feature weights and descriptions
*/
private final HashMap<String, ABOptionBundle> bundles;
private final HashMap<String, List<String>> events; // maps events to lists of interested keys
private static class ABOptionBundle {
public int[] weightedProbs;
public String[] descriptions;
public ABOptionBundle(int[] weightedProbs, String[] descriptions) {
this.weightedProbs = weightedProbs;
this.descriptions = descriptions;
}
}
public boolean isValidKey(String key) {
return bundles.containsKey(key);
}
/**
* Gets a localytics attribute array for the specified event.
* @param event
* @return
*/
public String[] getLocalyticsAttributeArrayForEvent(String event) {
ArrayList<String> attributes = new ArrayList<String>();
List<String> interestedKeys = events.get(event);
if (interestedKeys != null)
for (String key : interestedKeys) {
// Get choice if exists and add to array
if (isValidKey(key)) {
ABOptionBundle bundle = bundles.get(key);
int choice = ABChooser.readChoiceForOption(key);
if (choice != ABChooser.NO_OPTION &&
bundle.descriptions != null && choice < bundle.descriptions.length) {
attributes.add(key);
attributes.add(getDescriptionForOption(key, choice));
}
}
}
return attributes.toArray(new String[attributes.size()]);
}
/**
* A/B testing options are defined below according to the following spec:
*
* @param optionKey = "<key>"
* --This key is used to identify the option in the application and in the preferences
*
* @param probs = { int, int, ... }
* --The different choices in an option correspond to an index in the probability array.
* Probabilities are expressed as integers to easily define relative weights. For example,
* the array { 1, 2 } would mean option 0 would happen one time for every two occurrences of option 1
*
* (optional)
* @param descriptions = { "...", "...", ... }
* --A string description of each option. Useful for tagging events. The index of
* each description should correspond to the events location in the probability array
* (i.e. the arrays should be the same length if this one exists)
*
* (optional)
* @param relevantEvents = { "...", "...", ... }
* --An arbitrary length list of relevant localytics events. When events are
* tagged from StatisticsService, they will be appended with attributes
* that have that event in this array
*/
private void addOption(String optionKey, int[] probs, String[] descriptions, String[] relevantEvents) {
ABOptionBundle bundle = new ABOptionBundle(probs, descriptions);
bundles.put(optionKey, bundle);
if (relevantEvents != null) {
for (String event : relevantEvents) {
List<String> interestedKeys = events.get(event);
if (interestedKeys == null) {
interestedKeys = new ArrayList<String>();
events.put(event, interestedKeys);
}
interestedKeys.add(optionKey);
}
}
}
private void initialize() { // Set up
addOption(AB_OPTION_FIRST_ACTIVITY, AB_OPTION_FIRST_ACTIVITY_PROBS,
AB_OPTION_FIRST_ACTIVITY_DESCRIPTIONS, AB_OPTION_FIRST_ACTIVITY_RELEVANT_EVENTS);
addOption(AB_OPTION_WELCOME_LOGIN, AB_OPTION_WELCOME_LOGIN_PROBS,
AB_OPTION_WELCOME_LOGIN_DESCRIPTIONS, AB_OPTION_WELCOME_LOGIN_RELEVANT_EVENTS);
}
public static final String AB_OPTION_FIRST_ACTIVITY = "ab_first_activity";
private static final int[] AB_OPTION_FIRST_ACTIVITY_PROBS = { 1, 1 };
private static final String[] AB_OPTION_FIRST_ACTIVITY_DESCRIPTIONS = { "ab-show-tasks-first", "ab-show-lists-first" };
private static final String[] AB_OPTION_FIRST_ACTIVITY_RELEVANT_EVENTS = { StatisticsConstants.CREATE_TASK,
StatisticsConstants.TASK_CREATED_TASKLIST,
StatisticsConstants.USER_FIRST_TASK,
StatisticsConstants.ACTFM_LIST_SHARED,
StatisticsConstants.ACTFM_NEW_USER };//*/
public static final String AB_OPTION_WELCOME_LOGIN = "ab_welcome_login";
private static final int[] AB_OPTION_WELCOME_LOGIN_PROBS = { 0, 1 };
private static final String[] AB_OPTION_WELCOME_LOGIN_DESCRIPTIONS = { "ab-welcome-login-show", "ab-welcome-login-skip" };
private static final String[] AB_OPTION_WELCOME_LOGIN_RELEVANT_EVENTS = { StatisticsConstants.CREATE_TASK,
StatisticsConstants.TASK_CREATED_TASKLIST,
StatisticsConstants.USER_FIRST_TASK,
StatisticsConstants.ACTFM_LIST_SHARED,
StatisticsConstants.ACTFM_NEW_USER };//*/
}

@ -0,0 +1,92 @@
package com.todoroo.astrid.service.abtesting;
import java.io.IOException;
import java.util.Locale;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.text.TextUtils;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.HttpRestClient;
import com.todoroo.andlib.service.RestClient;
import com.todoroo.astrid.utility.Constants;
@SuppressWarnings("nls")
public class FeatureFlipper {
private static final String URL = "http://weloveastrid.com/settings.php";
private static final String KEY_SETTING_KEY = "key";
private static final String KEY_SET_OPTION = "setOption";
private static final String KEY_PROBABILITIES = "probabilities";
private final RestClient restClient = new HttpRestClient(4000);
@Autowired private ABChooser abChooser;
@Autowired private ABOptions abOptions;
public FeatureFlipper() {
DependencyInjectionService.getInstance().inject(this);
}
/**
* Requests a JSON array containing feature settings override data,
* parses the result, and updates the AB settings for the corresponding features
* @throws JSONException
*/
public void updateFeatures() {
JSONArray settingsBundle = requestOverrideSettings();
if (settingsBundle == null || settingsBundle.length() == 0)
return;
for (int i = 0; i < settingsBundle.length(); i++) {
try {
JSONObject settings = settingsBundle.getJSONObject(i);
String key = settings.getString(KEY_SETTING_KEY);
if (settings.has(KEY_SET_OPTION)) {
int option = settings.getInt(KEY_SET_OPTION);
abChooser.setChoiceForOption(key, option);
} else if (settings.has(KEY_PROBABILITIES)) {
JSONArray newProbabilities = settings.getJSONArray(KEY_PROBABILITIES);
int[] probs = new int[newProbabilities.length()];
for (int j = 0; j < newProbabilities.length(); j++) {
probs[j] = newProbabilities.getInt(j);
}
abOptions.setProbsForKey(key, probs);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private JSONArray requestOverrideSettings() {
PackageManager pm = ContextManager.getContext().getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(Constants.PACKAGE, PackageManager.GET_META_DATA);
int versionCode = pi.versionCode;
String result = restClient.get(URL + "?version=" + versionCode + "&" +
"language=" + Locale.getDefault().getISO3Language()); //$NON-NLS-1$
if(TextUtils.isEmpty(result))
return null;
return new JSONArray(result);
} catch (IOException e) {
return null;
} catch (NameNotFoundException e) {
return null;
} catch (JSONException e) {
return null;
}
}
}

@ -0,0 +1,108 @@
package com.todoroo.astrid.welcome;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Window;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.FilterListActivity;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.abtesting.ABChooser;
import com.todoroo.astrid.service.abtesting.ABOptions;
import com.todoroo.astrid.service.abtesting.FeatureFlipper;
import com.todoroo.astrid.utility.AstridPreferences;
public class SplashScreenLauncher extends Activity {
private boolean shouldGoThroughWelcome = false;
private int latestSetVersion = 0;
@Autowired ABChooser abChooser;
static {
AstridDependencyInjector.initialize();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
DependencyInjectionService.getInstance().inject(this);
setContentView(R.layout.splash_screen_launcher);
latestSetVersion = AstridPreferences.getCurrentVersion();
shouldGoThroughWelcome = ((latestSetVersion == 0) || !Preferences.getBoolean(WelcomeLogin.KEY_SHOWED_WELCOME_LOGIN, false));
ContextManager.setContext(this);
if (latestSetVersion == 0) {
new Thread() {
@Override
public void run() {
new FeatureFlipper().updateFeatures();
runOnUiThread(new Runnable() {
@Override
public void run() {
new StartupService().onStartupApplication(SplashScreenLauncher.this);
finishAndShowNext();
}
});
}
}.start();
} else {
new StartupService().onStartupApplication(this);
finishAndShowNext();
}
}
private void finishAndShowNext() {
if (shouldGoThroughWelcome) {
int welcomeLoginChoice = abChooser.getChoiceForOption(ABOptions.AB_OPTION_WELCOME_LOGIN);
welcomeLoginPath(welcomeLoginChoice);
} else {
int tasksOrListsChoice = abChooser.getChoiceForOption(ABOptions.AB_OPTION_FIRST_ACTIVITY);
mainActivityPath(tasksOrListsChoice);
}
}
private void welcomeLoginPath(int welcomeLoginChoice) {
Intent intent = new Intent();
switch(welcomeLoginChoice) {
case 0: // Show welcome login, then welcome screen
intent.setClass(this, WelcomeLogin.class);
break;
case 1: // Go straight to welcome screen
intent.setClass(this, WelcomeGraphic.class);
intent.putExtra(WelcomeGraphic.KEY_SHOW_EULA, true);
break;
default:
intent.setClass(this, WelcomeLogin.class);
break;
}
startActivity(intent);
finish();
}
private void mainActivityPath(int tasksOrListsChoice) {
Intent intent = new Intent();
switch (tasksOrListsChoice) {
case 0:
intent.setClass(this, TaskListActivity.class); // Go to task list activity
break;
case 1:
intent.setClass(this, FilterListActivity.class); // Go to filter list activity
intent.putExtra(FilterListActivity.SHOW_BACK_BUTTON, false);
break;
default:
intent.setClass(this, TaskListActivity.class);
break;
}
startActivity(intent);
finish();
}
}

@ -0,0 +1,109 @@
package com.todoroo.astrid.welcome;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.activity.Eula;
import com.todoroo.astrid.activity.FilterListActivity;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.abtesting.ABChooser;
import com.todoroo.astrid.service.abtesting.ABOptions;
public class WelcomeGraphic extends Activity {
public static final String KEY_SHOW_EULA = "show_eula"; //$NON-NLS-1$
@Autowired ABChooser abChooser;
@Override
protected void onCreate(Bundle savedInstanceState) {
ContextManager.setContext(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
DependencyInjectionService.getInstance().inject(this);
super.onCreate(savedInstanceState);
new StartupService().onStartupApplication(this);
setContentView(R.layout.welcome_screen);
if (getIntent().getBooleanExtra(KEY_SHOW_EULA, false))
Eula.showEula(this);
final ImageView image = (ImageView)findViewById(R.id.welcome_image);
image.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
image.setOnClickListener(null); // Prevent double click
new Thread() {
@Override
public void run() {
AndroidUtilities.sleepDeep(1000L);
runOnUiThread(new Runnable() {
@Override
public void run() {
finishAndStartNext();
}
});
}
}.start();
}
});
}
@Override
protected void onPause() {
StatisticsService.sessionPause();
super.onPause();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
}
@Override
protected void onStop() {
StatisticsService.sessionStop(this);
super.onStop();
}
private void finishAndStartNext() {
Intent nextActivity = getNextIntent();
startActivity(nextActivity);
finish();
}
private Intent getNextIntent() {
Intent intent = new Intent();
int choice = abChooser.getChoiceForOption(ABOptions.AB_OPTION_FIRST_ACTIVITY);
switch (choice) {
case 0:
intent.setClass(this, TaskListActivity.class);
break;
case 1:
intent.setClass(this, FilterListActivity.class);
intent.putExtra(FilterListActivity.SHOW_BACK_BUTTON, false);
break;
default:
intent.setClass(this, TaskListActivity.class);
}
return intent;
}
}

@ -23,11 +23,7 @@ import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.actfm.ActFmLoginActivity;
import com.todoroo.astrid.activity.Eula;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.utility.AstridPreferences;
public class WelcomeLogin extends ActFmLoginActivity implements AuthListener {
@ -35,14 +31,6 @@ public class WelcomeLogin extends ActFmLoginActivity implements AuthListener {
public static final String KEY_SHOWED_WELCOME_LOGIN = "key_showed_welcome_login"; //$NON-NLS-1$
public static final String KEY_IS_NEW_INSTALL = "key_is_new_install"; //$NON-NLS-1$
private boolean shouldShowWelcomeScreen = true;
static {
AstridDependencyInjector.initialize();
}
@Override
protected int getContentViewResource() {
return R.layout.welcome_login_activity;
@ -62,29 +50,20 @@ public class WelcomeLogin extends ActFmLoginActivity implements AuthListener {
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
int latestSetVersion = AstridPreferences.getCurrentVersion();
shouldShowWelcomeScreen = (latestSetVersion == 0);
new StartupService().onStartupApplication(this);
ContextManager.setContext(this);
if (latestSetVersion !=0 || Preferences.getBoolean(KEY_SHOWED_WELCOME_LOGIN, false)) {
if (Preferences.getBoolean(KEY_SHOWED_WELCOME_LOGIN, false)) {
finishAndShowNext();
}
initializeUI();
}
@Override
protected void finishAndShowNext() {
if (shouldShowWelcomeScreen) {
Intent welcomeScreen = new Intent(this, WelcomeScreen.class);
startActivity(welcomeScreen);
finish();
Preferences.setBoolean(KEY_SHOWED_WELCOME_LOGIN, true);
} else {
Intent taskListStartup = new Intent(this, TaskListActivity.class);
startActivity(taskListStartup);
finish();
}
Intent welcomeScreen = new Intent(this, WelcomeGraphic.class);
startActivity(welcomeScreen);
finish();
Preferences.setBoolean(KEY_SHOWED_WELCOME_LOGIN, true);
}
@Override

@ -1,65 +0,0 @@
package com.todoroo.astrid.welcome;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.activity.Eula;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.service.StartupService;
public class WelcomeScreen extends Activity {
public static final String KEY_SHOWED_WELCOME_SCREEN = "key_showed_welcome_screen"; //$NON-NLS-1$
@Override
protected void onCreate(Bundle savedInstanceState) {
ContextManager.setContext(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
new StartupService().onStartupApplication(this);
setContentView(R.layout.welcome_screen);
Eula.showEula(this);
final ImageView image = (ImageView)findViewById(R.id.welcome_image);
image.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
image.setOnClickListener(null); // Prevent double click
new Thread() {
@Override
public void run() {
AndroidUtilities.sleepDeep(1000L);
runOnUiThread(new Runnable() {
@Override
public void run() {
finishAndStartNext();
}
});
}
}.start();
}
});
if(Preferences.getBoolean(KEY_SHOWED_WELCOME_SCREEN, false)) {
finishAndStartNext();
}
}
private void finishAndStartNext() {
Intent taskListStartup = new Intent(this, TaskListActivity.class);
startActivity(taskListStartup);
finish();
Preferences.setBoolean(KEY_SHOWED_WELCOME_SCREEN, true);
}
}

@ -17,6 +17,7 @@ import com.todoroo.astrid.adapter.FilterAdapter;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterCategory;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
@SuppressWarnings("nls")
@ -71,7 +72,7 @@ abstract public class WidgetConfigActivity extends ExpandableListActivity {
Button button = (Button)findViewById(R.id.ok);
button.setOnClickListener(mOnClickListener);
StatisticsService.reportEvent("widget-config"); //$NON-NLS-1$
StatisticsService.reportEvent(StatisticsConstants.WIDGET_CONFIG);
}
View.OnClickListener mOnClickListener = new View.OnClickListener() {
@ -121,19 +122,20 @@ abstract public class WidgetConfigActivity extends ExpandableListActivity {
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
adapter.registerRecevier();
}
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
adapter.unregisterRecevier();
}
@Override
protected void onStart() {
super.onStart();
StatisticsService.sessionStart(this);
}
@Override

Loading…
Cancel
Save