# Technical documentation — ear_android_app

Evidence date: 2026-10-16.

Source: `git@bitbucket.org:overdrive/ear_android_app.git`, `master` at `5c15b03` (2023-03-10, Jaco Brits `jaco@netstart.co.za`, "eAr app POC"). Parent commit `d82966c` (same day, Jaco Brits `jaco@overdrive.co.za`) added only `.gitignore`.

No README, architecture decision, pipeline, or environment sample is in the repository. Facts below are from the files at that revision.

## Summary

A one-module Android application. `MainActivity` shows a `WebView` and loads `https://www.ear-academy.com/home/login`. JavaScript and DOM storage are enabled after that call. The manifest does not declare `android.permission.INTERNET`.

## Language and runtime

| Item | Value | Evidence |
|---|---|---|
| Language | Java | `MainActivity.java`. No Kotlin source, no `kotlin` plugin |
| Java bytecode target | 1.8 | `app/build.gradle` `compileOptions` |
| IDE language level | JDK_11 | `.idea/misc.xml` |
| IDE bytecode target | 11 | `.idea/compiler.xml` `bytecodeTargetLevel` |
| IDE JDK name | `Embedded JDK` | `.idea/misc.xml`, `.idea/gradle.xml` `gradleJvm` |
| UI toolkit | Android Views, AppCompat, one `WebView` | Layout and activity. Not Compose |
| AndroidX | `android.useAndroidX=true` | `gradle.properties` |
| R class namespacing | `android.nonTransitiveRClass=true` | `gradle.properties` |

The activity uses only Java 8-level syntax. Gradle `compileOptions` remain 1.8. The IDE files separately record language level JDK_11 and bytecode target 11. Which target a historical IDE build used is **Unknown**.

## SDK and build

| Item | Value | Evidence |
|---|---|---|
| Android Gradle Plugin | 7.4.2 | Root `build.gradle`. `com.android.application` is applied by `app/build.gradle`. `com.android.library` is declared and not applied |
| Gradle wrapper | 7.5 | `gradle/wrapper/gradle-wrapper.properties` (`gradle-7.5-bin.zip`, dated in the file comment Fri Mar 10 21:52:10 CAT 2023) |
| IDE `gradleHome` | `$PROJECT_DIR$/../../../../Gradle/gradle-6.9.3` | `.idea/gradle.xml` |
| IDE distribution type | `DEFAULT_WRAPPED` | `.idea/gradle.xml` |
| `compileSdk` | 33 | `app/build.gradle` |
| `minSdk` | 21 | `app/build.gradle` |
| `targetSdk` | 33 | `app/build.gradle` |
| `namespace` / `applicationId` | `com.example.ear` | `app/build.gradle` |
| `versionCode` / `versionName` | 1 / `1.0` | `app/build.gradle` |
| Instrumentation runner | `androidx.test.runner.AndroidJUnitRunner` | `app/build.gradle` |
| JVM args for Gradle | `-Xmx2048m -Dfile.encoding=UTF-8` | `gradle.properties` |
| Repositories | `google()`, `mavenCentral()`, `gradlePluginPortal()` for plugins | `settings.gradle` |
| Project repos inside modules | Forbidden (`FAIL_ON_PROJECT_REPOS`) | `settings.gradle` |
| Root project name | `eAr` | `settings.gradle` |
| Modules | `:app` only | `settings.gradle` |

`distributionType` `DEFAULT_WRAPPED` means Android Studio is set to use the wrapper (Gradle 7.5). `gradleHome` still points at a Gradle 6.9.3 directory four levels above the project. That path is a machine-local hint. It is not a hermetic input. **Unknown** which Gradle actually built any APK on the author's machine.

`local.properties` is gitignored. The Android SDK path is **Unknown**.

Wrapper scripts `gradlew` and `gradlew.bat` are present, plus `gradle/wrapper/gradle-wrapper.jar`.

Release build type:

- `minifyEnabled false`
- ProGuard files: default `proguard-android-optimize.txt` plus `app/proguard-rules.pro`
- `proguard-rules.pro` is the Android Studio comment template. No keep rule is active
- No `debug` block, no `signingConfigs`, no `flavorDimensions`

This review did not run Gradle. Whether the project still resolves on current JDKs and SDK 33 platforms is **Unknown / Requires Confirmation**.

## Application structure

