-
-
Notifications
You must be signed in to change notification settings - Fork 458
feat(android-distribution): add httpclient for checking for build distribution updates #4734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
57a565d
to
3e93cc4
Compare
Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
c8125f3 | 397.65 ms | 485.14 ms | 87.49 ms |
ee747ae | 386.94 ms | 431.43 ms | 44.49 ms |
23d6b12 | 354.10 ms | 408.38 ms | 54.28 ms |
d217708 | 409.83 ms | 474.72 ms | 64.89 ms |
d217708 | 411.22 ms | 430.86 ms | 19.63 ms |
ee747ae | 400.46 ms | 423.61 ms | 23.15 ms |
17a0955 | 372.53 ms | 446.70 ms | 74.17 ms |
3d205d0 | 352.15 ms | 432.53 ms | 80.38 ms |
1df7eb6 | 397.04 ms | 429.64 ms | 32.60 ms |
b750b96 | 408.98 ms | 480.32 ms | 71.34 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
c8125f3 | 1.58 MiB | 2.10 MiB | 532.32 KiB |
ee747ae | 1.58 MiB | 2.10 MiB | 530.95 KiB |
23d6b12 | 1.58 MiB | 2.10 MiB | 532.31 KiB |
d217708 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
d217708 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
ee747ae | 1.58 MiB | 2.10 MiB | 530.95 KiB |
17a0955 | 1.58 MiB | 2.10 MiB | 533.20 KiB |
3d205d0 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
1df7eb6 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
b750b96 | 1.58 MiB | 2.10 MiB | 533.19 KiB |
Previous results on branch: no/implement-distribution-check-for-updates
Startup times
Revision | Plain | With Sentry | Diff |
---|---|---|---|
6666e36 | 374.88 ms | 444.90 ms | 70.02 ms |
7b367ae | 349.24 ms | 457.92 ms | 108.68 ms |
c85da5d | 417.36 ms | 489.36 ms | 72.00 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
6666e36 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
7b367ae | 1.58 MiB | 2.10 MiB | 533.39 KiB |
c85da5d | 1.58 MiB | 2.10 MiB | 532.97 KiB |
import javax.net.ssl.HttpsURLConnection | ||
|
||
/** HTTP client for making requests to Sentry's distribution API. */ | ||
internal class DistributionHttpClient(private val options: SentryOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had claude generate an HttpClient for me. It works. I'm just not sure if it is a good idea to develop another client.
The other alternative is to expand the existing HttpConnection
to support our use case OR shadow oktthp in to our library. Open to thoughts!
import org.junit.Ignore | ||
import org.junit.Test | ||
|
||
class DistributionHttpClientTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a test class I used to test the integration. In a future, SAGP will inject the authToken and other things so we won't need to specify this manually. I'll also integrate distribution in to the sample app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
...-android-distribution/src/main/java/io/sentry/android/distribution/DistributionHttpClient.kt
Outdated
Show resolved
Hide resolved
...-android-distribution/src/main/java/io/sentry/android/distribution/DistributionHttpClient.kt
Outdated
Show resolved
Hide resolved
...-android-distribution/src/main/java/io/sentry/android/distribution/DistributionHttpClient.kt
Outdated
Show resolved
Hide resolved
...ry-android-distribution/src/main/java/io/sentry/android/distribution/UpdateResponseParser.kt
Show resolved
Hide resolved
UpdateStatus.UpdateError(e.message ?: "Configuration error") | ||
} catch (e: Exception) { | ||
sentryOptions.logger.log(SentryLevel.ERROR, e, "Failed to check for updates") | ||
UpdateStatus.UpdateError("Network error: ${e.message}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be nice to be able to distinguish between 'not connected' and 'network error' in the return type if that is possible and easy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UnknownHostException
would mean there is possibly no network and SocketTimeoutException
could mean a bad network. I added those to distinguish here.
...android-distribution/src/main/java/io/sentry/android/distribution/DistributionIntegration.kt
Outdated
Show resolved
Hide resolved
...android-distribution/src/main/java/io/sentry/android/distribution/DistributionIntegration.kt
Outdated
Show resolved
Hide resolved
...-android-distribution/src/main/java/io/sentry/android/distribution/DistributionHttpClient.kt
Outdated
Show resolved
Hide resolved
…ality Implements the checkForUpdateBlocking method in DistributionIntegration to check for app updates via Sentry's distribution API. ## Why not reuse existing HttpConnection? The existing `HttpConnection` class is designed specifically for Sentry event transport and is not suitable for distribution API calls: - Hardcoded for POST requests (we need GET) - Expects Sentry envelopes with gzip encoding (we need simple JSON) - Only considers status 200 successful (REST APIs use 200-299 range) - Includes Sentry-specific rate limiting logic ## Changes - **DistributionHttpClient**: New HTTP client for distribution API requests - Supports GET requests with query parameters (main_binary_identifier, app_id, platform, version) - Uses SentryOptions.DistributionOptions for configuration (orgSlug, projectSlug, orgAuthToken) - Handles SSL configuration, timeouts, and proper error handling - **UpdateResponseParser**: JSON response parser for API responses - Parses API responses into UpdateStatus objects (UpToDate, NewRelease, UpdateError) - Handles various HTTP status codes with appropriate error messages - Validates required fields in update information - **DistributionIntegration**: Updated to use new classes - Automatically extracts app information (package name, version) from Android context - Clean separation of concerns with HTTP client and response parser - Comprehensive error handling and logging - **Tests**: Added unit test for DistributionHttpClient with real API integration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Remove unnecessary Claude-style comments from DistributionHttpClient - Replace manual URL building with Android Uri.Builder for safer parameter encoding - Add comprehensive tests for UpdateResponseParser with 11 test cases - Improve error handling to distinguish between network connection vs server issues - Add clarifying comments about which exceptions indicate network connectivity problems - Fix null value handling in JSON parsing to properly validate "null" strings - Remove unclear comment about package name usage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Replace custom fallback "sentry-android-distribution" with error throw when sentryClientName is null, following the pattern used throughout the codebase where sentryClientName is expected to always be set. Addresses PR review feedback about reusing consistent user agent. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Change "check connection speed" to "check network connection" to be more general and align with the goal of distinguishing network connectivity issues. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
6465b7d
to
061d6b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm % some small comments
...android-distribution/src/main/java/io/sentry/android/distribution/DistributionIntegration.kt
Outdated
Show resolved
Hide resolved
...ry-android-distribution/src/main/java/io/sentry/android/distribution/UpdateResponseParser.kt
Show resolved
Hide resolved
...ry-android-distribution/src/main/java/io/sentry/android/distribution/UpdateResponseParser.kt
Show resolved
Hide resolved
...ry-android-distribution/src/main/java/io/sentry/android/distribution/UpdateResponseParser.kt
Show resolved
Hide resolved
...ry-android-distribution/src/main/java/io/sentry/android/distribution/UpdateResponseParser.kt
Outdated
Show resolved
Hide resolved
...android-distribution/src/main/java/io/sentry/android/distribution/DistributionIntegration.kt
Outdated
Show resolved
Hide resolved
- Add UpdateStatus.NoNetwork subclass for network-specific errors - Update DistributionIntegration to use NoNetwork for UnknownHostException and SocketTimeoutException - Improve UpdateResponseParser error messages to specify which required fields are missing - Add comprehensive tests for specific missing field error messages 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Update UpdateCheckParams constructor to use separate versionCode and versionName parameters - Replace Android Uri with string building for better compatibility - Remove unused Android Uri import - Update URL construction to use build_number and build_version query parameters This fixes the CI compilation errors where the old constructor expected a single 'version' parameter. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Extract versionCode properly from PackageInfo using longVersionCode for API 28+ - Fall back to deprecated versionCode for older Android versions - Add missing mainBinaryIdentifier parameter to UpdateCheckParams constructor - Use proper API-level checks to avoid deprecation warnings This resolves the compilation error where 'version' was undefined. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
append("&platform=${params.platform}") | ||
append("&build_number=${params.versionCode}") | ||
append("&build_version=${params.versionName}") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: URL Encoding and Null Checks Missing
The checkForUpdates
method builds the URL query string without encoding parameters like mainBinaryIdentifier
, appId
, platform
, versionCode
, and versionName
. This can result in malformed URLs and failed requests if these values contain special characters. Separately, orgSlug
, projectSlug
, authToken
, and baseUrl
are used without null checks, potentially causing NullPointerException
s.
packageInfo.longVersionCode.toInt() | ||
} else { | ||
@Suppress("DEPRECATION") packageInfo.versionCode | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Android API 28+ Version Code Truncation Bug
On Android API 28+, packageInfo.longVersionCode
is converted to an Int
. This can silently truncate version codes exceeding Int.MAX_VALUE
, leading to incorrect version information being sent to the distribution API and potentially faulty update checks.
Summary
Implements the
checkForUpdateBlocking
method inDistributionIntegration
to check for app updates via Sentry's distribution API.Why not reuse existing HttpConnection?
The existing
HttpConnection
class is designed specifically for Sentry event transport and is not suitable for distribution API calls:Changes
DistributionHttpClient: New HTTP client for distribution API requests
UpdateResponseParser: JSON response parser for API responses
#skip-changelog
🤖 Generated with Claude Code