Skip to content

Commit 3ed1370

Browse files
fix: critical bugs and performance improvements
- Fix retry off-by-one, race conditions, cookie injection - Add thread-safe operations with atomic types - Add input validation for all config classes - Configure lint for Cronet experimental APIs
1 parent f68f328 commit 3ed1370

25 files changed

+1497
-2
lines changed

.gitignore

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea
5+
.DS_Store
6+
/build
7+
/captures
8+
.externalNativeBuild
9+
.cxx
10+
local.properties
11+
*.apk
12+
*.ap_
13+
*.aab
14+
*.dex
15+
*.class
16+
bin/
17+
gen/
18+
out/
19+
release/
20+
21+
# Gradle files
22+
.gradle/
23+
build/
24+
25+
# Local configuration file (sdk path, etc)
26+
local.properties
27+
28+
# Log Files
29+
*.log
30+
31+
# Android Studio Navigation editor temp files
32+
.navigation/
33+
34+
# Android Studio captures folder
35+
captures/
36+
37+
# IntelliJ
38+
*.iml
39+
.idea/
40+
41+
# Keystore files
42+
*.jks
43+
*.keystore
44+
45+
# External native build folder generated in Android Studio 2.2 and later
46+
.externalNativeBuild
47+
.cxx/
48+
49+
# Version control
50+
vcs.xml
51+
52+
# lint
53+
lint/intermediates/
54+
lint/generated/
55+
lint/outputs/
56+
lint/tmp/
57+
lint-baseline.xml