```text
ear_android_app/
  build.gradle
  settings.gradle
  gradle.properties
  gradlew
  gradlew.bat
  gradle/wrapper/
  .idea/                  compiler.xml, gradle.xml, misc.xml, .gitignore
  app/
    build.gradle
    proguard-rules.pro
    src/main/
      AndroidManifest.xml
      java/com/example/ear/MainActivity.java
      res/layout/activity_main.xml
      res/values/           strings.xml, colors.xml, themes.xml
      res/values-night/themes.xml
      res/drawable/ic_launcher_background.xml
      res/drawable-v24/ic_launcher_foreground.xml
      res/mipmap-anydpi-v26/   ic_launcher.xml, ic_launcher_round.xml
      res/mipmap-anydpi-v33/   ic_launcher.xml
      res/mipmap-{m,h,xh,xxh,xxxh}dpi/   ic_launcher.webp, ic_launcher_round.webp
      res/xml/backup_rules.xml
      res/xml/data_extraction_rules.xml
    src/test/java/com/example/ear/ExampleUnitTest.java
    src/androidTest/java/com/example/ear/ExampleInstrumentedTest.java
```

No `res/menu`, navigation graph, `assets/`, `jni/`, or product `res/xml/network_security_config.xml`.

## Manifest

`app/src/main/AndroidManifest.xml`:

- `<application>`: `allowBackup=true`, `dataExtractionRules=@xml/data_extraction_rules`, `fullBackupContent=@xml/backup_rules`, icon `@mipmap/ic_launcher`, label `@string/app_name`, `supportsRtl=true`, theme `@style/Theme.EAr`, `tools:targetApi=31`.
- One activity: `.MainActivity`, `exported=true`, intent filter `MAIN` + `LAUNCHER`.
- No `uses-permission`, `uses-feature`, `queries`, service, receiver, or provider.
- No `android:networkSecurityConfig`, `usesCleartextTraffic`, `hardwareAccelerated` override, or `configChanges`.

`INTERNET` is a normal (install-time) permission. It is not granted unless declared. The WebView's remote `loadUrl` depends on it. Provenance: **Implemented** omission. Device confirmation was not part of this review.

Cleartext is not required by the URL, which is `https`. No cleartext flag is set.

## Activity behaviour

`MainActivity` extends `androidx.appcompat.app.AppCompatActivity`.

Field: `private WebView mywebView`.

`onCreate` order:

1. `super.onCreate`
2. `setContentView(R.layout.activity_main)`
3. Cast `findViewById(R.id.webview)` to `WebView`
4. `setWebViewClient(new WebViewClient())`
5. `loadUrl("https://www.ear-academy.com/home/login")`
6. `getSettings().setJavaScriptEnabled(true)`
7. `getSettings().setDomStorageEnabled(true)`

Not called: `setWebChromeClient`, `addJavascriptInterface`, `CookieManager`, `WebView.goBack`, `saveState` / `restoreState`, `setDownloadListener`, any `WebSettings` method other than the two above.

Layout `activity_main.xml`: `RelativeLayout` match_parent, one `WebView` match_parent, id `webview`. The `app` namespace is declared and unused. `tools:context` is `.MainActivity`.

Theme `Theme.EAr` parents `Theme.MaterialComponents.DayNight.DarkActionBar` in both `values` and `values-night`. Colours are the wizard palette (`purple_500` `#FF6200EE`, `teal_200` `#FF03DAC5`, and the matching variants in `colors.xml`). The layout does not include a `Toolbar`. The dark action bar comes from the theme parent. Whether that bar is visible above the WebView was not run on a device. Provenance: **Inferred** from the theme parent. **Requires Confirmation** if the bar covering or pushing the WebView matters.

Launcher vectors: `ic_launcher_foreground.xml` uses the Android Studio robot path (viewport 108, path starting `M31,63.928...`). `ic_launcher_background.xml` is the matching template background. API 33 `ic_launcher.xml` adds a monochrome layer pointing at the same foreground. Density `webp` files are committed for mdpi through xxxhdpi, square and round.

## Dependencies

From `app/build.gradle`:

| Configuration | Coordinate |
|---|---|
| implementation | `androidx.appcompat:appcompat:1.6.1` |
| implementation | `com.google.android.material:material:1.8.0` |
| implementation | `androidx.constraintlayout:constraintlayout:2.1.4` |
| testImplementation | `junit:junit:4.13.2` |
| androidTestImplementation | `androidx.test.ext:junit:1.1.5` |
| androidTestImplementation | `androidx.test.espresso:espresso-core:3.5.1` |

