Merge upstream/master

pull/14/head
Sam Bosley 14 years ago
commit 7233b14f35

@ -308,6 +308,8 @@
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.todoroo.astrid.actfm.ActFmGoogleAuthActivity"
android:theme="@style/Theme" android:configChanges="orientation|keyboardHidden"/>
<service android:name="com.todoroo.astrid.actfm.ActFmBackgroundService"> <service android:name="com.todoroo.astrid.actfm.ActFmBackgroundService">
<intent-filter> <intent-filter>
<action android:name="com.todoroo.astrid.actfm.SYNC" /> <action android:name="com.todoroo.astrid.actfm.SYNC" />

@ -0,0 +1,178 @@
/*
* ASTRID: Android's Simple Task Recording Dashboard
*
* Copyright (c) 2009 Tim Su
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.todoroo.astrid.actfm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.service.StatisticsService;
/**
* This activity allows users to sign in or log in to Google Tasks
* through the Android account manager
*
* @author Sam Bosley
*
*/
public class ActFmGoogleAuthActivity extends ListActivity {
private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/userinfo.profile"; //$NON-NLS-1$
public static final String RESULT_EMAIL = "email"; //$NON-NLS-1$
public static final String RESULT_TOKEN = "token"; //$NON-NLS-1$
// --- ui initialization
private GoogleAccountManager accountManager;
private String[] nameArray;
private String authToken;
private String accountName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ContextManager.setContext(this);
setContentView(R.layout.gtasks_login_activity);
setTitle(R.string.actfm_GAA_title);
accountManager = new GoogleAccountManager(this);
Account[] accounts = accountManager.getAccounts();
ArrayList<String> accountNames = new ArrayList<String>();
for (Account a : accounts) {
accountNames.add(a.name);
}
nameArray = accountNames.toArray(new String[accountNames.size()]);
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, nameArray));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
final ProgressDialog pd = DialogUtilities.progressDialog(this, this.getString(R.string.gtasks_GLA_authenticating));
pd.show();
final Account a = accountManager.getAccountByName(nameArray[position]);
accountName = a.name;
getAuthToken(a, pd);
}
private void getAuthToken(Account a, final ProgressDialog pd) {
AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
public void run(final AccountManagerFuture<Bundle> future) {
new Thread() {
@Override
public void run() {
try {
Bundle bundle = future.getResult(30, TimeUnit.SECONDS);
if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) {
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
onAuthTokenSuccess();
}
} catch (final Exception e) {
Log.e("actfm-google-auth", "Login Error", e); //$NON-NLS-1$ //$NON-NLS-2$
runOnUiThread(new Runnable() {
@Override
public void run() {
int error = e instanceof IOException ? R.string.gtasks_GLA_errorIOAuth :
R.string.gtasks_GLA_errorAuth;
Toast.makeText(ActFmGoogleAuthActivity.this,
error,
Toast.LENGTH_LONG).show();
}
});
} finally {
DialogUtilities.dismissDialog(ActFmGoogleAuthActivity.this, pd);
}
}
}.start();
}
};
accountManager.manager.getAuthToken(a, AUTH_TOKEN_TYPE, null, this, callback, null);
}
private void onAuthCancel() {
setResult(RESULT_CANCELED);
finish();
}
private void onAuthTokenSuccess() {
Intent data = new Intent();
data.putExtra(RESULT_EMAIL, accountName);
data.putExtra(RESULT_TOKEN, authToken);
setResult(RESULT_OK, data);
finish();
}
@Override
protected void onResume() {
super.onResume();
StatisticsService.sessionStart(this);
}
@Override
protected void onPause() {
super.onPause();
StatisticsService.sessionPause();
}
@Override
protected void onStop() {
super.onStop();
StatisticsService.sessionStop(this);
}
private static final int REQUEST_AUTHENTICATE = 0;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_AUTHENTICATE && resultCode == RESULT_OK){
final ProgressDialog pd = DialogUtilities.progressDialog(this, this.getString(R.string.gtasks_GLA_authenticating));
pd.show();
final Account a = accountManager.getAccountByName(accountName);
getAuthToken(a, pd);
} else {
onAuthCancel();
}
}
}

