aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/app/src/main/java/io/coinos/app/Push.java38
-rw-r--r--android/app/src/main/java/io/coinos/app/PushReceiver.java7
2 files changed, 39 insertions, 6 deletions
diff --git a/android/app/src/main/java/io/coinos/app/Push.java b/android/app/src/main/java/io/coinos/app/Push.java
index 1c4bee5..925693a 100644
--- a/android/app/src/main/java/io/coinos/app/Push.java
+++ b/android/app/src/main/java/io/coinos/app/Push.java
@@ -52,6 +52,10 @@ public final class Push {
private static final String KEY_DIST = "distributor";
private static final String KEY_ENDPOINT = "endpoint";
private static final String KEY_SENT = "endpointSent";
+ private static final String KEY_TRY = "tryIndex";
+ private static final String KEY_TRY_AT = "tryAt";
+ /** How long a distributor gets to answer before we try the next one. */
+ private static final long TRY_MS = 60_000;
static SharedPreferences prefs(Context c) {
return c.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
@@ -81,17 +85,41 @@ public final class Push {
return out;
}
+ /**
+ * Which distributor to ask.
+ *
+ * <p>Not simply the first one installed. Several apps embed a distributor
+ * for their own use and export it anyway — a phone here had three, and the
+ * first two were Element's and Yakihonne's internal ones, which will never
+ * hand an endpoint to anybody else. The spec's answer is to let the user
+ * choose, but this app has no settings screen to choose in, so it works
+ * through them instead: ask one, and if no endpoint has arrived by the next
+ * launch, ask the next. Whoever answers is remembered for good.
+ */
static String distributor(Context c) {
- String saved = prefs(c).getString(KEY_DIST, null);
+ SharedPreferences p = prefs(c);
List<String> all = distributors(c);
- // a distributor that's been uninstalled is not a distributor
- if (saved != null && all.contains(saved)) return saved;
if (all.isEmpty()) return null;
- String pick = all.get(0);
- prefs(c).edit().putString(KEY_DIST, pick).apply();
+ String saved = p.getString(KEY_DIST, null);
+ // one that answered, and is still installed, is the one we keep
+ if (saved != null && all.contains(saved) && p.getString(KEY_ENDPOINT, null) != null) return saved;
+ // otherwise the one we're currently trying, moving on if it's had its
+ // chance and produced nothing
+ int idx = p.getInt(KEY_TRY, 0);
+ long since = p.getLong(KEY_TRY_AT, 0);
+ if (saved != null && since > 0 && System.currentTimeMillis() - since > TRY_MS) idx++;
+ if (idx >= all.size()) idx = 0;
+ String pick = all.get(idx);
+ p.edit().putString(KEY_DIST, pick).putInt(KEY_TRY, idx).putLong(KEY_TRY_AT, System.currentTimeMillis()).apply();
return pick;
}
+ /** Give up on the current distributor; the next call picks another. */
+ static void nextDistributor(Context c) {
+ SharedPreferences p = prefs(c);
+ p.edit().putInt(KEY_TRY, p.getInt(KEY_TRY, 0) + 1).putLong(KEY_TRY_AT, 0).remove(KEY_DIST).apply();
+ }
+
static String endpoint(Context c) {
return prefs(c).getString(KEY_ENDPOINT, null);
}
diff --git a/android/app/src/main/java/io/coinos/app/PushReceiver.java b/android/app/src/main/java/io/coinos/app/PushReceiver.java
index 508c331..ce3e3f0 100644
--- a/android/app/src/main/java/io/coinos/app/PushReceiver.java
+++ b/android/app/src/main/java/io/coinos/app/PushReceiver.java
@@ -36,7 +36,12 @@ public class PushReceiver extends BroadcastReceiver {
if (endpoint != null && !endpoint.isEmpty()) Push.setEndpoint(context, endpoint);
break;
}
- case Push.ACTION_REGISTRATION_FAILED:
+ case Push.ACTION_REGISTRATION_FAILED: {
+ // this one won't have us — try the next one at the next opportunity
+ Push.nextDistributor(context);
+ Push.register(context);
+ break;
+ }
case Push.ACTION_UNREGISTERED: {
Push.prefs(context).edit().remove("endpoint").putBoolean("endpointSent", false).apply();
break;