Repository navigation
feat(business): add Kapusch.TikTok.Business.Android (TikTok Business SDK 1.7.1) - #5
Merged
Merged
Conversation
Pin the upstream release AAR (byte-identical to the JitPack artifact), its license and the Gradle distribution by SHA-256 in a lock file separate from the Share package lock, and add a restore script that fails on any checksum mismatch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The businessinterop module compiles against the locked upstream classes only and ships as its own AAR next to the unchanged upstream AAR. The Kotlin object maps a Bundle configuration to TTConfig, initializes on the main thread and reports the outcome at most once through a ValueCallback, with numeric wrapper codes shared with the iOS package. SDK 1.7.1 returns silently from every initializeSdk call after the first, and its async init step swallows Throwables without calling back. The facade therefore records its single native attempt and answers later attempts with an init-incomplete code instead of re-entering a half-built SDK; the managed caller bounds the wait. Track, identify, logout, flush, startTrack and updateAccessToken run synchronously, return whether the SDK accepted them and never throw into the host. Log levels map to the closest Android SDK level. Consumer R8 rules keep the facade, com.tiktok.** and the reflectively loaded AdvertisingIdClient, and tolerate absent Billing and Install Referrer. The Gradle verification metadata covers cold caches and the Linux aapt2 artifact. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add THIRD_PARTY_NOTICES.Business.md for the Business package so the Share package keeps its notices file unchanged, and document the data the SDK collects for privacy and Play Data Safety reviews. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a second packable project that ships the interop AAR, the locked upstream AAR, its license and the Business notices, with buildTransitive props/targets that inject only these two vendor AARs and support a source-mode switch. Shared AndroidX and Kotlin classes come from managed NuGets aligned on the AndroidX lifecycle 2.10 family (minSdk 23), so the package unifies with Billing 8.3 and AppCompat instead of duplicating classes. Billing and Install Referrer stay consumer-owned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Expose the same public API as Kapusch.TikTok.Business.iOS: a TikTokBusinessConfig record with required AppId, TikTokAppIds and AccessToken, InitializeAsync returning TikTokBusinessInitResult (Started, InitializedTrackingDisabled or Failed, int ErrorCode 0 on success, shared 1001/1002 codes), StartTrack, SetTrackingEnabled, TrackEvent and typed StartTrial/Subscribe/Purchase/Registration/Login helpers, Identify, Logout, Flush, UpdateAccessToken, IsInitialized, IsTrackingEnabled, SdkVersion and TestEventCode. Every call returns false before a successful initialization and nothing native loads until InitializeAsync. InitializeAsync validates the values and throws ArgumentException like iOS, shares one native initialization, returns the current state after a success, and is bounded to 30 seconds by a managed timer that does not depend on the main looper. A success that arrives after the timeout still latches the initialized state; retries are deterministic. A deferred start reports InitializedTrackingDisabled with ErrorCode 0. Android-only codes (11xx), constants and the SetTrackingEnabled(false) limitation of SDK 1.7.1 are documented on the members. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
validate-business-package.sh checks the required entries, that exactly two vendor AARs ship with no bundled runtime dependencies, that the upstream AAR matches its lock byte for byte, the JNI signatures the managed layer calls, that the Kotlin wrapper error codes match the managed constants, the consumer R8 rules, the notices, the managed NuGet dependencies and that Billing / Install Referrer stay consumer-owned. The Share validator now also rejects any Business artifact. verify-public.py checks tracked files for pasted App Secrets and filled sample templates, and rejects private terms read at run time from KAPUSCH_PRIVATE_TERMS or the untracked .git/info/private-terms file. No private term is tracked, and failures name only "private term #N". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A plain .NET Android app restores the packed package from artifacts/nuget and shows the consent-gated recipe: the SDK is only initialized after the user accepts. Credentials come from an untracked asset copied from a template. Release builds run R8; an MSBuild switch drops Billing and Install Referrer to prove the package links without them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a public-tree scan job fed by the KAPUSCH_PRIVATE_TERMS secret and a Business job on the same pinned runner and toolchain as the Share job: native build, pack, package validation, then a clean-consumer Release build of the sample with R8, once with Billing 8.3 and Install Referrer and once without them. The Share job is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep a single publish workflow so the existing NuGet Trusted Publishing policy covers both packages. v* tags still release Kapusch.TikTok.Android; business-v* tags release Kapusch.TikTok.Business.Android, which must be X.Y.Z or X.Y.Z-rc.N. Manual runs pick the package explicitly and a tag of the other family is refused. Releases refuse to overwrite an existing NuGet.org version, pack with the source commit, push only the selected nupkg and upload it as an artifact. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README lists the Share and Business packages with their tag families. Docs/Business/Integration.md covers requirements, the consent-gated initialization recipe, the bounded and deterministic initialization, threading and call order, result codes, the configuration and event reference, the automatic purchase double counting warning, Android permissions, R8 and Data Safety, the differences from the iOS package and coexistence with the Share package. Docs/Release.md documents independent releases, and AGENTS.md, CONTRIBUTING.md and the PR template gain the Business rules, validation commands and the private-terms scan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
Kapusch.TikTok.Business.Android, a .NET Android package for the TikTok Business SDK (App Events) 1.7.1, independent of the existingKapusch.TikTok.AndroidShare package. Replaces #4 with a clean history: no commit contains any encoded private pattern.Kapusch.TikTok.Business.iOS(TikTokApisForiOSComponents PR feat(business): add Kapusch.TikTok.Business.Android (TikTok Business SDK 1.7.1) #4): same types, members, config record (AppId,TikTokAppIds,AccessTokenand the same opt-outs),TikTokBusinessInitResult(Status, int ErrorCode, ErrorMessage)with the shared1001/1002codes, and the same semantics. A deferred start returnsInitializedTrackingDisabledwithErrorCode0. Calls returnfalsebefore initialization. Calls run synchronously in call order. Platform gaps are documented inDocs/Business/Integration.md("Differences from the iOS package").initializeSdkcall after the first, and its async init step swallows Throwables without calling back. The facade enters the SDK only once per process and answers later attempts withInitIncompleteErrorCode(1104). A managed 30 s timer that does not depend on the main looper reportsInitTimeoutErrorCode(1105). A late success still sets the initialized state.v*tags for Share (unchanged contract) andbusiness-v*tags for Business.scripts/verify-public.pyfollows the shared approach. Private terms come at run time fromKAPUSCH_PRIVATE_TERMS(CI secret) or.git/info/private-terms, and failures only say "private term #N".Review findings addressed
scripts/verify-public.py: replaced by the run-time private-terms scanner. Checkedgit log -p origin/master..HEADand all commit messages for plain, hex,\xescaped, base64 and URL-encoded forms of every configured term: none found.NONE < INFO < WARN < DEBUG, with errors logged atINFO).identify/logout.getAppEventLogger()returnsnulloutside SDK call stacks, so the SDK event queue cannot be used. The docs state the remaining Android ordering gap honestly.Validation
Native/Android/build.sh,dotnet pack,scripts/validate-business-package.sh(now also checks that the Kotlin and managed error codes match)scripts/validate-package.shpassed. Share sources are unchanged.python3 -I scripts/verify-public.pywith the local private-terms fileArgumentException;DisableAutoStartgivesInitializedTrackingDisabledwith code 0;StartTrackgivesStarted;true;SetTrackingEnabled(false), manual calls returnfalse;1102and no crash.KapuschTikTokAndroidIncludeBundledRuntimeDependencies=false. With the bundled graph it fails on duplicate AndroidX classes, as documented.🤖 Generated with Claude Code