@ -21,9 +21,7 @@ package com.todoroo.astrid.actfm;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.security.NoSuchAlgorithmException;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -79,9 +77,9 @@ import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.service.TaskService;
/** /**
* This activity allows users to sign in or log in to Producteev * This activity allows users to sign in or log in to Astrid.com
* *
* @author arne.jans * @author Tim Su <tim@astrid.com>
* *
*/ */
public class ActFmLoginActivity extends FragmentActivity implements AuthListener { public class ActFmLoginActivity extends FragmentActivity implements AuthListener {
@ -102,13 +100,14 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
private TextView errors; private TextView errors;
protected boolean noSync = false; protected boolean noSync = false;
public static final String SHOW_TOAST = "show_toast"; public static final String SHOW_TOAST = "show_toast"; //$NON-NLS-1$
private boolean showToast; private boolean showToast;
// --- ui initialization // --- ui initialization
private static final int REQUEST_CODE_GOOGLE_ACCOUNTS = 1; private static final int REQUEST_CODE_GOOGLE_ACCOUNTS = 1;
private static final int REQUEST_CODE_OAUTH = 2; private static final int REQUEST_CODE_GOOGLE = 2;
static { static {
AstridDependencyInjector.initialize(); AstridDependencyInjector.initialize();
@ -129,7 +128,6 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
} }
@SuppressWarnings("nls")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -189,6 +187,7 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_SHOW); StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_SHOW);
} }
@SuppressWarnings("nls")
protected void initializeUI() { protected void initializeUI() {
facebook = new Facebook(APP_ID); facebook = new Facebook(APP_ID);
facebookRunner = new AsyncFacebookRunner(facebook); facebookRunner = new AsyncFacebookRunner(facebook);
@ -207,21 +206,11 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
protected final OnClickListener googleListener = new OnClickListener() { protected final OnClickListener googleListener = new OnClickListener() {
@Override @Override
@SuppressWarnings("nls")
public void onClick(View arg0) { public void onClick(View arg0) {
Intent intent = new Intent(ActFmLoginActivity.this, Intent intent = new Intent(ActFmLoginActivity.this,
OAuthLoginActivity.class); ActFmGoogleAuthActivity.class);
try { startActivityForResult(intent, REQUEST_CODE_GOOGLE);
String url = actFmInvoker.createFetchUrl("user_oauth", StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_GL_START);
"provider", "google");
intent.putExtra(OAuthLoginActivity.URL_TOKEN, url);
startActivityForResult(intent, REQUEST_CODE_OAUTH);
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_GL_START);
} catch (UnsupportedEncodingException e) {
handleError(e);
} catch (NoSuchAlgorithmException e) {
handleError(e);
}
} }
}; };
@ -541,15 +530,10 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
onFBAuthSucceed(); onFBAuthSucceed();
} }
errors.setVisibility(View.GONE); errors.setVisibility(View.GONE);
} else if (requestCode == REQUEST_CODE_OAUTH) { } else if (requestCode == REQUEST_CODE_GOOGLE) {
String result = data.getStringExtra(OAuthLoginActivity.DATA_RESPONSE); String email= data.getStringExtra(ActFmGoogleAuthActivity.RESULT_EMAIL);
try { String token = data.getStringExtra(ActFmGoogleAuthActivity.RESULT_TOKEN);
JSONObject json = new JSONObject(result); authenticate(email, email, "google", token);
postAuthenticate(json, json.getString("token"));
StatisticsService.reportEvent(StatisticsConstants.ACTFM_LOGIN_GL_SUCCESS);
} catch (JSONException e) {
handleError(e);
}
} }
} }
@ -568,4 +552,4 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener
REQUEST_CODE_GOOGLE_ACCOUNTS, false); REQUEST_CODE_GOOGLE_ACCOUNTS, false);
} }
} }

