Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
64a52e3
fix(auth): improve user identifier retrieval (#2314)
demolaf Apr 9, 2026
702cdf6
fix: ensure that when selecting phone or email, it routes straight to…
russellwheatley Apr 17, 2026
323f8b1
fix: use secondary app if it is passed into FirebaseAuthUI (#2313)
russellwheatley Apr 22, 2026
9980c9f
fix(auth): make AuthException messages customisable via AuthUIStringP…
demolaf May 15, 2026
625cdca
fix(auth): preserve linkDomain in email link ActionCodeSettings (#2321)
demolaf May 15, 2026
bda2bb2
fix(auth): log out before Facebook sign-in to clear stale cached toke…
demolaf May 18, 2026
f3b65a1
Fix typo in README (#2325)
nlln19 May 19, 2026
f6a48ab
fix(auth): emit AuthResult on sign-in success and fix MFA tooltip aut…
demolaf May 20, 2026
e62d534
fix(auth): expose slot parameters through FirebaseAuthScreen (#2328)
demolaf May 22, 2026
5171b51
feat(auth): add customMethodPickerTermsContent slot to FirebaseAuthSc…
demolaf Jun 5, 2026
4535c3d
feat(auth): add isCredentialLinkingEnabled for authenticated users (#…
demolaf Jun 8, 2026
b381d73
feat(auth): surface GIdP password policy violations with actionable e…
demolaf Jun 8, 2026
195e21f
fix(auth): allow SAML providers in AuthUIConfiguration (#2331)
demolaf Jun 8, 2026
8ab48c8
feat(auth): add reauthentication flow with automatic operation retry …
demolaf Jun 10, 2026
d942d9e
feat(auth): implement `legacyFetchSignInWithEmail` configuration opti…
russellwheatley Jun 16, 2026
7b2e5bd
fix(auth): replace hardcoded loading state strings with translatable …
demolaf Jun 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ google-services.json
crashlytics-build.properties
auth/src/main/res/values/com_crashlytics_export_strings.xml
*.log
.kotlin/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ Then you can depend on snapshot versions:
implementation 'com.firebaseui:firebase-ui-auth:$X.Y.Z-SNAPSHOT'
```

You can see which `SNAPSHOT` builds are avaiable here:
You can see which `SNAPSHOT` builds are available here:
https://oss.jfrog.org/webapp/#/artifacts/browse/tree/General/oss-snapshot-local/com/firebaseui

Snapshot builds come with absolutely no guarantees and we will close any issues asking to troubleshoot
Expand Down
259 changes: 259 additions & 0 deletions app/scripts/run-demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
#!/usr/bin/env bash

set -euo pipefail

APP_ID="com.firebaseui.android.demo"
MAIN_ACTIVITY="com.firebaseui.android.demo.MainActivity"
APK_RELATIVE_PATH="app/build/outputs/apk/debug/app-debug.apk"
EMULATOR_LOG="${TMPDIR:-/tmp}/firebaseui-android-emulator.log"
EMULATOR_PID=""
LAUNCHED_EMULATOR=0
CONNECTED_DEVICES=()
AVAILABLE_AVDS=()
KNOWN_DEVICE_SERIALS=()

usage() {
cat <<'EOF'
Usage: run-demo.sh [--help]

Builds, installs, and launches the FirebaseUI Android demo app.

The script lets you:
1. Use an already connected Android device or emulator.
2. Start an AVD selected from `emulator -list-avds`.
EOF
}

require_command() {
local command_name="$1"
if ! command -v "$command_name" >/dev/null 2>&1; then
echo "Missing required command: $command_name" >&2
exit 1
fi
}

collect_connected_devices() {
CONNECTED_DEVICES=()
while IFS= read -r serial; do
if [[ -n "$serial" ]]; then
CONNECTED_DEVICES+=("$serial")
fi
done < <(adb devices | awk 'NR > 1 && $2 == "device" { print $1 }')
}

collect_available_avds() {
AVAILABLE_AVDS=()
while IFS= read -r avd_name; do
if [[ -n "$avd_name" ]]; then
AVAILABLE_AVDS+=("$avd_name")
fi
done < <(emulator -list-avds 2>/dev/null)
}

prompt_for_choice() {
local prompt="$1"
shift
local options=("$@")
local selection
local index=1

echo "$prompt"
for option in "${options[@]}"; do
printf " %d) %s\n" "$index" "$option"
index=$((index + 1))
done

while true; do
printf "Select an option [1-%d]: " "${#options[@]}"
read -r selection

if [[ "$selection" =~ ^[0-9]+$ ]] && (( selection >= 1 && selection <= ${#options[@]} )); then
CHOICE_INDEX=$((selection - 1))
return 0
fi

echo "Please enter a number between 1 and ${#options[@]}."
done
}

is_known_device() {
local candidate="$1"
local known
local index

for (( index=0; index<${#KNOWN_DEVICE_SERIALS[@]}; index++ )); do
known="${KNOWN_DEVICE_SERIALS[$index]}"
if [[ "$known" == "$candidate" ]]; then
return 0
fi
done

return 1
}

cleanup_on_exit() {
local exit_code="$?"

if (( exit_code != 0 )) && (( LAUNCHED_EMULATOR == 1 )) && [[ -n "$EMULATOR_PID" ]]; then
echo "Stopping emulator started by this script..." >&2
kill "$EMULATOR_PID" 2>/dev/null || true
fi

exit "$exit_code"
}

wait_for_device_boot() {
local serial="$1"
local attempt
local boot_completed

adb -s "$serial" wait-for-device >/dev/null

echo "Waiting for $serial to finish booting..."
for (( attempt=1; attempt<=120; attempt++ )); do
boot_completed="$(adb -s "$serial" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')"
if [[ "$boot_completed" == "1" ]]; then
echo "$serial is ready."
return 0
fi
sleep 2
done

echo "Timed out waiting for $serial to boot." >&2
exit 1
}

start_selected_avd() {
local avd_name="$1"
local attempt
local serial
local index

collect_connected_devices
KNOWN_DEVICE_SERIALS=()
for (( index=0; index<${#CONNECTED_DEVICES[@]}; index++ )); do
KNOWN_DEVICE_SERIALS+=("${CONNECTED_DEVICES[$index]}")
done

echo "Starting emulator '$avd_name'..."
echo "Emulator logs: $EMULATOR_LOG"
emulator -avd "$avd_name" >"$EMULATOR_LOG" 2>&1 &
EMULATOR_PID=$!
LAUNCHED_EMULATOR=1

for (( attempt=1; attempt<=120; attempt++ )); do
sleep 2
collect_connected_devices
for (( index=0; index<${#CONNECTED_DEVICES[@]}; index++ )); do
serial="${CONNECTED_DEVICES[$index]}"
case "$serial" in
emulator-*)
if ! is_known_device "$serial"; then
TARGET_SERIAL="$serial"
wait_for_device_boot "$TARGET_SERIAL"
return 0
fi
;;
esac
done
done

echo "Failed to detect the new emulator for AVD '$avd_name'." >&2
exit 1
}

choose_target_device() {
local option_labels=()
local option_types=()
local option_values=()
local serial
local avd_name
local index

collect_connected_devices
collect_available_avds

for (( index=0; index<${#CONNECTED_DEVICES[@]}; index++ )); do
serial="${CONNECTED_DEVICES[$index]}"
option_labels+=("Use connected device: $serial")
option_types+=("device")
option_values+=("$serial")
done

for (( index=0; index<${#AVAILABLE_AVDS[@]}; index++ )); do
avd_name="${AVAILABLE_AVDS[$index]}"
option_labels+=("Start emulator: $avd_name")
option_types+=("avd")
option_values+=("$avd_name")
done

if (( ${#option_labels[@]} == 0 )); then
cat >&2 <<'EOF'
No connected Android devices were found, and no AVDs are available.
Connect a device or create an emulator first, then rerun this script.
EOF
exit 1
fi

prompt_for_choice "Choose a target for the demo app:" "${option_labels[@]}"

case "${option_types[$CHOICE_INDEX]}" in
device)
TARGET_SERIAL="${option_values[$CHOICE_INDEX]}"
;;
avd)
start_selected_avd "${option_values[$CHOICE_INDEX]}"
;;
esac
}

main() {
local script_dir
local repo_root
local apk_path
local launch_output

if [[ "${1:-}" == "--help" ]]; then
usage
exit 0
fi

trap cleanup_on_exit EXIT

require_command adb
require_command emulator

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/../.." && pwd)"
apk_path="$repo_root/$APK_RELATIVE_PATH"

if [[ ! -x "$repo_root/gradlew" ]]; then
echo "gradlew not found or not executable at $repo_root/gradlew" >&2
exit 1
fi

choose_target_device

echo "Building debug APK..."
"$repo_root/gradlew" :app:assembleDebug

if [[ ! -f "$apk_path" ]]; then
echo "APK not found at $apk_path" >&2
exit 1
fi

echo "Installing app on $TARGET_SERIAL..."
adb -s "$TARGET_SERIAL" install -r "$apk_path"

echo "Launching demo app on $TARGET_SERIAL..."
launch_output="$(adb -s "$TARGET_SERIAL" shell am start -n "$APP_ID/$MAIN_ACTIVITY")"
echo "$launch_output"
if [[ "$launch_output" == *"Error:"* ]]; then
echo "Failed to launch the demo app." >&2
exit 1
fi

trap - EXIT
}

main "$@"
31 changes: 31 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,37 @@
android:label="Custom Slots &amp; Theming Demo"
android:exported="false"
android:theme="@style/Theme.FirebaseUIAndroid" />

<activity
android:name=".CredentialLinkingDemoActivity"
android:label="Credential Linking Demo"
android:exported="false"
android:theme="@style/Theme.FirebaseUIAndroid" />

<activity
android:name=".EmailAuthSlotDemoActivity"
android:label="Email Auth — Custom Slot"
android:exported="false"
android:theme="@style/Theme.FirebaseUIAndroid" />

<activity
android:name=".PhoneAuthSlotDemoActivity"
android:label="Phone Auth — Custom Slot"
android:exported="false"
android:theme="@style/Theme.FirebaseUIAndroid" />

<activity
android:name=".ShapeCustomizationDemoActivity"
android:label="Shape Customization"
android:exported="false"
android:theme="@style/Theme.FirebaseUIAndroid" />

<activity
android:name=".CustomMethodPickerDemoActivity"
android:label="Custom Method Picker Layout"
android:exported="false"
android:theme="@style/Theme.FirebaseUIAndroid" />

</application>

</manifest>
Loading
Loading