# Mobile Application Development — Stale course audit

- URL: https://getstale.tech/run/web_20260504T162848Z
- Target role: Mobile Developer
- Course focus: Android Application Development
- Audit date: 2026-05-04T16:28:48Z
- Verified findings: 13
- Structured data: https://getstale.tech/run/web_20260504T162848Z.json

## Findings

### 1. Security risk (critical severity)

**Location:** Lecture 10 Exploring Maps and Location Based Services_.pdf page 3

**What the slide says:**

> 3- Replace YOUR_API_KEY with You API KEY: AIza<REDACTED> -OR- AIza<REDACTED>

**Primary source:** https://cloud.google.com/docs/authentication/api-keys-best-practices (verified)

> API keys hardcoded in the source code or stored in a repository are open to interception or theft by bad actors.

**What to learn instead:** Never display real Google API keys in lecture slides or code samples. Teach students to load keys from local.properties (excluded via .gitignore), Android Keystore, environment variables, or a backend proxy, and to apply API key restrictions in the Google Cloud console (application restrictions to the app's package name + SHA-1, plus API restrictions to the Maps SDK only). The two keys shown should be revoked from the project they belong to.

### 2. Security risk (critical severity)

**Location:** Lecture 6 _Database and Content Providers_.pdf pages 9, 10, 22, 23, 24

**What the slide says:**

> db.execSQL("INSERT INTO student VALUES('"+editRollno.getText()+"','"+editName.getText()+ "','"+editMarks.getText()+"');"); ... Cursor c=db.rawQuery("SELECT * FROM student WHERE rollno='"+editRollno.getText()+"'", null);

**Primary source:** https://owasp.org/www-community/attacks/SQL_Injection (verified)

> A successful SQL injection exploit can read sensitive data from the database, modify database data (Insert/Update/Delete), execute administration operations on the database

**What to learn instead:** Every CRUD example in the StudentDB / EmployeeDB lectures concatenates `EditText` user input directly into SQL strings — a textbook SQL injection vulnerability. Rewrite using parameterised APIs: `db.execSQL(sql, new Object[]{name, marks})` for writes, `db.rawQuery("SELECT ... WHERE rollno = ?", new String[]{rollno})` for reads, or `db.insert/update/delete(...)` with `ContentValues` and `?`-placeholder selection arguments. Even better, teach Room, which forces compile-time-checked parameterised queries.

### 3. Outdated (high severity)

**Location:** Lecture 11 Threads in Android-2.pdf pages 33-52

**What the slide says:**

> The AsyncTask class implements a best practice pattern for moving your time-consuming(short-lived) operations onto a background Thread and synchronizing with the UI Thread...

**Primary source:** https://developer.android.com/reference/android/os/AsyncTask (verified)

> This class was deprecated in API level 30. Use the standard java.util.concurrent or Kotlin concurrency utilities instead.

**What to learn instead:** Replace AsyncTask instruction with Kotlin coroutines (viewModelScope/lifecycleScope with Dispatchers.IO), java.util.concurrent.Executors + Handler(Looper.getMainLooper()), or WorkManager for deferrable background work. Note that AsyncTask leaks Context across configuration changes, swallows exceptions in doInBackground, and has been deprecated since Android 11.

### 4. Security risk (high severity)

**Location:** Lecture 6 _Database and Content Providers_.pdf page 6

**What the slide says:**

> MODE_WORLD_READABLE: File creation mode: allow all other applications to have read access to the created file. MODE_WORLD_WRITEABLE: File creation mode: allow all other applications to have write access to the created file.

**Primary source:** https://developer.android.com/reference/android/content/Context#MODE_WORLD_READABLE (verified)

> This constant was deprecated in API level 17. Creating world-readable files is very dangerous, and likely to cause security holes in applications.

**What to learn instead:** Remove MODE_WORLD_READABLE / MODE_WORLD_WRITEABLE from the curriculum. They have been deprecated since Android 4.2 (API 17) and throw SecurityException on targetSdk ≥ 24. Teach MODE_PRIVATE plus a properly-exported ContentProvider (with android:permission) for cross-app data sharing, or FileProvider with content:// URIs for sharing files.

### 5. Outdated (high severity)

**Location:** Lecture 5 _week 5_.pdf pages 5-25

**What the slide says:**

> FragmentManager fragmentManager = getFragmentManager(); ... 1. Extend Fragment OR one of its subclasses (DialogFragment, ListFragment, PreferenceFragment, WebViewFragment) ... import android.app.Fragment;

**Primary source:** https://developer.android.com/reference/android/app/Fragment (verified)

> This class was deprecated in API level 28. Use the Jetpack Fragment Library Fragment for consistent behavior across all devices and access to Lifecycle.

**What to learn instead:** Migrate the entire Fragment chapter from `android.app.Fragment` to `androidx.fragment.app.Fragment`. Have the activity extend `AppCompatActivity` (or `FragmentActivity`) and use `getSupportFragmentManager()`. The platform Fragment, ListFragment, DialogFragment, PreferenceFragment, and WebViewFragment have all been deprecated since API 28 (Android 9, 2018) and do not receive Lifecycle/ViewModel integration.

### 6. Outdated (high severity)

**Location:** Lecture 2 _week 2_.pdf pages 32-36

**What the slide says:**

> Dalvik Virtual Machine ✓Providing environment on which every Android application runs ... Dalvik interprets Java bytecode.

**Primary source:** https://source.android.com/docs/core/runtime (verified)

> Android runtime (ART) is the managed runtime used by apps and some system services on Android. ART and its predecessor Dalvik were originally created specifically for the Android project.

**What to learn instead:** Rewrite the runtime section to teach ART (Android Runtime) as the current runtime — Dalvik was replaced by ART as the default runtime in Android 5.0 (Lollipop, 2014) and removed entirely in later versions. Cover ART's hybrid AOT + JIT + profile-guided compilation, dex2oat, and improved garbage collection. Mention Dalvik only as historical context (and note that .dex bytecode is still the distribution format consumed by ART).

### 7. No longer works (high severity)

**Location:** Lecture 1 _Mobile Application Trends_ Android OS_.pdf page 50

**What the slide says:**

> Android SDK Features ... • Cloud to Device Messaging

**Primary source:** https://developers.google.com/android/c2dm (verified)

> C2DM was officially deprecated on June 26, 2012, and was shut down completely as of July 30, 2015.

**What to learn instead:** Replace 'Cloud to Device Messaging' with 'Firebase Cloud Messaging (FCM)'. C2DM was deprecated in 2012 and the servers were turned off in 2015; its successor GCM was also deprecated and shut down in 2019. Any push-notification material in the course should be taught against FCM via the Firebase SDK.

### 8. Outdated (medium severity)

**Location:** Lecture 4.pdf pages 15-19

**What the slide says:**

> Commonly‐used Android containers are: • Absolute Layout ... An Absolute Layout lets you specify exact locations (x/y coordinates) of its children.

**Primary source:** https://developer.android.com/reference/android/widget/AbsoluteLayout (verified)

> This class was deprecated in API level 3. Use FrameLayout, RelativeLayout or a custom layout instead.

**What to learn instead:** Drop AbsoluteLayout from the curriculum entirely. It has been deprecated since 2009 (API 3, Cupcake). Modern Android UI should be taught with ConstraintLayout (the default in Android Studio templates), LinearLayout, FrameLayout, or — preferably — Jetpack Compose.

### 9. Outdated (medium severity)

**Location:** Lecture 8.pdf pages 12, 17-24

**What the slide says:**

> startActivityForResult(in, 1); ... startActivityForResult(intent, SHOW_SUBACTIVITY); ... public void onActivityResult(int requestCode, int resultCode, Intent data) {...}

**Primary source:** https://developer.android.com/training/basics/intents/result (verified)

> Google strongly recommends using the Activity Result APIs introduced in AndroidX Activity and Fragment classes.

**What to learn instead:** Replace the `startActivityForResult` / `onActivityResult` examples with the Activity Result APIs: `registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> ... }`. The new APIs are deprecation-free, type-safe via `ActivityResultContract`, survive process death, and work uniformly inside Fragments. The old APIs are flagged deprecated in androidx.activity 1.2+ (released 2021).

### 10. Outdated (medium severity)

**Location:** Lecture 10 Exploring Maps and Location Based Services_.pdf pages 30-31

**What the slide says:**

> Geocoder geocoder = new Geocoder(this); try { addressList = geocoder.getFromLocationName(locatiion, 1); ... }

**Primary source:** https://developer.android.com/reference/android/location/Geocoder (verified)

> This method was deprecated in API level 33. Use getFromLocationName(String,int,GeocodeListener) instead to avoid blocking a thread waiting for results.

**What to learn instead:** Replace the synchronous `getFromLocationName(String, int)` call (which blocks the calling thread on a network lookup and was deprecated in API 33 / Android 13) with the asynchronous overload `getFromLocationName(String, int, Geocoder.GeocodeListener)` on Android 13+, falling back to running the legacy call inside a coroutine / Executor on older devices. The current code, executed on the UI thread, will trigger a NetworkOnMainThreadException on any modern device.

### 11. Outdated (medium severity)

**Location:** Lecture 7.pdf pages 26-31

**What the slide says:**

> Android 3.0 (API level 11) introduced the Loader class. ... CursorLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

**Primary source:** https://developer.android.com/reference/android/content/CursorLoader (verified)

> This class was deprecated in API level 28. Use the Support Library CursorLoader

**What to learn instead:** Stop teaching the platform `android.content.CursorLoader` and `LoaderManager` — both were deprecated in API 28 (2018). For new content-provider/database UIs, teach Room + Flow/LiveData + ViewModel (officially recommended) or, if students must use a Cursor pipeline, the AndroidX `androidx.loader.content.CursorLoader`. The slide's `getSupportLoaderManager()` already hints at the AndroidX path; align the rest of the lecture with it.

### 12. Outdated (low severity)

**Location:** Lecture 4.pdf pages 6-50 (XML examples throughout)

**What the slide says:**

> android:layout_width="fill_parent" android:layout_height="fill_parent

**Primary source:** https://developer.android.com/reference/android/view/ViewGroup.LayoutParams#FILL_PARENT (verified)

> This value is deprecated starting in API Level 8 and replaced by MATCH_PARENT

**What to learn instead:** Replace every `fill_parent` in XML examples with `match_parent`. fill_parent has been deprecated since Android 2.2 (API 8, May 2010); the slides also use `match_parent` in some examples (Lecture 5), so the inconsistency teaches outdated naming.

### 13. Incorrect (low severity)

**Location:** Lecture 6 _Database and Content Providers_.pdf page 2

**What the slide says:**

> Datasets –can't exceed file system limit or 2TB

**Primary source:** https://www.sqlite.org/limits.html (verified)

> the database file can grow to be as large as about 281 terabytes

**What to learn instead:** Update the SQLite size limit. Per the official SQLite limits page, the theoretical maximum database size is approximately 281 terabytes (with the maximum 65,536-byte page size), bounded in practice by the host filesystem. The 2 TB figure in the slide is off by more than two orders of magnitude.

## Market fit

This curriculum prepares the student for an early-2010s Java/AsyncTask Android developer role — strong on activities, fragments, intents, SQLite, Maps and broadcast receivers, but missing the REST/HTTP, unit-testing, push-notification and store-deployment plumbing that 40–80% of today's mobile postings expect, while modern Kotlin/Compose/MVVM/CI-CD demands sit outside the course's stated depth bound.

### REST API consumption (HTTP client usage from Android, e.g. HttpURLConnection) (critical)

Networking is partially covered: L10 p22 declares the INTERNET permission ('For network transactions we need to define Internet … <uses-permission android:name="android.permission.INTERNET" />') and L11 p12 lists 'Network lookups' / 'accessing data from the Internet' as canonical time-consuming/blocking operations to push onto a background thread. The course never shows how to actually issue an HTTP request, parse a JSON response, or hit a REST endpoint — yet 10/12 mobile postings demand REST API skills. Extension: in the existing background-thread unit, walk through a concrete HttpURLConnection (or built-in URL/JSONObject) GET/POST against a REST endpoint, executed on a java.util.concurrent.Executor with results delivered back to the UI thread via Handler(Looper.getMainLooper()). Note: the course's current AsyncTask scaffolding (L11 p52) is deprecated as of API 30 and should be replaced — not extended — when adding this REST lab. Stays at SDK-fundamentals depth (no Retrofit/OkHttp/Coroutines per depth bound).

### Unit testing of Android code (JUnit + Android instrumentation) (high)

Testing is mentioned but not taught: L1 p70 lists in the Android dev-process diagram 'Test your application using the Android testing and instrumentation framework' but no lecture, lab, or example actually writes a test. 9/12 mobile postings require unit testing. Extension: in the existing dev-process treatment, add a hands-on JUnit test of a plain helper class plus one Android-instrumented test (e.g. assertEquals on a util used by an existing activity). Stays at hands-on Android-SDK depth — no Espresso/Mockito/CI per depth bound.

### Push notifications (Firebase Cloud Messaging-style remote notifications) (high)

Notifications and cloud messaging are partially covered: L2 p22 'Application Framework- Notification Manager — Alerts the user about occurring important events. Enabling all applications to display customer alerts in the status bar, flashing lights, vibrations etc.' and L1 p50 lists 'Cloud to Device Messaging' as an Android SDK feature. Neither slide shows how to display a NotificationCompat.Builder notification or receive a server-sent push. 8/12 postings demand push notifications. Extension: extend the Notification Manager slide to a worked example that builds and posts a local notification via NotificationCompat.Builder + NotificationManager.notify(), and conceptually link 'Cloud to Device Messaging' to FCM-delivered remote notifications received in a BroadcastReceiver — reusing the BroadcastReceiver content already in L9.

### App store deployment (signing + Google Play / App Store upload workflow) (medium)

Distribution is partially covered: L1 p70 development-process diagram explicitly includes 'Prepare your application for release — Configure, build, and test your application in release mode' and 'Release your application — Publicize, sell, and distribute your application', and L1 p23 names the App Store / Google Play as the distribution channels. The course stops at the concept; it never walks through generating a signed APK/AAB or the Play Console upload. 5/12 postings demand app store deployment skills. Extension: in the existing release-step slide, add a concrete walk-through of generating a release-keystore-signed APK/AAB in Android Studio and uploading it to the Google Play Console (and the Xcode archive → App Store Connect equivalent for the iOS side). Stays at hands-on SDK depth — no CI/CD/Fastlane per depth bound.

## Recommended topics

The top three prescriptions — REST API consumption via HttpURLConnection on an Executor (83% of postings), hands-on JUnit4 + AndroidJUnit4 unit testing (75%), and modern NotificationCompat + FCM push notifications (67%) — together address the three skills that more than two-thirds of the analysed mobile postings demand and that the current curriculum only gestures at. Crucially, prescription #1 doubles as the Auditor's mandated replacement of the deprecated AsyncTask chapter, and prescription #3 doubles as the replacement of the dead 'Cloud to Device Messaging' bullet, so adopting them retires two flagged patterns at the same time as closing two market gaps.

### #1 REST API consumption from Android: HttpURLConnection GET/POST + JSONObject parsing, executed on a java.util.concurrent.Executor with results posted back via Handler(Looper.getMainLooper()) (~8h to learn)

Teach students to actually call a REST endpoint from Android — HttpURLConnection + JSONObject on an Executor with a main-thread Handler — replacing the deprecated AsyncTask walk-through that 10 of 12 postings have made obsolete.

Keywords: rest api, http, httpurlconnection, json, jsonobject, executor, handler, looper, background thread

Where it fits: Mobile Application Programming · Replaces — not extends — the AsyncTask material in Lecture 11 'Threads in Android' (pages 33-52, flagged outdated by the Auditor). The lecture currently teaches AsyncTask as the way to do 'Network lookups' (L11 p12), but never actually issues an HTTP request. The fix is to swap the AsyncTask example for an Executors.newSingleThreadExecutor() + Handler(Looper.getMainLooper()) pattern that performs an HttpURLConnection GET/POST against a public REST endpoint and parses the response with org.json.JSONObject. The INTERNET permission slide (L10 p22) already supplies the manifest piece; this lecture supplies the missing client code.

### #2 Hands-on unit testing for Android: JUnit4 local tests in src/test/java plus a minimal AndroidJUnit4 instrumentation test in src/androidTest/java (~6h to learn)

Turn the one-bullet 'Test your application' diagram into an actual JUnit4 lab plus a one-screen AndroidJUnit4 instrumentation test — the testing skill 9 of 12 postings list as required.

Keywords: unit testing, junit, junit4, assertequals, androidjunit4, instrumentation test, test runner

Where it fits: Mobile Application Programming · Extends Lecture 1 page 70 ('Test your application using the Android testing and instrumentation framework'), which today is a single bullet in the development-process diagram with no worked example. Promote this bullet to a short hands-on unit: write a JUnit4 test of a pure-Java helper used by an existing activity (e.g. a roll-number / marks validator from the StudentDB lab — once that lab is rewritten with parameterised SQL per the Auditor's fix), and a single @RunWith(AndroidJUnit4.class) instrumentation test that launches an activity and asserts a TextView's text. Stays at SDK-fundamentals depth — no Mockito, no Espresso flows, no CI.

### #3 Modern Android notifications: NotificationCompat.Builder + NotificationChannel for local notifications, with a conceptual walk-through of receiving a Firebase Cloud Messaging (FCM) remote push in a service (~6h to learn)

Replace the dead 'Cloud to Device Messaging' bullet with a working NotificationCompat.Builder + FCM walk-through — covering the push-notification skill 8 of 12 postings demand.

Keywords: push notifications, notificationcompat, notificationmanager, notificationchannel, firebase cloud messaging, fcm, firebasemessagingservice

Where it fits: Mobile Application Programming · Extends Lecture 2 page 22 (Notification Manager) with a concrete NotificationCompat.Builder + NotificationChannel (mandatory since API 26) example that calls NotificationManager.notify(). Simultaneously *replaces* the 'Cloud to Device Messaging' bullet on Lecture 1 page 50 — flagged dead by the Auditor (C2DM was shut down in 2015) — with a brief Firebase Cloud Messaging conceptual segment showing a FirebaseMessagingService.onMessageReceived() handler that builds the same NotificationCompat notification. Per the depth bound this stays at SDK-level construction; no full Firebase backend setup or token-management deep dive.

### #4 App store deployment workflow: generate an upload-keystore-signed Android App Bundle (AAB) in Android Studio and upload to the Google Play Console (with the Xcode Archive → App Store Connect equivalent for the iOS intro) (~5h to learn)

Take the 'Release your application' bullet on the dev-process slide all the way to a signed AAB on the Play Console — the deployment skill 5 of 12 postings ask for.

Keywords: app store deployment, google play console, signed apk, aab, android app bundle, keystore, release build, xcode archive, app store connect

Where it fits: Mobile Application Programming · Extends the release-step slide on Lecture 1 page 70 ('Prepare your application for release — Configure, build, and test your application in release mode' / 'Release your application — Publicize, sell, and distribute your application') and the App Store / Google Play distribution mention on L1 p23. The course currently stops at the concept; this prescription adds a concrete walk-through: Build → Generate Signed Bundle/APK in Android Studio, generation of an upload keystore, an AAB upload to a Google Play Console internal-testing track, plus a parallel Product → Archive → Distribute App flow for the Lecture 12 Xcode/Swift intro. Stays at hands-on SDK depth — no Fastlane, no CI/CD pipeline per the depth bound.

---
Produced by Stale (https://getstale.tech). Request a course audit: https://getstale.tech/request-audit