@ -41,7 +41,7 @@ public class ActFmPreferenceService extends SyncProviderUtilities {
@Override @Override
public boolean shouldShowToast() { public boolean shouldShowToast() {
if(Preferences.getBoolean(AstridPreferences.P_FIRST_ACTION, false)) if(Preferences.getBoolean(AstridPreferences.P_FIRST_TASK, true))
return false; return false;
return super.shouldShowToast(); return super.shouldShowToast();
} }

@ -19,6 +19,7 @@
*/ */
package com.todoroo.astrid.gtasks.auth; package com.todoroo.astrid.gtasks.auth;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -30,6 +31,7 @@ import android.app.ListActivity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
@ -81,8 +83,9 @@ public class GtasksLoginActivity extends ListActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ContextManager.setContext(this); ContextManager.setContext(this);
setContentView(R.layout.gtasks_login_activity);
setTitle(R.string.gtasks_GLA_title); setTitle(R.string.gtasks_GLA_title);
getListView().setBackgroundColor(getResources().getColor(android.R.color.background_dark));
accountManager = new GoogleAccountManager(this); accountManager = new GoogleAccountManager(this);
Account[] accounts = accountManager.getAccounts(); Account[] accounts = accountManager.getAccounts();
ArrayList<String> accountNames = new ArrayList<String>(); ArrayList<String> accountNames = new ArrayList<String>();
@ -117,12 +120,16 @@ public class GtasksLoginActivity extends ListActivity {
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN); authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
onAuthTokenSuccess(); onAuthTokenSuccess();
} }
} catch (Exception e) { } catch (final Exception e) {
e.printStackTrace(); Log.e("gtasks-login", "Login Error", e); //$NON-NLS-1$ //$NON-NLS-2$
GtasksLoginActivity.this.runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Toast.makeText(GtasksLoginActivity.this, R.string.gtasks_GLA_errorAuth, Toast.LENGTH_LONG).show(); int error = e instanceof IOException ? R.string.gtasks_GLA_errorIOAuth :
R.string.gtasks_GLA_errorAuth;
Toast.makeText(GtasksLoginActivity.this,
error,
Toast.LENGTH_LONG).show();
} }
}); });
} finally { } finally {

@ -13,6 +13,9 @@
-keep class com.google.common.base.Preconditions -keep class com.google.common.base.Preconditions
-keep class * extends com.todoroo.andlib.data.AbstractModel -keep class * extends com.todoroo.andlib.data.AbstractModel
-keep class android.support.v4.** -keep class android.support.v4.**
-keep class com.google.gson.stream.JsonReader {
public void setLenient(boolean);
}
# ignore reflection-based access from google libraries # ignore reflection-based access from google libraries
-dontwarn com.google.** -dontwarn com.google.**

@ -1,14 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="fill_parent"
android:layout_height="wrap_content"> android:layout_height="fill_parent"
style="@style/Content">
<ListView android:id="@android:id/list" <ListView android:id="@android:id/list"
android:layout_width="wrap_content" android:layout_width="fill_parent"
android:layout_height="wrap_content"/> android:layout_height="fill_parent"/>
<TextView android:id="@android:id/empty" <TextView android:id="@android:id/empty"
android:layout_width="wrap_content" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="fill_parent"
android:text="@string/gtasks_GLA_noaccounts"/> android:text="@string/gtasks_GLA_noaccounts"
android:gravity="center"
style="@style/TextAppearance.TLA_NoItems" />
</LinearLayout> </FrameLayout>

@ -220,11 +220,8 @@
<!-- share login: Login Title --> <!-- share login: Login Title -->
<string name="actfm_ALA_login_title">Login to Astrid.com</string> <string name="actfm_ALA_login_title">Login to Astrid.com</string>
<!-- share login: OAUTH Login Prompt --> <!-- share login: Google Auth title -->
<string name="actfm_OLA_prompt">Please connect to Google:</string> <string name="actfm_GAA_title">Select a Google account:</string>
<!-- share login: Sharing notice -->
<string name="actfm_ALA_notice">Astrid won\'t send messages e-mails without permission.</string>
<!-- ================================================ Synchronization == --> <!-- ================================================ Synchronization == -->

@ -75,6 +75,9 @@
<!-- Error Message when we receive a HTTP 401 Unauthorized --> <!-- Error Message when we receive a HTTP 401 Unauthorized -->
<string name="gtasks_GLA_errorAuth">Error authenticating! Please check your username and password in your phone\'s account manager</string> <string name="gtasks_GLA_errorAuth">Error authenticating! Please check your username and password in your phone\'s account manager</string>
<!-- Error Message when we receive an IO Exception -->
<string name="gtasks_GLA_errorIOAuth">Sorry, we had trouble communicating with Google servers. Please try again later.</string>
<!-- Error Message when we receive a HTTP 401 Unauthorized multiple times --> <!-- Error Message when we receive a HTTP 401 Unauthorized multiple times -->
<string name="gtasks_GLA_errorAuth_captcha">You may have encountered a captcha. <string name="gtasks_GLA_errorAuth_captcha">You may have encountered a captcha.

@ -15,9 +15,9 @@
<string name="welcome_title_7_return">That\'s it!</string> <string name="welcome_title_7_return">That\'s it!</string>
<string name="welcome_body_1">The perfect personal\nto-do list that works great\nwith friends</string> <string name="welcome_body_1">The perfect to-do list that \nworks great with friends</string>
<string name="welcome_body_2">Perfect for any list:\nto read, to watch, to buy,\nto visit, to do!</string> <string name="welcome_body_2">Perfect for any list:\nread, watch, buy, visit!</string>
<string name="welcome_body_3">Share lists\nwith friends, housemates,\nor your sweetheart!</string> <string name="welcome_body_3">Share lists with \nfriends, housemates,\nor your sweetheart!</string>
<string name="welcome_body_4">Never wonder who\'s\nbringing dessert!</string> <string name="welcome_body_4">Never wonder who\'s\nbringing dessert!</string>
<string name="welcome_body_5">Tap to add notes,\nset reminders,\nand much more!</string> <string name="welcome_body_5">Tap to add notes,\nset reminders,\nand much more!</string>
<string name="welcome_body_6">Additional features,\nproductivity tips, and\nsuggestions from friends</string> <string name="welcome_body_6">Additional features,\nproductivity tips, and\nsuggestions from friends</string>

@ -73,7 +73,7 @@ public class MetadataDao extends DatabaseDao<Metadata> {
item.setValue(Metadata.CREATION_DATE, DateUtilities.now()); item.setValue(Metadata.CREATION_DATE, DateUtilities.now());
boolean state = super.persist(item); boolean state = super.persist(item);
if(Preferences.getBoolean(AstridPreferences.P_FIRST_LIST, false)) { if(Preferences.getBoolean(AstridPreferences.P_FIRST_LIST, true)) {
if (state && item.getValue(Metadata.KEY).equals(TagService.KEY)) { if (state && item.getValue(Metadata.KEY).equals(TagService.KEY)) {
StatisticsService.reportEvent(StatisticsConstants.USER_FIRST_LIST); StatisticsService.reportEvent(StatisticsConstants.USER_FIRST_LIST);
Preferences.setBoolean(AstridPreferences.P_FIRST_LIST, false); Preferences.setBoolean(AstridPreferences.P_FIRST_LIST, false);

@ -207,9 +207,9 @@ public class TaskDao extends DatabaseDao<Task> {
} }
private void userRetentionMetrics() { private void userRetentionMetrics() {
if(Preferences.getBoolean(AstridPreferences.P_FIRST_ACTION, false)) { if(Preferences.getBoolean(AstridPreferences.P_FIRST_TASK, true)) {
StatisticsService.reportEvent(StatisticsConstants.USER_FIRST_TASK); StatisticsService.reportEvent(StatisticsConstants.USER_FIRST_TASK);
Preferences.setBoolean(AstridPreferences.P_FIRST_ACTION, false); Preferences.setBoolean(AstridPreferences.P_FIRST_TASK, false);
} }
long firstLaunchTime = Preferences.getLong(AstridPreferences.P_FIRST_LAUNCH, 0); long firstLaunchTime = Preferences.getLong(AstridPreferences.P_FIRST_LAUNCH, 0);

@ -41,6 +41,7 @@ import com.todoroo.astrid.utility.AstridPreferences;
public final class UpgradeService { public final class UpgradeService {
public static final int V3_9_2_3 = 210;
public static final int V3_9_2_2 = 209; public static final int V3_9_2_2 = 209;
public static final int V3_9_2_1 = 208; public static final int V3_9_2_1 = 208;
public static final int V3_9_2 = 207; public static final int V3_9_2 = 207;
@ -174,6 +175,14 @@ public final class UpgradeService {
Preferences.clear(AstridPreferences.P_UPGRADE_FROM); Preferences.clear(AstridPreferences.P_UPGRADE_FROM);
StringBuilder changeLog = new StringBuilder(); StringBuilder changeLog = new StringBuilder();
if (from >= V3_9_2 && from < V3_9_2_3) {
newVersionString(changeLog, "3.9.2.3 (1/20/12)", new String[] {
"Fixed a bug with displaying update messages",
"Fixed an occasional crash in Gtasks Sync",
"Other minor bugfixes"
});
}
if (from >= V3_9_2 && from < V3_9_2_2) { if (from >= V3_9_2 && from < V3_9_2_2) {
newVersionString(changeLog, "3.9.2.2 (1/19/12)", new String[] { newVersionString(changeLog, "3.9.2.2 (1/19/12)", new String[] {
"Astrid now recognizes words like 'tomorrow', 'monday', '!!!' and '2 pm' to set date and importance", "Astrid now recognizes words like 'tomorrow', 'monday', '!!!' and '2 pm' to set date and importance",

@ -15,7 +15,7 @@ public class AstridPreferences {
private static final String P_CURRENT_VERSION = "cv"; //$NON-NLS-1$ private static final String P_CURRENT_VERSION = "cv"; //$NON-NLS-1$
public static final String P_FIRST_ACTION = "fa"; //$NON-NLS-1$ public static final String P_FIRST_TASK = "ft"; //$NON-NLS-1$
public static final String P_FIRST_LIST = "fl"; //$NON-NLS-1$ public static final String P_FIRST_LIST = "fl"; //$NON-NLS-1$

Loading…
Cancel
Save