Appcompat is used (`AppCompatActivity`). Material is used as the theme parent. Constraintlayout is not referenced by the layout. Espresso is not referenced by the instrumented test. No dependency lock file or `libs.versions.toml`.

## Data and storage

No database, Room, DataStore, SharedPreferences, or file API appears in `MainActivity`.

WebView may still write its own cookie and cache files under the app's data directory. The activity never configures that store. `allowBackup` is true and the backup XML files do not exclude WebView directories. What Android backup would copy is **Unknown / Requires Confirmation** and depends on the OS version (`backup_rules.xml` itself notes that the full-backup file is ignored before API 31).

## Networking and security

- One outbound URL, hardcoded HTTPS.
- No certificate pinning, no custom trust manager, no `network_security_config`.
- JavaScript enabled. No JavaScript interface, so the page cannot call into an annotated Java object through `addJavascriptInterface`. The page can still use ordinary web APIs the system WebView allows.
- DOM storage enabled.
- No token, API key, or password in the source tree. (Checked the Java, XML, Gradle, and IDE files. No `.env`.)
- `.gitignore` ignores `local.properties`, `.gradle`, `/build`, captures, and selected `.idea` caches. It does not ignore the committed `.idea/gradle.xml`, which contains a local `gradleHome` path. That path is not a secret. It is machine-specific.
- Release is not minified and no signing config is stored. A release APK's certificate is **Unknown**.
- `exported=true` is required for a launcher activity. No other component is exported because no other component exists.

## Integrations

| System | When | Notes |
|---|---|---|
| `www.ear-academy.com` | Process start of the activity | WebView load of `/home/login`. No app-level auth header |
| Maven repositories | Build | `google()`, `mavenCentral()` |

No Firebase, Maps, Retrofit, OkHttp, Gson, or analytics dependency is declared. The WebView uses the device's system or Android System WebView. The app does not pin a WebView version.

## Background work

No `Service`, `WorkManager`, `JobScheduler`, `BroadcastReceiver`, `AlarmManager`, or foreground service.

## Environments and deployment

No product flavors, no `src/debug` source set, no `buildConfigField`, no CI file, no Dockerfile, no Fastlane, no Play `listings/` metadata.

`versionName` `1.0` is the only version string.

Distribution status (internal APK, Play internal track, or never installed) is **Unknown / Requires Confirmation**.

## Testing

| Test | Type | Assertion | Covers the WebView? |
|---|---|---|---|
| `ExampleUnitTest` | JVM unit | `4 == 2 + 2` | No |
| `ExampleInstrumentedTest` | Device, AndroidJUnit4 | package name `com.example.ear` | No |

No test plan file, no CI job, no coverage configuration. This review did not execute either test.

## Sonar and the scan-host listing

The onboarding request listed `sonar-project.properties` and `sonarqube_scan.bat` beside `settings.gradle`. At git revision `5c15b03` those files are absent, and `git log` has no commit that adds or deletes them. There is no `bitbucket-pipelines.yml`.

Provenance: **Unknown**. Treat them as possible untracked files on the scan host of 2026-09-28 until someone confirms.

## IDE files that affect builds

Committed under `.idea/`:

| File | What it records |
|---|---|
| `misc.xml` | Android project type, JDK_11, Embedded JDK, output `build/classes` |
| `gradle.xml` | Gradle test runner, wrapped distribution, external project path `$PROJECT_DIR$`, `gradleHome` Gradle 6.9.3, modules `$PROJECT_DIR$` and `$PROJECT_DIR$/app` |
| `compiler.xml` | `bytecodeTargetLevel` 11 |
| `.gitignore` | Ignores shelf and workspace XML inside `.idea` |

`compiler.xml` sets the IDE bytecode target to 11. It does not add annotation processors or a custom compiler argument. Gradle still compiles the module as Java 1.8.

## Operability gaps (from the source, not a pentest)

1. Missing `INTERNET` permission against a remote `loadUrl`.
2. `loadUrl` before the two `WebSettings` calls.
3. No error callback and no offline UI.
4. No WebView state restore.
5. No host allow-list while JavaScript is enabled.
6. Backup allowed with sample (empty) rules.
7. Application id still on `com.example`.
8. No reproducible signing or CI.
9. Wrapper Gradle 7.5 versus an IDE `gradleHome` of 6.9.3.

## Related Silicon Ark sets

`silicon_ark/ear_lambdas/` documents Lambdas that HTTP GET `https://www.ear-academy.com/admin/...`. Shared evidence is the hostname only. This repository does not import, call, or configure those functions.
