Phase 6 · Professional AndroidModule 40~35 min read

Android Security & Privacy

Audit real data flows, minimize permissions, select media through system pickers, and protect storage, networking and release credentials.

Android Security & Privacy: learning goals

Review a small app's actual data flows: what it collects, where it stores information, what it sends, and when it deletes data. Make a narrow, demonstrable security improvement before preparing a release.

Project setup and scope

Use Activity Compose for the photo-picker example. Treat the generated app, its libraries and any backend as separate trust boundaries. The code demonstrates selecting one user-chosen image; rendering, durable URI access and storage/deletion policies are separate decisions to implement for your use case.

Build the mental model

Start from assets and boundaries. A study note may contain personal information even when the app has no login screen. List each asset, the code that can read it, the system or service it crosses, and the user's expectation. Avoid collecting data that the feature does not need.

Server credentials cannot be kept confidential inside a distributed APK. Moving a secret into a resources file, BuildConfig, native code or obfuscation changes its location rather than making a trustworthy server boundary. Keep privileged server operations behind an authenticated backend and apply provider-supported restrictions to public client identifiers.

Choose storage and cryptography based on a threat model. App-private storage limits ordinary cross-app access but does not by itself promise protection against every compromised device or backup exposure. Android Keystore helps manage cryptographic keys; it is not a replacement for access control, lifecycle design, deletion policy or careful cryptographic API use.

Prefer platform-mediated selection when the user chooses a specific file or photo. A picker can grant access to selected content without requesting broad media-library access. A returned URI is an identifier with scoped access, not a filesystem path or unlimited permanent grant. Handle cancellation and decide whether durable access or a controlled local copy is needed.

Choose the right approach

NeedApproach
User chooses one imageUse the system photo picker and handle a null/cancel result.
Privileged backend secretKeep it on a server; never ship it in the app.
Ordinary private session dataUse app-private persistence with an explicit backup/deletion policy.
Sensitive local encryption keyEvaluate Android Keystore and vetted crypto APIs against the threat model.
Diagnostic loggingUse nonpersonal identifiers and remove tokens, notes and sensitive payloads.

Predict and trace the behavior

Android concept labInteractive walkthrough

Android Security & Privacy

Predict what happens next. Follow the diagram, then explain the change in your own words.

Representative concept map

Delivery is a sequence of quality gates

release
01ConfigureID · version · privacy
02VerifyTests · release build
03DistributeSigned AAB · testing track
04ObserveFeedback · stability
Feedback informs the next release

Keep signing keys and credentials outside source control. Widen rollout only after reviewing evidence.

Verify the artifact you will distribute, start with a testing track, then observe feedback before widening delivery.

Explore this general model independently. The lesson sequence below follows its own example.

Prepare: Review application ID, versioning, privacy declarations, and production configuration.

Lesson sequence1 / 4
Step 1 of 4

Inventory

Name each collected field, purpose, storage location and deletion behavior.

Up nextMinimize access
A teaching simulation; diagrams illustrate the concept. Run the Kotlin examples in Android Studio.

Worked Kotlin example

PickAttachment.kt
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable

@Composable
fun PickAttachment(onSelected: (Uri) -> Unit) {
    val picker = rememberLauncherForActivityResult(PickVisualMedia()) { uri ->
        if (uri != null) onSelected(uri) // Cancel leaves the current note unchanged.
    }
    Button(onClick = {
        picker.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))
    }) {
        Text("Choose image") // Move this label into strings.xml in your app.
    }
}
// No broad storage/media permission is needed for this selection flow.
// TODO: decide URI access lifetime, validate content/size, and implement removal.
Focused teaching example. Keep your generated package/theme and complete the explicitly labeled integration points.
  1. The launcher belongs to the composition, and launching occurs from a user event. Do not open the picker automatically during recomposition.
  2. A null result represents cancellation; the callback deliberately leaves the current note untouched.
  3. Accepting a URI is only the selection boundary. Use ContentResolver for content access, handle revoked/unavailable access, and apply a size/type policy before uploading or copying content.
  4. If access must survive longer, follow the contract/provider guidance for persistable grants or make a controlled app-private copy; implement deletion for either approach.

Student practice and expected behavior

Audit the notes app. Add one optional user-selected attachment, remove unnecessary permissions, redact sensitive logs, and document a data deletion action. Record the purpose, retention and transmission of every field.

  • Cancelling the picker leaves the existing note and attachment unchanged.
  • Choosing an image attaches only the selected content; no broad gallery permission prompt appears for this flow.
  • An unavailable URI shows a recoverable state instead of crashing or silently uploading a different file.
  • Deleting a note removes app-owned attachment data according to your stated policy, while not claiming to erase the user's original photo.
  • The source and logs contain no private backend credentials, user note text, session tokens or signing passwords.

Write down the input, expected outcome and observed outcome for each check. Include a screenshot, a short recording or a nonpersonal diagnostic trace appropriate to the behavior you are proving.

Debugging clinic

  • An encrypted blob is not a complete privacy policy. Retention, sharing, backups, deletion and SDK behavior still matter.
  • Do not convert content:// URIs to guessed filesystem paths or assume every provider gives permanent access.
  • Avoid disabling TLS certificate checks to repair a development connection. Correct the endpoint/certificate and isolate development configuration.
  • A client-supplied user ID is not server authorization. The backend must verify what the authenticated caller may access.

Instructor prompts

  1. Ask pairs to draw the path of one attachment from selection to deletion and mark each trust boundary.
  2. Give students a fake secret in BuildConfig and ask why obfuscating the APK would not establish a server boundary.
  3. Review a privacy inventory against the actual app flow and installed SDKs; highlight one unverified claim.

Teach-back checkpoint

Ask a student to describe one incorrect approach, reproduce the resulting behavior, and explain the repair using ownership, lifetime, constraints or trust boundaries from this lesson.

Quick check and references

Quick check

1. Where does a privileged backend credential belong?

2. What should picker cancellation do in this example?

Continue with the phase capstone after demonstrating the practice checks. Use the official documentation to verify APIs against your project's selected dependency versions.