Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/neat-bugs-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@capawesome/capacitor-age-signals': minor
---

feat!: add `DECLARED` status, `ageRangeDeclaration`, and `SDK_VERSION_OUTDATED` error
27 changes: 19 additions & 8 deletions packages/age-signals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ npx cap sync

If needed, you can define the following project variable in your app's `variables.gradle` file to change the default version of the dependency:

- `$androidPlayAgeSignalsVersion` version of `com.google.android.play:age-signals` (default: `0.0.2`)
- `$androidPlayAgeSignalsVersion` version of `com.google.android.play:age-signals` (default: `0.0.3`)

This can be useful if you encounter dependency conflicts with other plugins in your project.

Expand Down Expand Up @@ -316,13 +316,14 @@ Only available on Android.

#### CheckAgeSignalsResult

| Prop | Type | Description | Since |
| ---------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| **`userStatus`** | <code><a href="#userstatus">UserStatus</a></code> | The user's verification status. | 0.0.1 |
| **`ageLower`** | <code>number</code> | The (inclusive) lower bound of a supervised user's age range. Only available when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED`. | 0.0.1 |
| **`ageUpper`** | <code>number</code> | The (inclusive) upper bound of a supervised user's age range. Only available when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED` and the user's age is under 18. | 0.0.1 |
| **`mostRecentApprovalDate`** | <code>string</code> | The effective from date of the most recent significant change that was approved. When an app is installed, the date of the most recent significant change prior to install is used. Only available when `userStatus` is `SUPERVISED_APPROVAL_PENDING` or `SUPERVISED_APPROVAL_DENIED`. Only available on Android. | 0.0.1 |
| **`installId`** | <code>string</code> | An ID assigned to supervised user installs by Google Play, used for the purposes of notifying you of revoked app approval. Only available when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED`. Only available on Android. | 0.0.1 |
| Prop | Type | Description | Since |
| ---------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| **`userStatus`** | <code><a href="#userstatus">UserStatus</a></code> | The user's verification status. | 0.0.1 |
| **`ageLower`** | <code>number</code> | The (inclusive) lower bound of a supervised user's age range. Only available when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED`. | 0.0.1 |
| **`ageUpper`** | <code>number</code> | The (inclusive) upper bound of a supervised user's age range. Only available when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED` and the user's age is under 18. | 0.0.1 |
| **`mostRecentApprovalDate`** | <code>string</code> | The effective from date of the most recent significant change that was approved. When an app is installed, the date of the most recent significant change prior to install is used. Only available when `userStatus` is `SUPERVISED_APPROVAL_PENDING` or `SUPERVISED_APPROVAL_DENIED`. Only available on Android. | 0.0.1 |
| **`installId`** | <code>string</code> | An ID assigned to supervised user installs by Google Play, used for the purposes of notifying you of revoked app approval. Only available when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED`. Only available on Android. | 0.0.1 |
| **`ageRangeDeclaration`** | <code><a href="#agerangedeclaration">AgeRangeDeclaration</a></code> | The age range declaration type. Only available on iOS. | 0.4.0 |


#### CheckAgeSignalsOptions
Expand Down Expand Up @@ -376,9 +377,18 @@ Only available on Android.
| **`SupervisedApprovalPending`** | <code>'SUPERVISED_APPROVAL_PENDING'</code> | The user has a supervised Google Account, and their supervising parent has not yet approved one or more pending significant changes. Use `ageLower` and `ageUpper` to determine the user's age range. Use `mostRecentApprovalDate` to determine the last significant change that was approved. | 0.0.1 |
| **`SupervisedApprovalDenied`** | <code>'SUPERVISED_APPROVAL_DENIED'</code> | The user has a supervised Google Account, and their supervising parent denied approval for one or more significant changes. Use `ageLower` and `ageUpper` to determine the user's age range. Use `mostRecentApprovalDate` to determine the last significant change that was approved. | 0.0.1 |
| **`Unknown`** | <code>'UNKNOWN'</code> | The user is not verified or supervised in applicable jurisdictions and regions. These users could be over or under 18. To obtain an age signal from Google Play, ask the user to visit the Play Store to resolve their status. | 0.0.1 |
| **`Declared`** | <code>'DECLARED'</code> | The user has self-declared or guardian-declared their age. Only available on Android. | 0.4.0 |
| **`Empty`** | <code>'EMPTY'</code> | All other users return this value. | 0.0.1 |


#### AgeRangeDeclaration

| Members | Value | Description | Since |
| ---------------------- | -------------------------------- | -------------------------------------------- | ----- |
| **`SelfDeclared`** | <code>'SELF_DECLARED'</code> | The age range was self-declared by the user. | 0.4.0 |
| **`GuardianDeclared`** | <code>'GUARDIAN_DECLARED'</code> | The age range was declared by a guardian. | 0.4.0 |


#### ErrorCode

| Members | Value | Description | Since |
Expand All @@ -393,6 +403,7 @@ Only available on Android.
| **`ClientTransientError`** | <code>'CLIENT_TRANSIENT_ERROR'</code> | There was a transient error in the client device. | 0.0.1 |
| **`AppNotOwned`** | <code>'APP_NOT_OWNED'</code> | The app was not installed by Google Play. | 0.0.1 |
| **`InternalError`** | <code>'INTERNAL_ERROR'</code> | Unknown internal error. | 0.0.1 |
| **`SdkVersionOutdated`** | <code>'SDK_VERSION_OUTDATED'</code> | The Age Signals SDK version is outdated. Only available on Android. | 0.4.0 |

</docgen-api>

Expand Down
2 changes: 1 addition & 1 deletion packages/age-signals/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ext {
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
androidPlayAgeSignalsVersion = project.hasProperty('androidPlayAgeSignalsVersion') ? rootProject.ext.androidPlayAgeSignalsVersion : '0.0.2'
androidPlayAgeSignalsVersion = project.hasProperty('androidPlayAgeSignalsVersion') ? rootProject.ext.androidPlayAgeSignalsVersion : '0.0.3'
}

buildscript {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ private Exception mapErrorCodeToException(@NonNull Exception exception) {
return CustomExceptions.APP_NOT_OWNED;
case 25009:
return CustomExceptions.INTERNAL_ERROR;
case 25010:
return CustomExceptions.SDK_VERSION_OUTDATED;
default:
return exception;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public class CustomExceptions {
);
public static final CustomException APP_NOT_OWNED = new CustomException("APP_NOT_OWNED", "The app was not installed by Google Play.");
public static final CustomException INTERNAL_ERROR = new CustomException("INTERNAL_ERROR", "Unknown internal error.");
public static final CustomException SDK_VERSION_OUTDATED = new CustomException(
"SDK_VERSION_OUTDATED",
"The Age Signals SDK version is outdated."
);
public static final CustomException USER_STATUS_MISSING = new CustomException(null, "userStatus must be provided.");
public static final CustomException FAKE_MANAGER_NOT_ENABLED = new CustomException(null, "Fake manager is not enabled.");
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ private int mapErrorCodeToAgeSignalsErrorCode(@NonNull String errorCode) throws
return AgeSignalsErrorCode.APP_NOT_OWNED;
case "INTERNAL_ERROR":
return AgeSignalsErrorCode.INTERNAL_ERROR;
case "SDK_VERSION_OUTDATED":
return AgeSignalsErrorCode.SDK_VERSION_OUTDATED;
default:
throw new Exception("Invalid errorCode: " + errorCode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ private Integer mapUserStatusToVerificationStatus(@NonNull UserStatus userStatus
return AgeSignalsVerificationStatus.SUPERVISED_APPROVAL_DENIED;
case UNKNOWN:
return AgeSignalsVerificationStatus.UNKNOWN;
case DECLARED:
return AgeSignalsVerificationStatus.DECLARED;
default:
return AgeSignalsVerificationStatus.UNKNOWN;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,21 @@ private UserStatus mapUserStatus(@Nullable Integer status) {
return UserStatus.EMPTY;
}

UserStatus[] values = UserStatus.values();

if (status < 0 || status >= values.length) {
throw new IllegalArgumentException("Invalid UserStatus: " + status);
switch (status) {
case 0:
return UserStatus.VERIFIED;
case 1:
return UserStatus.SUPERVISED;
case 2:
return UserStatus.SUPERVISED_APPROVAL_PENDING;
case 3:
return UserStatus.SUPERVISED_APPROVAL_DENIED;
case 4:
return UserStatus.UNKNOWN;
case 5:
return UserStatus.DECLARED;
default:
throw new IllegalArgumentException("Invalid UserStatus: " + status);
}

return values[status];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ public enum UserStatus {
SUPERVISED_APPROVAL_PENDING,
SUPERVISED_APPROVAL_DENIED,
UNKNOWN,
DECLARED,
EMPTY
}
4 changes: 4 additions & 0 deletions packages/age-signals/ios/Plugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
7C2FC3452ED3795D000FC952 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2FC3442ED3795A000FC952 /* Result.swift */; };
7C2FC3472ED3799B000FC952 /* UserStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2FC3462ED37997000FC952 /* UserStatus.swift */; };
7C2FC34C2ED37E89000FC952 /* CheckAgeSignalsOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2FC34B2ED37E83000FC952 /* CheckAgeSignalsOptions.swift */; };
7C2FC3502ED4A000000FC952 /* AgeRangeDeclaration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2FC34F2ED4A000000FC952 /* AgeRangeDeclaration.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -49,6 +50,7 @@
7C2FC3442ED3795A000FC952 /* Result.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
7C2FC3462ED37997000FC952 /* UserStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserStatus.swift; sourceTree = "<group>"; };
7C2FC34B2ED37E83000FC952 /* CheckAgeSignalsOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckAgeSignalsOptions.swift; sourceTree = "<group>"; };
7C2FC34F2ED4A000000FC952 /* AgeRangeDeclaration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgeRangeDeclaration.swift; sourceTree = "<group>"; };
91781294A431A2A7CC6EB714 /* Pods-Plugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Plugin.release.xcconfig"; path = "Pods/Target Support Files/Pods-Plugin/Pods-Plugin.release.xcconfig"; sourceTree = "<group>"; };
96ED1B6440D6672E406C8D19 /* Pods-PluginTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.debug.xcconfig"; sourceTree = "<group>"; };
F65BB2953ECE002E1EF3E424 /* Pods-PluginTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -122,6 +124,7 @@
7C2FC33C2ED36FC5000FC952 /* Enums */ = {
isa = PBXGroup;
children = (
7C2FC34F2ED4A000000FC952 /* AgeRangeDeclaration.swift */,
7C2FC3462ED37997000FC952 /* UserStatus.swift */,
7C2FC33D2ED36FCB000FC952 /* CustomError.swift */,
);
Expand Down Expand Up @@ -365,6 +368,7 @@
7C2FC3472ED3799B000FC952 /* UserStatus.swift in Sources */,
7C2FC34C2ED37E89000FC952 /* CheckAgeSignalsOptions.swift in Sources */,
7C2FC33E2ED36FCF000FC952 /* CustomError.swift in Sources */,
7C2FC3502ED4A000000FC952 /* AgeRangeDeclaration.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
17 changes: 16 additions & 1 deletion packages/age-signals/ios/Plugin/AgeSignals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,27 @@ import DeclaredAgeRange
status = .unknown
}

let declaration: AgeRangeDeclaration?
if #available(iOS 26.2, *) {
switch range.ageRangeDeclaration {
case .selfDeclared:
declaration = .selfDeclared
case .guardianDeclared:
declaration = .guardianDeclared
@unknown default:
declaration = nil
}
} else {
declaration = nil
}

return CheckAgeSignalsResult(
userStatus: status,
ageLower: lower,
ageUpper: upper,
mostRecentApprovalDate: nil,
installId: nil
installId: nil,
ageRangeDeclaration: declaration
)

@unknown default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ import Capacitor
let ageUpper: Int?
let mostRecentApprovalDate: String?
let installId: String?
let ageRangeDeclaration: AgeRangeDeclaration?

init(
userStatus: UserStatus,
ageLower: Int? = nil,
ageUpper: Int? = nil,
mostRecentApprovalDate: String? = nil,
installId: String? = nil
installId: String? = nil,
ageRangeDeclaration: AgeRangeDeclaration? = nil
) {
self.userStatus = userStatus
self.ageLower = ageLower
self.ageUpper = ageUpper
self.mostRecentApprovalDate = mostRecentApprovalDate
self.installId = installId
self.ageRangeDeclaration = ageRangeDeclaration
}

func toJSObject() -> AnyObject {
Expand All @@ -28,6 +31,7 @@ import Capacitor
result["ageUpper"] = ageUpper
result["mostRecentApprovalDate"] = mostRecentApprovalDate
result["installId"] = installId
result["ageRangeDeclaration"] = ageRangeDeclaration?.rawValue
return result as AnyObject
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
enum AgeRangeDeclaration: String {
case selfDeclared = "SELF_DECLARED"
case guardianDeclared = "GUARDIAN_DECLARED"
}
1 change: 1 addition & 0 deletions packages/age-signals/ios/Plugin/Enums/UserStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ enum UserStatus: String {
case supervisedApprovalPending = "SUPERVISED_APPROVAL_PENDING"
case supervisedApprovalDenied = "SUPERVISED_APPROVAL_DENIED"
case unknown = "UNKNOWN"
case declared = "DECLARED"
case empty = "EMPTY"
}
Loading
Loading