Prevent flattr login if API keys are missing

closes #474
This commit is contained in:
daniel oeh 2014-08-06 19:37:18 +02:00
parent 04cb23acff
commit ee807628bb
3 changed files with 249 additions and 216 deletions

View File

@ -45,6 +45,7 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
private static final String TAG = "PreferenceActivity"; private static final String TAG = "PreferenceActivity";
private static final String PREF_FLATTR_THIS_APP = "prefFlattrThisApp"; private static final String PREF_FLATTR_THIS_APP = "prefFlattrThisApp";
private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs"; private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
@ -332,6 +333,7 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
boolean hasFlattrToken = FlattrUtils.hasToken(); boolean hasFlattrToken = FlattrUtils.hasToken();
findPreference(PREF_FLATTR_SETTINGS).setEnabled(FlattrUtils.hasAPICredentials());
findPreference(PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken); findPreference(PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken);
findPreference(PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken); findPreference(PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken);
findPreference(PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken); findPreference(PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken);

View File

@ -872,7 +872,7 @@ public final class DBTasks {
item.getFlattrStatus().setFlattrQueue(); item.getFlattrStatus().setFlattrQueue();
DBWriter.setFlattredStatus(context, item, true); DBWriter.setFlattredStatus(context, item, true);
} else { } else {
FlattrUtils.showNoTokenDialog(context, item.getPaymentLink()); FlattrUtils.showNoTokenDialogOrRedirect(context, item.getPaymentLink());
} }
} }
@ -888,7 +888,7 @@ public final class DBTasks {
feed.getFlattrStatus().setFlattrQueue(); feed.getFlattrStatus().setFlattrQueue();
DBWriter.setFlattredStatus(context, feed, true); DBWriter.setFlattredStatus(context, feed, true);
} else { } else {
FlattrUtils.showNoTokenDialog(context, feed.getPaymentLink()); FlattrUtils.showNoTokenDialogOrRedirect(context, feed.getPaymentLink());
} }
} }

View File

