Skip to content

Commit 6a3d053

Browse files
committed
Add sqlite-android-inspection for App Inspection Database support
1 parent 0bbaa7a commit 6a3d053

25 files changed

Lines changed: 2773 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ jobs:
2323
java-version: "17"
2424
distribution: "adopt"
2525

26+
- name: Verify sqlite-android-inspection
27+
run: ./scripts/verify-sqlite-android-inspection.sh
28+
2629
- name: Run Android tests
2730
uses: reactivecircus/android-emulator-runner@v2
2831
with:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
/.idea/libraries
77
.DS_Store
88
/build
9+
sqlite-android-inspection/build/
910
/captures

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,34 @@ on a `SupportSQLiteOpenHelper.Configuration` and `SupportSQLiteOpenHelper.Callba
7474
This also allows you to use sqlite-android with libraries like Room by passing an instance
7575
of `RequerySQLiteOpenHelperFactory` to them.
7676

77+
### Android Studio Database Inspector (API 26+)
78+
79+
App Inspection’s Database Inspector expects AndroidX’s sqlite inspector and the official
80+
`androidx.inspection` runtime (including `libart_tooling.so`). Add the optional
81+
**`sqlite-android-inspection`** artifact **for debug builds only**:
82+
83+
```gradle
84+
// Root settings.gradle: androidx.dev snapshot (see gradle.properties in this repo for build id).
85+
dependencyResolutionManagement {
86+
repositories {
87+
// ... google(), mavenCentral(), etc.
88+
maven {
89+
url "https://androidx.dev/snapshots/builds/<BUILD_ID>/artifacts/repository"
90+
content { includeGroup("androidx.inspection") }
91+
}
92+
}
93+
}
94+
95+
dependencies {
96+
implementation "com.github.requery:sqlite-android:<version>"
97+
// JitPack multi-module artifact (see https://docs.jitpack.io/#building-a-multi-module-project)
98+
debugImplementation "com.github.requery.sqlite-android:sqlite-android-inspection:<version>"
99+
}
100+
```
101+
102+
When consuming the library from Maven, use the same snapshot repository so the transitive
103+
`androidx.inspection:inspection` dependency resolves. See `sqlite-android-inspection/VENDOR.txt`.
104+
77105

78106
CPU Architectures
79107
-----------------

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
plugins {
22
id "com.android.library" version "8.13.0" apply false
33
id "de.undercouch.download" version "5.6.0" apply false
4+
id "com.google.protobuf" version "0.9.4" apply false
45
}

gradle.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
1616
android.useAndroidX=true
1717
#
18+
# androidx.inspection snapshot (see https://androidx.dev/snapshots/builds)
19+
androidx.inspection.snapshot.buildId=15127136
20+
androidx.inspection.version=1.0.0-SNAPSHOT
21+
#
1822
GROUP=io.requery
1923
VERSION_NAME=3.50.4-SNAPSHOT
2024
#
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Verifies sqlite-android-inspection: assemble, debug classpath, AAR SPI/classes.
4+
# Usage (from repo root): ./scripts/verify-sqlite-android-inspection.sh
5+
# Exit non-zero on any failure.
6+
7+
set -euo pipefail
8+
9+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
10+
cd "$ROOT"
11+
12+
echo "==> sqlite-android-inspection verification (repo: $ROOT)"
13+
echo
14+
15+
echo "==> [1/5] Gradle assembleDebug"
16+
./gradlew :sqlite-android-inspection:assembleDebug --no-daemon -q
17+
18+
echo "==> [2/5] Gradle assembleRelease"
19+
./gradlew :sqlite-android-inspection:assembleRelease --no-daemon -q
20+
21+
echo "==> [3/5] debugCompileClasspath includes androidx.inspection:inspection"
22+
if ! ./gradlew :sqlite-android-inspection:dependencies --configuration debugCompileClasspath --no-daemon -q 2>/dev/null | grep -q 'androidx.inspection:inspection'; then
23+
echo "ERROR: androidx.inspection:inspection not found on debugCompileClasspath (check snapshot repo / androidx.inspection.snapshot.buildId)" >&2
24+
exit 1
25+
fi
26+
27+
AAR_DIR="$ROOT/sqlite-android-inspection/build/outputs/aar"
28+
AAR=""
29+
if [[ -d "$AAR_DIR" ]]; then
30+
AAR=$(ls -1 "$AAR_DIR"/*-debug.aar 2>/dev/null | head -1 || true)
31+
fi
32+
33+
if [[ -z "${AAR:-}" || ! -f "$AAR" ]]; then
34+
echo "ERROR: expected debug AAR under $AAR_DIR" >&2
35+
exit 1
36+
fi
37+
echo "==> [4/5] AAR: $AAR"
38+
39+
TMP="$(mktemp -d)"
40+
trap 'rm -rf "$TMP"' EXIT
41+
42+
unzip -q -o "$AAR" -d "$TMP"
43+
44+
JAR="$TMP/classes.jar"
45+
if [[ ! -f "$JAR" ]]; then
46+
echo "ERROR: classes.jar missing in AAR" >&2
47+
exit 1
48+
fi
49+
50+
SPI_REL="META-INF/services/androidx.inspection.InspectorFactory"
51+
if ! jar tf "$JAR" | grep -q "^${SPI_REL}\$"; then
52+
echo "ERROR: missing $SPI_REL in classes.jar" >&2
53+
exit 1
54+
fi
55+
SPI_CONTENT="$(unzip -p "$JAR" "$SPI_REL")"
56+
if ! grep -q 'androidx\.sqlite\.inspection\.SqliteInspectorFactory' <<<"$SPI_CONTENT"; then
57+
echo "ERROR: SPI factory line not found in $SPI_REL" >&2
58+
printf '%s\n' "$SPI_CONTENT" >&2
59+
exit 1
60+
fi
61+
echo " SPI OK: $(echo "$SPI_CONTENT" | tr -d '\n')"
62+
63+
for class in \
64+
'androidx/sqlite/inspection/SqliteInspector.class' \
65+
'androidx/sqlite/inspection/SqliteInspectorFactory.class'; do
66+
if ! jar tf "$JAR" | grep -q "^$class\$"; then
67+
echo "ERROR: missing $class in classes.jar" >&2
68+
exit 1
69+
fi
70+
echo " class OK: $class"
71+
done
72+
73+
echo
74+
echo "==> [5/5] All checks passed. E2E: :sqlite-android-inspection:connectedDebugAndroidTest (see VENDOR.txt)."

settings.gradle

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,19 @@ dependencyResolutionManagement {
1010
repositories {
1111
google()
1212
mavenCentral()
13+
def props = new Properties()
14+
file("${rootDir}/gradle.properties").withInputStream { props.load(it) }
15+
def buildId = props.getProperty("androidx.inspection.snapshot.buildId", "15127136")
16+
maven {
17+
url = uri("https://androidx.dev/snapshots/builds/${buildId}/artifacts/repository")
18+
content {
19+
includeGroup("androidx.inspection")
20+
}
21+
}
1322
}
1423
}
1524

1625
rootProject.name = 'requery-sqlite'
1726

1827
include ':sqlite-android'
28+
include ':sqlite-android-inspection'
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
androidx.sqlite.inspection fork for io.requery (OpenParams-free), plus proto and SPI
2+
(META-INF/services/androidx.inspection.InspectorFactory → SqliteInspectorFactory).
3+
4+
Runtime androidx.inspection.* and libart_tooling.so come from Maven artifact
5+
androidx.inspection:inspection (not vendored here). Snapshot repo and build id:
6+
gradle.properties (androidx.inspection.version, androidx.inspection.snapshot.buildId);
7+
settings.gradle adds https://androidx.dev/snapshots/builds/<BUILD_ID>/artifacts/repository
8+
9+
debugApi(inspection): transitive for debug consumers. releaseCompileOnly: release AAR does not bundle JVMTI.
10+
11+
App: debugImplementation(project(":sqlite-android-inspection")) or published coordinates.
12+
If the app resolves this module from Maven (not project()), add the same androidx.dev snapshot repo
13+
(or a mirror) so transitive androidx.inspection:inspection resolves.
14+
15+
Checks: ./scripts/verify-sqlite-android-inspection.sh
16+
E2E (device): ./gradlew :sqlite-android-inspection:connectedDebugAndroidTest (InspectionJvmtiRuntimeTest)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
plugins {
2+
id "com.android.library"
3+
id "com.google.protobuf"
4+
id "com.vanniktech.maven.publish" version "0.34.0"
5+
}
6+
7+
android {
8+
buildToolsVersion = "36.1.0"
9+
compileSdk {
10+
version = release(36)
11+
}
12+
namespace "androidx.sqlite.inspection"
13+
defaultConfig {
14+
minSdkVersion 26
15+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16+
consumerProguardFiles "consumer-rules.pro"
17+
}
18+
compileOptions {
19+
sourceCompatibility JavaVersion.VERSION_17
20+
targetCompatibility JavaVersion.VERSION_17
21+
}
22+
lint {
23+
abortOnError false
24+
}
25+
}
26+
27+
protobuf {
28+
protoc {
29+
artifact = "com.google.protobuf:protoc:3.25.3"
30+
}
31+
generateProtoTasks {
32+
all().each { task ->
33+
task.builtins {
34+
java {
35+
option "lite"
36+
}
37+
}
38+
}
39+
}
40+
}
41+
42+
dependencies {
43+
def inspVersion = findProperty("androidx.inspection.version") ?: "1.0.0-SNAPSHOT"
44+
debugApi("androidx.inspection:inspection:${inspVersion}")
45+
releaseCompileOnly("androidx.inspection:inspection:${inspVersion}")
46+
47+
compileOnly("androidx.annotation:annotation:1.8.1")
48+
api("org.jspecify:jspecify:1.0.0")
49+
api("com.google.protobuf:protobuf-javalite:3.25.3")
50+
api(project(":sqlite-android"))
51+
52+
androidTestImplementation("androidx.test:runner:1.7.0")
53+
androidTestImplementation("androidx.test.ext:junit:1.3.0")
54+
}
55+
56+
mavenPublishing {
57+
publishToMavenCentral(/* automaticRelease */ true)
58+
signAllPublications()
59+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# App Inspection / Database Inspector (vendored androidx sqlite-inspection + io.requery hooks)
2+
-keep class androidx.sqlite.inspection.** { *; }
3+
-keep class androidx.inspection.** { *; }
4+
-keepclassmembers class io.requery.android.database.sqlite.SQLiteDatabase {
5+
public static *** openDatabase(...);
6+
public *** rawQueryWithFactory(...);
7+
void endTransaction();
8+
}
9+
-keep class io.requery.android.database.sqlite.SQLiteClosable { *; }
10+
-keep class io.requery.android.database.sqlite.SQLiteCursor { *; }
11+
-keep class io.requery.android.database.sqlite.SQLiteStatement { *; }

0 commit comments

Comments
 (0)