README.md

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,127 @@
1-
# android-apifier
2-
Library to abstract API and HTTP calls on android, backed by Cronet and OkHTTP
1+
# Android Apifier
2+
3+
[![](https://jitpack.io/v/Androidacy/android-apifier.svg)](https://jitpack.io/#Androidacy/android-apifier)
4+
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5+
6+
HTTP and API networking library for Android with Cronet and OkHttp.
7+
8+
## Features
9+
10+
- **Cronet Integration**: Multi-provider Cronet support (GMS → Native → Java fallback)
11+
- **HTTP/3 & QUIC**: Modern protocol support for improved performance
12+
- **Configurable Retry**: Built-in exponential backoff and retry logic
13+
- **Progress Tracking**: Download/upload progress monitoring
14+
- **Secure Cookies**: Encrypted cookie storage with customizable backend
15+
- **Connection Optimization**: Mobile-optimized connection pooling and timeouts
16+
- **DSL Configuration**: Kotlin DSL for clean, type-safe configuration
17+
18+
## Installation
19+
20+
Add JitPack repository:
21+
22+
```gradle
23+
repositories {
24+
maven { url 'https://jitpack.io' }
25+
}
26+
```
27+
28+
Add dependency:
29+
30+
```gradle
31+
dependencies {
32+
implementation 'com.github.Androidacy:android-apifier:1.0.0'
33+
}
34+
```
35+
36+
## Documentation
37+
38+
API documentation is available at [javadoc.jitpack.io](https://javadoc.jitpack.io/com/github/Androidacy/android-apifier/latest/javadoc/)
39+
40+
## Usage
41+
42+
```kotlin
43+
val client = ApifierClient(context) {
44+
cronet {
45+
enableQuic = true
46+
enableHttp2 = true
47+
quicHint("api.example.com")
48+
cacheDirectory = context.cacheDir.resolve("cronet")
49+
}
50+
51+
timeouts {
52+
connect = 5.seconds
53+
read = 60.seconds
54+
}
55+
56+
retry {
57+
maxAttempts = 3
58+
retryOn5xx = true
59+
}
60+
61+
cookieStorage(MyCookieStorage())
62+
header("User-Agent", "MyApp/1.0")
63+
dynamicHeader("Authorization") { getAuthToken() }
64+
}
65+
66+
client.get("https://api.example.com/data", object : Callback {
67+
override fun onResponse(call: Call, response: Response) {
68+
// Handle response
69+
}
70+
71+
override fun onFailure(call: Call, e: IOException) {
72+
// Handle error
73+
}
74+
})
75+
```
76+
77+
## Cookie Storage
78+
79+
Implement `CookieStorage` interface:
80+
81+
```kotlin
82+
class MyCookieStorage : CookieStorage {
83+
override fun getStringSet(key: String, defaultValue: Set<String>?) =
84+
encryptedPrefs.getStringSet(key, defaultValue)
85+
86+
override fun putStringSet(key: String, value: Set<String>) =
87+
encryptedPrefs.edit { putStringSet(key, value) }
88+
89+
override fun remove(key: String) =
90+
encryptedPrefs.edit { remove(key) }
91+
}
92+
```
93+
94+
## Progress Tracking
95+
96+
```kotlin
97+
client.download(url, object : ProgressListener {
98+
override fun update(bytesRead: Long, contentLength: Long, done: Boolean) {
99+
val progress = (bytesRead * 100 / contentLength).toInt()
100+
updateProgressBar(progress)
101+
}
102+
}, callback)
103+
```
104+
105+
## Requirements
106+
107+
- Android API 26+
108+
- Kotlin 2.2+
109+
- OkHttp 5.3+
110+
111+
## License
112+
113+
```
114+
Copyright 2025 Androidacy
115+
116+
Licensed under the Apache License, Version 2.0 (the "License");
117+
you may not use this file except in compliance with the License.
118+
You may obtain a copy of the License at
119+
120+
http://www.apache.org/licenses/LICENSE-2.0
121+
122+
Unless required by applicable law or agreed to in writing, software
123+
distributed under the License is distributed on an "AS IS" BASIS,
124+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125+
See the License for the specific language governing permissions and
126+
limitations under the License.
127+
```

apifier/build.gradle.kts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
plugins {
2+
id("com.android.library")
3+
id("org.jetbrains.kotlin.android")
4+
`maven-publish`
5+
}
6+
7+
android {
8+
namespace = "com.androidacy.apifier"
9+
compileSdk = 36
10+
11+
defaultConfig {
12+
minSdk = 26
13+
14+
consumerProguardFiles("consumer-rules.pro")
15+
}
16+
17+
buildTypes {
18+
release {
19+
isMinifyEnabled = false
20+
proguardFiles(
21+
getDefaultProguardFile("proguard-android-optimize.txt"),
22+
"proguard-rules.pro"
23+
)
24+
}
25+
}
26+
27+
compileOptions {
28+
sourceCompatibility = JavaVersion.VERSION_17
29+
targetCompatibility = JavaVersion.VERSION_17
30+
}
31+
32+
kotlin {
33+
compilerOptions {
34+
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
35+
}
36+
}
37+
38+
publishing {
39+
singleVariant("release") {
40+
withSourcesJar()
41+
withJavadocJar()
42+
}
43+
}
44+
}
45+
46+
dependencies {
47+
// OkHttp
48+
api("com.squareup.okhttp3:okhttp:5.3.0")
49+
50+
// Cronet
51+
api("com.google.android.gms:play-services-cronet:18.1.1")
52+
api("org.chromium.net:cronet-api:101.4951.41")
53+
implementation("org.chromium.net:cronet-embedded:113.5672.61")
54+
implementation("com.google.net.cronet:cronet-okhttp:0.1.0")
55+
56+
// Kotlin coroutines
57+
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
58+
api("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
59+
60+
// AndroidX
61+
implementation("androidx.core:core-ktx:1.17.0")
62+
}
63+
64+
afterEvaluate {
65+
publishing {
66+
publications {
67+
create<MavenPublication>("release") {
68+
from(components["release"])
69+
groupId = "com.github.Androidacy"
70+
artifactId = "android-apifier"
71+
version = "1.0.0"
72+
73+
pom {
74+
name.set("Android Apifier")
75+
description.set("HTTP and API networking library for Android with Cronet and OkHttp")
76+
url.set("https://github.com/Androidacy/android-apifier")
77+
licenses {
78+
license {
79+
name.set("The Apache License, Version 2.0")
80+
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
81+
}
82+
}
83+
}
84+
}
85+
}
86+
}
87+
}

apifier/consumer-rules.pro

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Apifier consumer ProGuard rules
2+
3+
# Keep Cronet classes
4+
-keep class org.chromium.net.** { *; }
5+
-keep class com.google.android.gms.net.** { *; }
6+
7+
# Keep OkHttp classes
8+
-dontwarn okhttp3.**
9+
-dontwarn okio.**
10+
-keep class okhttp3.** { *; }
11+
-keep interface okhttp3.** { *; }
12+
13+
# Keep public API
14+
-keep public class com.androidacy.apifier.** {
15+
public protected *;
16+
}

apifier/lint.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<lint>
3+
<issue id="UnsafeOptInUsageError">
4+
<option name="opt-in" value="org.chromium.net.QuicOptions.Experimental,org.chromium.net.DnsOptions.Experimental" />
5+
</issue>
6+
</lint>

apifier/proguard-rules.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Add project specific ProGuard rules here.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
<uses-permission android:name="android.permission.INTERNET" />
4+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
5+
</manifest>

0 commit comments

Comments
 (0)