@ -9,12 +9,8 @@ import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.PodcastApp; import org.apache.commons.lang3.StringUtils;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.FlattrAuthActivity;
import de.danoeh.antennapod.asynctask.FlattrTokenFetcher;
import de.danoeh.antennapod.storage.DBWriter;
import org.shredzone.flattr4j.FlattrService; import org.shredzone.flattr4j.FlattrService;
import org.shredzone.flattr4j.exception.FlattrException; import org.shredzone.flattr4j.exception.FlattrException;
import org.shredzone.flattr4j.model.Flattr; import org.shredzone.flattr4j.model.Flattr;
@ -23,252 +19,287 @@ import org.shredzone.flattr4j.oauth.AccessToken;
import org.shredzone.flattr4j.oauth.AndroidAuthenticator; import org.shredzone.flattr4j.oauth.AndroidAuthenticator;
import org.shredzone.flattr4j.oauth.Scope; import org.shredzone.flattr4j.oauth.Scope;
import java.util.*; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.TimeZone;
/** Utility methods for doing something with flattr. */ import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.FlattrAuthActivity;
import de.danoeh.antennapod.asynctask.FlattrTokenFetcher;
import de.danoeh.antennapod.storage.DBWriter;
/**
* Utility methods for doing something with flattr.
*/
public class FlattrUtils { public class FlattrUtils {
private static final String TAG = "FlattrUtils"; private static final String TAG = "FlattrUtils";
private static final String HOST_NAME = "de.danoeh.antennapod"; private static final String HOST_NAME = "de.danoeh.antennapod";
private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken"; private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken";
// Flattr URL for this app. // Flattr URL for this app.
public static final String APP_URL = "http://antennapod.com"; public static final String APP_URL = "http://antennapod.com";
// Human-readable flattr-page. // Human-readable flattr-page.
public static final String APP_LINK = "https://flattr.com/thing/745609/"; public static final String APP_LINK = "https://flattr.com/thing/745609/";
public static final String APP_THING_ID = "745609"; public static final String APP_THING_ID = "745609";
private static volatile AccessToken cachedToken; private static volatile AccessToken cachedToken;
private static AndroidAuthenticator createAuthenticator() { private static AndroidAuthenticator createAuthenticator() {
return new AndroidAuthenticator(HOST_NAME, BuildConfig.FLATTR_APP_KEY, return new AndroidAuthenticator(HOST_NAME, BuildConfig.FLATTR_APP_KEY,
BuildConfig.FLATTR_APP_SECRET); BuildConfig.FLATTR_APP_SECRET);
} }
public static void startAuthProcess(Context context) throws FlattrException { public static void startAuthProcess(Context context) throws FlattrException {
AndroidAuthenticator auth = createAuthenticator(); AndroidAuthenticator auth = createAuthenticator();
auth.setScope(EnumSet.of(Scope.FLATTR)); auth.setScope(EnumSet.of(Scope.FLATTR));
Intent intent = auth.createAuthenticateIntent(); Intent intent = auth.createAuthenticateIntent();
context.startActivity(intent); context.startActivity(intent);
} }
private static AccessToken retrieveToken() { private static AccessToken retrieveToken() {
if (cachedToken == null) { if (cachedToken == null) {
if (BuildConfig.DEBUG) if (BuildConfig.DEBUG)
Log.d(TAG, "Retrieving access token"); Log.d(TAG, "Retrieving access token");
String token = PreferenceManager.getDefaultSharedPreferences( String token = PreferenceManager.getDefaultSharedPreferences(
PodcastApp.getInstance()) PodcastApp.getInstance())
.getString(PREF_ACCESS_TOKEN, null); .getString(PREF_ACCESS_TOKEN, null);
if (token != null) { if (token != null) {
if (BuildConfig.DEBUG) if (BuildConfig.DEBUG)
Log.d(TAG, "Found access token. Caching."); Log.d(TAG, "Found access token. Caching.");
cachedToken = new AccessToken(token); cachedToken = new AccessToken(token);
} else { } else {
if (BuildConfig.DEBUG) if (BuildConfig.DEBUG)
Log.d(TAG, "No access token found"); Log.d(TAG, "No access token found");
return null; return null;
} }
} }
return cachedToken; return cachedToken;
} }
public static boolean hasToken() { /**
return retrieveToken() != null; * Returns true if FLATTR_APP_KEY and FLATTR_APP_SECRET in BuildConfig are not null and not empty
} */
public static boolean hasAPICredentials() {
return StringUtils.isNotEmpty(BuildConfig.FLATTR_APP_KEY)
&& StringUtils.isNoneEmpty(BuildConfig.FLATTR_APP_SECRET);
}
public static void storeToken(AccessToken token) { public static boolean hasToken() {
if (BuildConfig.DEBUG) return retrieveToken() != null;
Log.d(TAG, "Storing token"); }
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(PodcastApp.getInstance()).edit();
if (token != null) {
editor.putString(PREF_ACCESS_TOKEN, token.getToken());
} else {
editor.putString(PREF_ACCESS_TOKEN, null);
}
editor.commit();
cachedToken = token;
}
public static void deleteToken() { public static void storeToken(AccessToken token) {
if (BuildConfig.DEBUG) if (BuildConfig.DEBUG)
Log.d(TAG, "Deleting flattr token"); Log.d(TAG, "Storing token");
storeToken(null); SharedPreferences.Editor editor = PreferenceManager
} .getDefaultSharedPreferences(PodcastApp.getInstance()).edit();
if (token != null) {
editor.putString(PREF_ACCESS_TOKEN, token.getToken());
} else {
editor.putString(PREF_ACCESS_TOKEN, null);
}
editor.commit();
cachedToken = token;
}
public static Thing getAppThing(Context context) { public static void deleteToken() {
FlattrService fs = FlattrServiceCreator.getService(retrieveToken()); if (BuildConfig.DEBUG)
try { Log.d(TAG, "Deleting flattr token");
Thing thing = fs.getThing(Thing.withId(APP_THING_ID)); storeToken(null);
return thing; }
} catch (FlattrException e) {
e.printStackTrace();
showErrorDialog(context, e.getMessage());
return null;
}
}
public static void clickUrl(Context context, String url) public static Thing getAppThing(Context context) {
throws FlattrException { FlattrService fs = FlattrServiceCreator.getService(retrieveToken());
if (hasToken()) { try {
FlattrService fs = FlattrServiceCreator.getService(retrieveToken()); Thing thing = fs.getThing(Thing.withId(APP_THING_ID));
fs.click(url); return thing;
} else { } catch (FlattrException e) {
Log.e(TAG, "clickUrl was called with null access token"); e.printStackTrace();
} showErrorDialog(context, e.getMessage());
} return null;
}
public static List<Flattr> retrieveFlattredThings() }
throws FlattrException {
ArrayList<Flattr> myFlattrs = new ArrayList<Flattr>();
if (hasToken()) { public static void clickUrl(Context context, String url)
FlattrService fs = FlattrServiceCreator.getService(retrieveToken()); throws FlattrException {
if (hasToken()) {
FlattrService fs = FlattrServiceCreator.getService(retrieveToken());
fs.click(url);
} else {
Log.e(TAG, "clickUrl was called with null access token");
}
}
Calendar firstOfMonth = Calendar.getInstance(TimeZone.getTimeZone("UTC")); public static List<Flattr> retrieveFlattredThings()
firstOfMonth.set(Calendar.MILLISECOND, 0); throws FlattrException {
firstOfMonth.set(Calendar.SECOND, 0); ArrayList<Flattr> myFlattrs = new ArrayList<Flattr>();
firstOfMonth.set(Calendar.MINUTE, 0);
firstOfMonth.set(Calendar.HOUR_OF_DAY, 0);
firstOfMonth.set(Calendar.DAY_OF_MONTH, Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));
Date firstOfMonthDate = firstOfMonth.getTime();
// subscriptions some times get flattrd slightly before midnight - give it an hour leeway if (hasToken()) {
firstOfMonthDate = new Date(firstOfMonthDate.getTime() - 60*60*1000); FlattrService fs = FlattrServiceCreator.getService(retrieveToken());
final int FLATTR_COUNT = 30;
final int FLATTR_MAXPAGE = 5;
for (int page = 0; page < FLATTR_MAXPAGE; page++) {
for (Flattr fl: fs.getMyFlattrs(FLATTR_COUNT, page)) {
if (fl.getCreated().after(firstOfMonthDate))
myFlattrs.add(fl);
else
break;
}
}
if (BuildConfig.DEBUG) {
Log.d(TAG, "Got my flattrs list of length " + Integer.toString(myFlattrs.size()) + " comparison date" + firstOfMonthDate);
for (Flattr fl: myFlattrs) { Calendar firstOfMonth = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Thing thing = fl.getThing(); firstOfMonth.set(Calendar.MILLISECOND, 0);
Log.d(TAG, "Flattr thing: " + fl.getThingId() + " name: " + thing.getTitle() + " url: " + thing.getUrl() + " on: " + fl.getCreated()); firstOfMonth.set(Calendar.SECOND, 0);
} firstOfMonth.set(Calendar.MINUTE, 0);
} firstOfMonth.set(Calendar.HOUR_OF_DAY, 0);
firstOfMonth.set(Calendar.DAY_OF_MONTH, Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));
} else {
Log.e(TAG, "retrieveFlattrdThings was called with null access token");
}
return myFlattrs;
}
public static void handleCallback(Context context, Uri uri) { Date firstOfMonthDate = firstOfMonth.getTime();
AndroidAuthenticator auth = createAuthenticator();
new FlattrTokenFetcher(context, auth, uri).executeAsync();
}
public static void revokeAccessToken(Context context) { // subscriptions some times get flattrd slightly before midnight - give it an hour leeway
if (BuildConfig.DEBUG) firstOfMonthDate = new Date(firstOfMonthDate.getTime() - 60 * 60 * 1000);
Log.d(TAG, "Revoking access token");
deleteToken(); final int FLATTR_COUNT = 30;
FlattrServiceCreator.deleteFlattrService(); final int FLATTR_MAXPAGE = 5;
showRevokeDialog(context);
for (int page = 0; page < FLATTR_MAXPAGE; page++) {
for (Flattr fl : fs.getMyFlattrs(FLATTR_COUNT, page)) {
if (fl.getCreated().after(firstOfMonthDate))
myFlattrs.add(fl);
else
break;
}
}
if (BuildConfig.DEBUG) {
Log.d(TAG, "Got my flattrs list of length " + Integer.toString(myFlattrs.size()) + " comparison date" + firstOfMonthDate);
for (Flattr fl : myFlattrs) {
Thing thing = fl.getThing();
Log.d(TAG, "Flattr thing: " + fl.getThingId() + " name: " + thing.getTitle() + " url: " + thing.getUrl() + " on: " + fl.getCreated());
}
}
} else {
Log.e(TAG, "retrieveFlattrdThings was called with null access token");
}
return myFlattrs;
}
public static void handleCallback(Context context, Uri uri) {
AndroidAuthenticator auth = createAuthenticator();
new FlattrTokenFetcher(context, auth, uri).executeAsync();
}
public static void revokeAccessToken(Context context) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Revoking access token");
deleteToken();
FlattrServiceCreator.deleteFlattrService();
showRevokeDialog(context);
DBWriter.clearAllFlattrStatus(context); DBWriter.clearAllFlattrStatus(context);
} }
// ------------------------------------------------ DIALOGS // ------------------------------------------------ DIALOGS
public static void showRevokeDialog(final Context context) { public static void showRevokeDialog(final Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.access_revoked_title); builder.setTitle(R.string.access_revoked_title);
builder.setMessage(R.string.access_revoked_info); builder.setMessage(R.string.access_revoked_info);
builder.setNeutralButton(android.R.string.ok, new OnClickListener() { builder.setNeutralButton(android.R.string.ok, new OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
dialog.cancel(); dialog.cancel();
} }
}); });
builder.create().show(); builder.create().show();
} }
public static void showNoTokenDialog(final Context context, final String url) { /**
if (BuildConfig.DEBUG) * Opens a dialog that ask the user to either connect the app with flattr or to be redirected to
Log.d(TAG, "Creating showNoTokenDialog"); * the thing's website.
AlertDialog.Builder builder = new AlertDialog.Builder(context); * If no API credentials are available, the user will immediately be redirected to the thing's website.
builder.setTitle(R.string.no_flattr_token_title); * */
builder.setMessage(R.string.no_flattr_token_msg); public static void showNoTokenDialogOrRedirect(final Context context, final String url) {
builder.setPositiveButton(R.string.authenticate_now_label, if (hasAPICredentials()) {
new OnClickListener() { AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.no_flattr_token_title);
builder.setMessage(R.string.no_flattr_token_msg);
builder.setPositiveButton(R.string.authenticate_now_label,
new OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
context.startActivity(new Intent(context, context.startActivity(new Intent(context,
FlattrAuthActivity.class)); FlattrAuthActivity.class));
} }
}); }
builder.setNegativeButton(R.string.visit_website_label, );
new OnClickListener() {
@Override builder.setNegativeButton(R.string.visit_website_label,
public void onClick(DialogInterface dialog, int which) { new OnClickListener() {
Uri uri = Uri.parse(url);
context.startActivity(new Intent(Intent.ACTION_VIEW,
uri));
}
}); @Override
builder.create().show(); public void onClick(DialogInterface dialog, int which) {
} Uri uri = Uri.parse(url);
context.startActivity(new Intent(Intent.ACTION_VIEW,
uri));
}
public static void showForbiddenDialog(final Context context, }
final String url) { );
AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.create().show();
builder.setTitle(R.string.action_forbidden_title); } else {
builder.setMessage(R.string.action_forbidden_msg); Uri uri = Uri.parse(url);
builder.setPositiveButton(R.string.authenticate_now_label, context.startActivity(new Intent(Intent.ACTION_VIEW, uri));
new OnClickListener() { }
}
@Override public static void showForbiddenDialog(final Context context,
public void onClick(DialogInterface dialog, int which) { final String url) {
context.startActivity(new Intent(context, AlertDialog.Builder builder = new AlertDialog.Builder(context);
FlattrAuthActivity.class)); builder.setTitle(R.string.action_forbidden_title);
} builder.setMessage(R.string.action_forbidden_msg);
builder.setPositiveButton(R.string.authenticate_now_label,
new OnClickListener() {
}); @Override
builder.setNegativeButton(R.string.visit_website_label, public void onClick(DialogInterface dialog, int which) {
new OnClickListener() { context.startActivity(new Intent(context,
FlattrAuthActivity.class));
}
@Override }
public void onClick(DialogInterface dialog, int which) { );
Uri uri = Uri.parse(url); builder.setNegativeButton(R.string.visit_website_label,
context.startActivity(new Intent(Intent.ACTION_VIEW, new OnClickListener() {
uri));
}
}); @Override
builder.create().show(); public void onClick(DialogInterface dialog, int which) {
} Uri uri = Uri.parse(url);
context.startActivity(new Intent(Intent.ACTION_VIEW,
uri));
}
public static void showErrorDialog(final Context context, final String msg) { }
AlertDialog.Builder builder = new AlertDialog.Builder(context); );
builder.setTitle(R.string.error_label); builder.create().show();
builder.setMessage(msg); }
builder.setNeutralButton(android.R.string.ok, new OnClickListener() {
@Override public static void showErrorDialog(final Context context, final String msg) {
public void onClick(DialogInterface dialog, int which) { AlertDialog.Builder builder = new AlertDialog.Builder(context);
dialog.cancel(); builder.setTitle(R.string.error_label);
} builder.setMessage(msg);
}); builder.setNeutralButton(android.R.string.ok, new OnClickListener() {
builder.create().show();
} @Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.create().show();
}
} }