Content Providers & Broadcasts Quiz

ANDROID › Components

Your app stores data only for its own use and never shares it. Which is the best choice?

Answer: Use Room or another local store directly; no ContentProvider needed

ContentProviders are mainly justified for cross-app sharing, search suggestions, widgets, or sync adapters. For app-private data, Room/DataStore is simpler and the provider adds needless overhead.

What does ContentResolver.insert() return on success?

Answer: The content URI for the newly inserted row

insert() returns the Uri of the new row (e.g. content://authority/table/id); query() returns a Cursor, while update() and delete() return row-count Ints.

In a ContentResolver query, what does the projection parameter specify?

Answer: The set of columns to return

Projection is the array of column names to return (the SELECT columns). Selection/selectionArgs form the WHERE clause and sortOrder is the ORDER BY.

Since Android 8.0 (API 26), what is true about manifest-declared receivers for implicit broadcasts?

Answer: Most implicit broadcasts no longer hit manifest receivers, except a few

API 26 removed most implicit broadcasts from manifest receivers to reduce background wakeups; a short exemption list (e.g. ACTION_BOOT_COMPLETED) remains. Use context-registered receivers or scheduled jobs instead.

Which capability is unique to an ordered broadcast (sendOrderedBroadcast) versus a normal one?

Answer: A receiver can abort delivery or pass modified result data on

Ordered broadcasts go to one receiver at a time in priority order, letting each propagate or modify result data or call abortBroadcast(). Normal broadcasts run in undefined order with no result sharing or aborting.

On Android 13+ you context-register a receiver but omit the export flag. What happens?

Answer: It throws because RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED is required

Targeting API 33+, registering a runtime receiver requires explicitly passing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED (via ContextCompat.registerReceiver); omitting it raises an exception.

A BroadcastReceiver needs to do a few seconds of background work in onReceive(). What is the correct approach?

Answer: Use goAsync(), work off the main thread, then call finish() within ~10s

onReceive() runs on the main thread and the process can be killed once it returns, so raw threads are unsafe. goAsync() keeps the broadcast alive while you work on a background thread, finishing within about 10 seconds; longer work belongs in WorkManager/JobScheduler.

By convention, what MIME type should a ContentProvider's getType() return for a URI that matches multiple rows (a directory)?

Answer: A string starting with vnd.android.cursor.dir/

The Android convention is vnd.android.cursor.dir/ for a URI matching many rows and vnd.android.cursor.item/ for a single row; getType() returns these so callers know whether the URI is a collection or one item.

You want to let another app read one specific image URI from your provider just for the duration of an Intent, without exposing your whole provider. What is the correct mechanism?

Answer: Add FLAG_GRANT_READ_URI_PERMISSION to the Intent

Temporary, per-URI access is granted by flagging the Intent with FLAG_GRANT_READ_URI_PERMISSION (and the provider allowing grantUriPermissions); the grant lasts only as long as the receiving component's stack, avoiding broad permanent exposure.

How does a client get notified when the data behind a content URI changes, rather than re-querying on a timer?

Answer: Register a ContentObserver; the provider calls notifyChange() after each write

Clients register a ContentObserver against the URI, and the provider must call ContentResolver.notifyChange() after modifying data so observers fire; ContentResolver does not expose an automatic Flow per URI.

Why do libraries such as Jetpack App Startup, Firebase, and WorkManager use a stub ContentProvider for auto-initialization?

Answer: A provider's onCreate() runs before Application.onCreate(), enabling early auto-init

The system instantiates manifest-declared providers and calls their onCreate() before Application.onCreate(), so a zero-data stub provider is a convenient hook to run startup initialization automatically via manifest merging.

You send an app-wide broadcast but want only apps that hold a specific permission to be able to receive it. What is the correct approach?

Answer: Pass the permission string as receiverPermission in sendBroadcast()

sendBroadcast(intent, receiverPermission) limits delivery to receivers whose apps hold the named permission. FLAG_RECEIVER_REGISTERED_ONLY only restricts to runtime-registered receivers, and exported=false blocks other apps entirely rather than gating by permission.

LocalBroadcastManager is deprecated. What is the recommended modern way to deliver app-internal events between components in the same process?

Answer: Use a shared Flow/StateFlow or LiveData observable

LocalBroadcastManager was deprecated in favor of observable data holders; an app-scoped StateFlow/SharedFlow or LiveData lets components communicate in-process without the broadcast machinery and its lifecycle pitfalls.

You implement a ContentProvider used only inside your own app. What is the best way to keep other apps from accessing it?

Answer: Set android:exported="false" on the <provider> element

Explicitly setting android:exported="false" keeps the provider private to your app. Relying on defaults is unsafe because providers defaulted to exported=true before API 17, and grantUriPermissions/syncable do not control general cross-app access.

Back to Content Providers & Broadcasts