Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3f186d5
Commerce: customer lookup, identity and signed answers in CommerceMan…
shai-almog Nov 11, 2026
205ea68
Commerce: declare and stamp the cloud commerce build hints
shai-almog Nov 11, 2026
4652da2
Commerce: offerings, paywalls and the customer center on the client
shai-almog Nov 11, 2026
69beea4
Commerce: in-app purchase on the native macOS port
shai-almog Nov 11, 2026
d2ec517
Commerce: Amazon Appstore in-app purchase on Android
shai-almog Nov 11, 2026
f1c707a
Commerce: web checkout, billing portal, promotional offers and the Ma…
shai-almog Nov 11, 2026
b7f6f8d
Developer guide: rewrite the Commerce chapter for offerings, paywalls…
shai-almog Nov 11, 2026
848cd6d
Commerce: a shown paywall returns to the previous form when a purchas…
shai-almog Nov 11, 2026
68fcfca
Developer guide: name the Commerce console pages as the console does
shai-almog Nov 11, 2026
9e62cdf
Commerce: analytics events, the analytics client id in requests, and …
shai-almog Nov 11, 2026
db31662
Purchase e2e: refresh commerce after the StoreKit purchase and link t…
shai-almog Nov 11, 2026
f5eec5d
Commerce: trust only signed and verified cloud answers, cache the sig…
shai-almog Nov 11, 2026
9fd8c30
Commerce: /validate answers are signed and verified like the other de…
shai-almog Nov 11, 2026
a9aea74
Developer guide: Commerce identity, transfer policy, signed answers, …
shai-almog Nov 11, 2026
31c6d82
Commerce: each signed answer carries its own envelope, and answers bo…
shai-almog Nov 11, 2026
e19a737
Purchase test app: add the Codename One header to the files the branc…
shai-almog Nov 11, 2026
60e8388
Commerce: iterate the endpoint paths with a for-each (PMD ForLoopCanB…
shai-almog Nov 11, 2026
be1f85c
Commerce: embed the production public key of the Commerce service
shai-almog Nov 11, 2026
b2cfeb5
Merge remote-tracking branch 'origin/master' into commerce-parity
shai-almog Nov 11, 2026
fc71fe8
Android port: exclude AmazonBillingSupport from the Ant and NetBeans …
shai-almog Nov 12, 2026
7449404
Commerce docs: a runnable paywall snippet, contractions in the Amazon…
shai-almog Nov 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions CodenameOne/src/com/codename1/analytics/Analytics.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,72 @@ public static void flush() {
}
}

// The install-attribution hook. One observer, held here rather than in
// the invite package so that another part of the framework can listen
// without naming a class of that package: the builders read a reference
// to it as "this application uses invites" and add what invites need.
private static Runnable attributionObserver;
private static boolean attributionKnown;
private static boolean attributionObserverTold;

/// Framework hook: registers the observer that is told when the invite
/// attribution of this install is known. It runs at most once per
/// registration -- at once when the attribution is already known, and
/// otherwise when it arrives. This is separate from the application's own
/// `InviteListener`, which it neither replaces nor delays.
///
/// #### Parameters
///
/// - `observer`: the observer, or null to remove it
///
/// #### Deprecated
///
/// Internal framework hook; an application listens with an
/// `InviteListener`.
public static void setAttributionObserver(Runnable observer) {
attributionObserver = observer;
attributionObserverTold = false;
if (attributionKnown) {
tellAttributionObserver();
}
}

/// Framework hook: called by the invite support when it knows whether
/// this install has an invite attribution. Tells the observer registered
/// with [#setAttributionObserver(Runnable)] the first time the answer is
/// yes. Never throws into the caller.
///
/// #### Parameters
///
/// - `available`: true when the install has an attribution, false when
/// it was forgotten
///
/// #### Deprecated
///
/// Internal framework hook; not intended for app use.
public static void attributionAvailable(boolean available) {
attributionKnown = available;
if (available) {
tellAttributionObserver();
} else {
// A later attribution in this process is news to the observer.
attributionObserverTold = false;
}
}

private static void tellAttributionObserver() {
Runnable observer = attributionObserver;
if (observer == null || attributionObserverTold) {
return;
}
attributionObserverTold = true;
try {
observer.run();
} catch (Throwable t) {
Log.e(t);
}
}

/// The pseudonymous client id, generating and persisting one on first use.
/// Not derived from any hardware identifier.
///
Expand Down
17 changes: 17 additions & 0 deletions CodenameOne/src/com/codename1/analytics/invite/Invites.java
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,7 @@ private static void flush(boolean skipInFlight) {
/// that left the referral dimensions behind would re-link the fresh
/// identity to the same inviter.
public static void reset() {
Analytics.attributionAvailable(false);
if (!resetVerified()) {
// The records did not go, and this method promised they would.
//
Expand Down Expand Up @@ -3890,7 +3891,23 @@ private static Map<String, String> parseParams(String json) {
// restart; deliveredThisRun covers the window between resolving and the
// flag reaching the disk, so a failed write costs at most a duplicate
// after a crash rather than one on every launch.
// Tells the framework's own observer (Analytics.setAttributionObserver)
// that this install has an attribution. It is not the application's
// listener and takes nothing from it: no delivered flag is read or
// written here, and Analytics tells its observer once however often this
// runs.
private static void announceAttribution() {
try {
if (getAttribution() != null) {
Analytics.attributionAvailable(true);
}
} catch (Throwable t) {
Log.e(t);
}
}

private static void deliverPending() {
announceAttribution();
if (listener == null || deliveredThisRun) {
return;
}
Expand Down
Loading
Loading