App On Device


1) Install the debug APK on a device/emulator

From your android folder the APK is here:

app/build/outputs/apk/debug/app-debug.apk

PowerShell (device plugged in with USB debugging enabled or an emulator running):

# optional: list devices
adb devices

# install/replace
adb install -r .\app\build\outputs\apk\debug\app-debug.apk

Tip: on an emulator you can also just drag the APK onto the emulator window.

Launch the “Ashley Timer” app and check that the splash shows, then your web UI appears.

2) If the splash does NOT show

You already have:

<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
  <item name="android:background">@drawable/splash</item>
</style>

Quick checks:

  • Manifest theme (open android/app/src/main/AndroidManifest.xml) — make sure the launcher activity uses the splash theme:
<application ... android:theme="@style/AppTheme.NoActionBarLaunch">
    <activity android:name="com.getcapacitor.BridgeActivity"
              android:exported="true"
              android:theme="@style/AppTheme.NoActionBarLaunch">
        <intent-filter> ... </intent-filter>
    </activity>
</application>
  • Asset exists at:
android/app/src/main/res/drawable/splash.png
  • Rebuild/clean after changes:
cd android
.\gradlew clean
.\gradlew assembleDebug
adb install -r .\app\build\outputs\apk\debug\app-debug.apk

3) Adaptive launcher icon (quick path)

In Android Studio:

  • Right-click app (the module) → New → Image Asset.
  • Icon Type: Launcher Icons (Adaptive and Legacy).
  • Foreground Layer: your Ashley logo (SVG/PNG).
  • Background Layer: solid color or background image.
  • Finish → this writes mipmap-anydpi-v26/ic_launcher*.xml and PNGs in mipmap-*.

Make sure your manifest uses it (usually already set):

<application
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/ic_launcher_round"
    ... />

Rebuild and install again.

4) Typical warnings you saw

  • flatDir warnings are common in Capacitor projects using local plugin libs—safe to ignore.
  • “unchecked or unsafe operations” is just a javac note—fine for now.

5) Don’t forget when you change web files

Any time you change index.html, JS, CSS:

# from project root (where index.html lives)
npx cap copy
# (or) npx cap sync
# then rebuild in Android Studio OR:
cd android
.\gradlew assembleDebug
adb install -r .\app\build\outputs\apk\debug\app-debug.apk

If you want, next I can walk you through a quick signed AAB release path now that debug works.

You said:

walk me through a quick signed AAB release path now that debug works

ChatGPT said:

Thought for a secondThought for 7s

Awesome—debug builds are green. Here’s the fastest, no-nonsense path to a signed AAB you can upload to Google Play.

0) Prep once (if you already did this, skip)

Generate/upload keystore (PKCS12):

# Run inside: C:\Users\Heru Da Guru\projects\ashleytimer
# You already installed keytool via Android Studio JBR.
& "C:\Program Files\Android\Android Studio\jbr\bin\keytool.exe" -genkeypair -v `
  -keystore release.keystore `
  -storetype PKCS12 `
  -alias ashley_upload `
  -keyalg RSA -keysize 2048 -validity 10000

Move release.keystoreandroid\app\.

Add secrets to Gradle user props (recommended):
Edit C:\Users\Heru Da Guru\.gradle\gradle.properties and add:

MYAPP_UPLOAD_STORE_FILE=release.keystore
MYAPP_UPLOAD_KEY_ALIAS=ashley_upload
MYAPP_UPLOAD_STORE_PASSWORD=YOUR_STORE_PASSWORD
MYAPP_UPLOAD_KEY_PASSWORD=YOUR_KEY_PASSWORD

1) Wire signing in android/app/build.gradle

Open android/app/build.gradle and ensure these blocks exist:

android {
    defaultConfig {
        applicationId "com.studio1live.ashleytimer2" // your actual id
        // bump these for release when needed:
        versionCode 1
        versionName "1.0.0"
    }

    signingConfigs {
        release {
            storeFile file(MYAPP_UPLOAD_STORE_FILE)
            storePassword MYAPP_UPLOAD_STORE_PASSWORD
            keyAlias MYAPP_UPLOAD_KEY_ALIAS
            keyPassword MYAPP_UPLOAD_KEY_PASSWORD
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
            // Optional hardening (enable after you verify a working AAB)
            // minifyEnabled true
            // shrinkResources true
            // proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug {
            // keep default
        }
    }
}

At the very top of that same file (or anywhere before android { ... }) make sure these lines exist so Gradle can read your props:

def MYAPP_UPLOAD_STORE_FILE      = project.hasProperty('MYAPP_UPLOAD_STORE_FILE') ? project.property('MYAPP_UPLOAD_STORE_FILE') : null
def MYAPP_UPLOAD_KEY_ALIAS       = project.hasProperty('MYAPP_UPLOAD_KEY_ALIAS') ? project.property('MYAPP_UPLOAD_KEY_ALIAS') : null
def MYAPP_UPLOAD_STORE_PASSWORD  = project.hasProperty('MYAPP_UPLOAD_STORE_PASSWORD') ? project.property('MYAPP_UPLOAD_STORE_PASSWORD') : null
def MYAPP_UPLOAD_KEY_PASSWORD    = project.hasProperty('MYAPP_UPLOAD_KEY_PASSWORD') ? project.property('MYAPP_UPLOAD_KEY_PASSWORD') : null

Tip: If you ever prefer project-local props instead of user-global, you can put those four lines in android/gradle.properties too. Just don’t commit them.

2) Make sure latest web files are in Android

From your project root (where index.html is):

npx cap sync android

If it says platform already exists and you’re in the android subfolder, cd up one:

cd "C:\Users\Heru Da Guru\projects\ashleytimer"
npx cap sync android

3) Clean + build the release AAB

From the android folder:

cd "C:\Users\Heru Da Guru\projects\ashleytimer\android"
.\gradlew clean
.\gradlew bundleRelease

Output:
android\app\build\outputs\bundle\release\app-release.aab

4) Quick validations before upload

  • Version bump: Increase versionCode (integer) each release; versionName can be semantic.
  • Splash/Landing check: Run a release APK locally if you want to sanity check UI: .\gradlew assembleRelease Install app-release-unsigned.apk only for visual checks (or sign/align for device). The AAB is what Play needs.
  • No absolute URLs: In your web assets ensure paths are relative (e.g., vendor/three.min.js, style_twopane.css), not starting with /.
  • Performance: If you later enable minifyEnabled/shrinkResources, test the UI and three.js render after enabling.

5) Upload to Google Play (Internal testing first)

  1. Go to Google Play ConsoleCreate app (if not done).
  2. Set up app (privacy policy URL, category, content ratings).
  3. TestingInternal testingCreate new release → upload app-release.aab.
  4. Add testers (Gmail accounts), roll out to internal. Install via the Play testing link.
  5. When happy, promote to Closed or Production.

6) Common gotchas & fixes

  • “android platform not added yet” when running npx cap sync android
    You’re likely in the android folder. Run it from project root (where capacitor.config.* lives).
  • Signing errors (Keystore was tampered with): Double-check passwords in gradle.properties.
  • Blank screen on release only: If you enable minify, add: -keep class com.getcapacitor.** { *; } -keep class com.capacitorjs.plugins.** { *; } -keep class org.apache.cordova.** { *; } in app/proguard-rules.pro. Rebuild.
  • Splash not showing: Ensure res/drawable/splash.png exists and styles.xml uses Theme.SplashScreen with @drawable/splash.

7) One-liner build (after everything’s wired)

From android/:

.\gradlew clean bundleRelease && explorer ".\app\build\outputs\bundle\release"