Repository navigation
feat(mobile): android app shell - #1068
Open
SeanDuggan wants to merge 15 commits into
Open
SeanDuggan wants to merge 15 commits into
SeanDuggan wants to merge 15 commits into
Conversation
Adds the Gradle project, manifest, resources, launch/login/main activities, navigation, preferences, authentication, key validation and progress tracking utilities, and the home, progress, scoreboard and ADB reference screens. Lesson and challenge screens referenced by the navigation graph are added in the following PRs, so those destinations are not usable until then. Part of the split of OWASP#894 (mobile app).
Disable cleartext traffic app-wide via a network security config and reject non-https server URLs at login, registration and key validation. Debug builds additionally trust user-installed CAs for local development.
The shell now builds with an empty KeyValidator.Module enum and empty nav, menu and module-info registries. Each lesson/challenge category PR registers its own entries. Removes the myapp://open deep link and the KeyValidator unit test, which return with the first category.
Removes lesson/challenge strings and the Insufficient Cryptography ADB reference card. These return with their own category PRs.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical issues can break builds, crash sign-in on supported Android versions, and expose session cookies through server-address changes, backups, and insufficient release certificate restrictions on older devices.
8 open issues
Exclude authentication preferences from device backups · New Use API-compatible color lookup on Android 21 and 22 · New Invalidate sessions when the server address changes · New Enforce release CA restrictions on Android 21–23 · New Remove machine-specific JAVA_HOME Gradle override · New Use the correct application ID in package discovery commands · New Refresh drawer navigation after Home authentication changes · New Refresh scoreboard after successful reauthentication · New
What changed in this PR
Adds the unified Mobile Shepherd Android app shell, establishing the shared interface and server integration for later lesson and challenge PRs split from #894. This PR does not add training modules or change the server platform.
Changes:
- Introduces the Gradle Android project, app configuration, and HTTPS network policy.
- Adds landing, authentication, Home, Preferences, ADB Reference, and Scoreboard interfaces.
- Provides navigation, progress tracking, badges, and key-management infrastructure with empty module registries.
| File | Description |
|---|---|
mobile/settings.gradle |
Defines repositories and the app module. |
mobile/scripts/calculate_key_hashes.py |
Generates training-key hashes. |
mobile/gradlew.bat |
Adds the Windows Gradle launcher. |
mobile/gradlew |
Adds the POSIX Gradle launcher. |
mobile/gradle/wrapper/gradle-wrapper.properties |
Pins the Gradle distribution. |
mobile/gradle.properties |
Configures Gradle and Android resources. |
mobile/build.gradle |
Declares Android build plugins. |
mobile/app/src/main/res/xml/preferences.xml |
Defines application preferences. |
mobile/app/src/main/res/xml/network_security_config.xml |
Configures HTTPS and debug CA trust. |
mobile/app/src/main/res/xml/file_paths.xml |
Defines FileProvider sharing paths. |
mobile/app/src/main/res/xml/data_extraction_rules.xml |
Adds modern backup configuration. |
mobile/app/src/main/res/xml/backup_rules.xml |
Adds legacy backup configuration. |
mobile/app/src/main/res/values/themes.xml |
Defines the Material application theme. |
mobile/app/src/main/res/values/strings.xml |
Supplies interface text and commands. |
mobile/app/src/main/res/values/dimens.xml |
Defines default spacing. |
mobile/app/src/main/res/values/colors.xml |
Defines the light-mode palette. |
mobile/app/src/main/res/values-w600dp/dimens.xml |
Adjusts spacing for wider screens. |
mobile/app/src/main/res/values-w1240dp/dimens.xml |
Adjusts spacing for large screens. |
mobile/app/src/main/res/values-night/themes.xml |
Defines dark-mode theme overrides. |
mobile/app/src/main/res/values-night/colors.xml |
Defines the dark-mode palette. |
mobile/app/src/main/res/values-land/dimens.xml |
Adjusts landscape spacing. |
mobile/app/src/main/res/navigation/mobile_navigation.xml |
Declares shell navigation destinations. |
mobile/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml |
Defines an adaptive launcher icon. |
mobile/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml |
Defines a round adaptive icon. |
mobile/app/src/main/res/menu/main.xml |
Adds toolbar menu actions. |
mobile/app/src/main/res/menu/activity_main_drawer.xml |
Defines the Home menu entry. |
mobile/app/src/main/res/layout/nav_item_layout.xml |
Defines expandable navigation rows. |
mobile/app/src/main/res/layout/nav_header_main.xml |
Adds branding and authentication controls. |
mobile/app/src/main/res/layout/nav_drawer_layout.xml |
Arranges the drawer header and list. |
mobile/app/src/main/res/layout/item_user_result.xml |
Defines a user-result card. |
mobile/app/src/main/res/layout/item_scoreboard_entry.xml |
Displays rankings, medals, and scores. |
mobile/app/src/main/res/layout/item_module_progress.xml |
Displays module completion details. |
mobile/app/src/main/res/layout/fragment_scoreboard.xml |
Defines scoreboard loading and result states. |
mobile/app/src/main/res/layout/fragment_progress.xml |
Defines progress totals and module lists. |
mobile/app/src/main/res/layout/fragment_preferences.xml |
Adds a placeholder preferences layout. |
mobile/app/src/main/res/layout/fragment_home.xml |
Defines welcome and authentication cards. |
mobile/app/src/main/res/layout/dialog_lesson_info.xml |
Provides a reusable module-information layout. |
mobile/app/src/main/res/layout/dialog_auth.xml |
Defines the authentication dialog form. |
mobile/app/src/main/res/layout/content_main.xml |
Hosts navigation content. |
mobile/app/src/main/res/layout/app_bar_main.xml |
Arranges the toolbar and help buttons. |
mobile/app/src/main/res/layout/activity_main.xml |
Combines app content and drawer. |
mobile/app/src/main/res/layout/activity_login.xml |
Defines sign-in and registration forms. |
mobile/app/src/main/res/layout/activity_landing.xml |
Defines the introduction and warning screen. |
mobile/app/src/main/res/drawable/side_nav_bar.xml |
Adds a navigation gradient. |
mobile/app/src/main/res/drawable/shepherd_background.xml |
Composes the branded screen background. |
mobile/app/src/main/res/drawable/shape.xml |
Adds a bordered rectangular background. |
mobile/app/src/main/res/drawable/nav_header_background.xml |
Composes the drawer-header background. |
mobile/app/src/main/res/drawable/ic_status_incomplete.xml |
Adds an incomplete-status icon. |
mobile/app/src/main/res/drawable/ic_status_complete.xml |
Adds a completion icon. |
mobile/app/src/main/res/drawable/ic_menu_web.xml |
Adds a web navigation icon. |
mobile/app/src/main/res/drawable/ic_menu_warning.xml |
Adds a warning icon. |
mobile/app/src/main/res/drawable/ic_menu_slideshow.xml |
Adds a slideshow icon. |
mobile/app/src/main/res/drawable/ic_menu_shield.xml |
Adds a shield icon. |
mobile/app/src/main/res/drawable/ic_menu_settings.xml |
Adds a settings icon. |
mobile/app/src/main/res/drawable/ic_menu_network.xml |
Adds a network icon. |
mobile/app/src/main/res/drawable/ic_menu_lock.xml |
Adds a lock icon. |
mobile/app/src/main/res/drawable/ic_menu_link.xml |
Adds a link icon. |
mobile/app/src/main/res/drawable/ic_menu_key.xml |
Adds a key icon. |
mobile/app/src/main/res/drawable/ic_menu_home.xml |
Adds the Home icon. |
mobile/app/src/main/res/drawable/ic_menu_gallery.xml |
Adds a gallery icon. |
mobile/app/src/main/res/drawable/ic_menu_database.xml |
Adds a database icon. |
mobile/app/src/main/res/drawable/ic_menu_code.xml |
Adds a code icon. |
mobile/app/src/main/res/drawable/ic_menu_camera.xml |
Adds a navigation icon resource. |
mobile/app/src/main/res/drawable/ic_menu_alert.xml |
Adds an alert icon. |
mobile/app/src/main/res/drawable/ic_launcher_background.xml |
Adds launcher background artwork. |
mobile/app/src/main/res/drawable/ic_expand_more.xml |
Adds the drawer expansion indicator. |
mobile/app/src/main/res/drawable/grassbackground.xml |
Adds a tiled branded background. |
mobile/app/src/main/res/drawable/card_ripple.xml |
Defines card touch feedback. |
mobile/app/src/main/res/drawable/button_scale_animation.xml |
Defines button scaling states. |
mobile/app/src/main/res/drawable/bg_scoreboard_row.xml |
Styles scoreboard rows. |
mobile/app/src/main/res/drawable/bg_medal_silver.xml |
Styles silver medal indicators. |
mobile/app/src/main/res/drawable/bg_medal_gold.xml |
Styles gold medal indicators. |
mobile/app/src/main/res/drawable/bg_medal_bronze.xml |
Styles bronze medal indicators. |
mobile/app/src/main/res/drawable/animation.xml |
Defines a frame animation. |
mobile/app/src/main/res/drawable-v24/ic_menu.xml |
Adds an API-qualified menu icon. |
mobile/app/src/main/res/drawable-v24/ic_launcher_foreground.xml |
Adds launcher foreground artwork. |
mobile/app/src/main/res/drawable-v24/ic_launcher_background.xml |
Adds API-qualified launcher artwork. |
mobile/app/src/main/res/drawable-v24/animation.xml |
Adds an API-qualified frame animation. |
mobile/app/src/main/res/anim/slide_out_right.xml |
Defines a rightward exit transition. |
mobile/app/src/main/res/anim/slide_out_left.xml |
Defines a leftward exit transition. |
mobile/app/src/main/res/anim/slide_in_right.xml |
Defines entry from the right. |
mobile/app/src/main/res/anim/slide_in_left.xml |
Defines entry from the left. |
mobile/app/src/main/res/anim/scale_up.xml |
Defines a scale-up entrance. |
mobile/app/src/main/res/anim/scale_down.xml |
Defines a scale-down exit. |
mobile/app/src/main/res/anim/fade_out.xml |
Defines a fade-out transition. |
mobile/app/src/main/res/anim/fade_in.xml |
Defines a fade-in transition. |
mobile/app/src/main/java/org/owasp/mobileshepherd/utils/ProgressTracker.java |
Persists completion status and statistics. |
mobile/app/src/main/java/org/owasp/mobileshepherd/utils/ModuleInfoHelper.java |
Provides module metadata dialogs. |
mobile/app/src/main/java/org/owasp/mobileshepherd/utils/KeyValidator.java |
Provides server and offline key validation. |
mobile/app/src/main/java/org/owasp/mobileshepherd/utils/KeyProvider.java |
Fetches user-specific module keys. |
mobile/app/src/main/java/org/owasp/mobileshepherd/utils/CompletionVisualFeedback.java |
Applies completion borders. |
mobile/app/src/main/java/org/owasp/mobileshepherd/utils/CompletionBadge.java |
Calculates badges and progress messages. |
mobile/app/src/main/java/org/owasp/mobileshepherd/ui/scoreboard/ScoreboardFragment.java |
Fetches and renders server rankings. |
mobile/app/src/main/java/org/owasp/mobileshepherd/ui/progress/ProgressFragment.java |
Renders progress statistics and history. |
mobile/app/src/main/java/org/owasp/mobileshepherd/ui/home/HomeFragment.java |
Manages Home authentication controls. |
mobile/app/src/main/java/org/owasp/mobileshepherd/ui/adb/AdbReferenceFragment.java |
Copies reference commands to the clipboard. |
mobile/app/src/main/java/org/owasp/mobileshepherd/Preferences.java |
Handles themes, progress reset, and support. |
mobile/app/src/main/java/org/owasp/mobileshepherd/NavigationItem.java |
Models hierarchical drawer entries. |
mobile/app/src/main/java/org/owasp/mobileshepherd/NavigationAdapter.java |
Renders expandable navigation entries. |
mobile/app/src/main/java/org/owasp/mobileshepherd/LoginActivity.java |
Coordinates registration, login, and offline entry. |
mobile/app/src/main/java/org/owasp/mobileshepherd/LandingActivity.java |
Presents the introduction and entrance animations. |
mobile/app/src/main/AndroidManifest.xml |
Declares activities, permissions, and app policies. |
mobile/app/src/androidTest/java/com/owasp/reverser/ExampleInstrumentedTest.java |
Checks the installed application package. |
mobile/app/proguard-rules.pro |
Configures release shrinking and class retention. |
mobile/app/build.gradle |
Configures Android builds and dependencies. |
mobile/app/.gitignore |
Excludes app build output. |
mobile/.gitignore |
Updates generated-file and local-file exclusions. |
Review effort: Balanced
Comment on lines
+11
to
+13
| android:allowBackup="true" | ||
| android:dataExtractionRules="@xml/data_extraction_rules" | ||
| android:fullBackupContent="@xml/backup_rules" |
Comment on lines
+138
to
+140
| statusText.setTextColor(isError | ||
| ? getResources().getColor(android.R.color.holo_red_dark, getTheme()) | ||
| : getResources().getColor(android.R.color.darker_gray, getTheme())); |
| @Override | ||
| public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { | ||
| // Load the preferences from an XML resource | ||
| setPreferencesFromResource(R.xml.preferences, rootKey); |
Comment on lines
+13
to
+16
| <debug-overrides> | ||
| <trust-anchors> | ||
| <certificates src="system" /> | ||
| <certificates src="user" /> |
Comment on lines
+10
to
+11
| # Configure Gradle to use Java 17 | ||
| org.gradle.java.home=C:\\Program Files\\Android\\Android Studio\\jbr |
| setupCopyButton(binding.copySqliteQuery, "sqlite> SELECT * FROM users;"); | ||
| setupCopyButton(binding.copyCat, "adb shell cat /data/data/org.owasp.mobileshepherd/shared_prefs/UserCredentials.xml"); | ||
|
|
||
| setupCopyButton(binding.copyGetPackages, "adb shell pm list packages | grep reverser"); |
Comment on lines
+38
to
+52
| updateAuthCard(); | ||
| } | ||
|
|
||
| private void updateAuthCard() { | ||
| TextView statusText = binding.getRoot().findViewById(org.owasp.mobileshepherd.R.id.home_auth_status_text); | ||
| MaterialButton authButton = binding.getRoot().findViewById(org.owasp.mobileshepherd.R.id.home_auth_button); | ||
| if (statusText == null || authButton == null) return; | ||
|
|
||
| if (AuthManager.isAuthenticated(requireContext())) { | ||
| String username = AuthManager.getUsername(requireContext()); | ||
| statusText.setText("Signed in as " + username + " — keys update from server"); | ||
| authButton.setText("Sign Out"); | ||
| authButton.setOnClickListener(v -> { | ||
| AuthManager.logout(requireContext()); | ||
| updateAuthCard(); |
Comment on lines
+65
to
+68
| signInButton.setOnClickListener(v -> { | ||
| if (getActivity() instanceof MainActivity) { | ||
| ((MainActivity) getActivity()).openAuthDialog(); | ||
| } |
The app asks /mobileModuleStatus which modules the signed-in student can open and greys out the rest in the navigation drawer and progress list, with the server's reason shown when tapped. This mirrors the platform's open floor / CTF rules: module closed, event not running, module blocked. Advisory only: the server re-checks every module start and key request. It fails open, so signed-out or offline use and failed requests grey out nothing. Status refreshes on resume, drawer open, sign in and sign out.
…JDK path Changing server_preference while signed in kept the old server's session cookie, so it would be sent to the new server. Log out when the server actually changes. Remove org.gradle.java.home, which pinned a Windows Android Studio path and overrode JAVA_HOME on other machines.
Replace the individually listed local planning docs with a single *.md rule.
Remove CHALLENGE_SOLUTIONS.txt and missing_challenges.txt, which refer to no files in the repository.
This was referenced Nov 1, 2026
The logcat grep example rendered a literal "search_term" on the ADB Commands screen.
The Android app lives in mobile/, not mobile/MobileShepherd/.
…l' into mobile-split/04-android-app-shell
Insecure Communication is deferred to 4.0.1. Remove its key hash entries, ProGuard rules and the cleartext-traffic comment.
Drop the About dialog button that opened owasp.org and the unused hidden Top 10 FAB with its string. Lessons now name the relevant risk as plain text.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Adds the Mobile Shepherd Android app shell. It has no lessons or challenges; those arrive one OWASP Mobile category per PR, after this merges.
Part 3 of the split of #894. Depends on the module IDs/cheatsheets PR and the server API PR.
Included
mobile/AuthManager), scoreboard, progress tracking and badgesKeyValidator(server-validated keys),KeyProvider,ModuleInfoHelperKeyValidator.Moduleenum, which each category PR fills inSecurity notes
cleartextTrafficPermitted=false, and the app only accepts anhttps://server URL (AuthManager.isSecureServerUrl).Testing
./gradlew assembleDebug testDebugUnitTestpasses.