Media, Bluetooth & Wi-Fi

Play audio and video, connect Bluetooth devices, and monitor network status

Audio Video Bluetooth Wi-Fi

Table of Contents

Media & Connectivity Overview

Android apps frequently play media, connect to Bluetooth peripherals, and react to network changes. Each capability uses dedicated APIs with specific permissions and lifecycle considerations.

Media: MediaPlayer / ExoPlayer → AudioManager → Speaker or BT headset Bluetooth: BluetoothAdapter → Scan → Pair → Connect (Classic or BLE) Wi-Fi: ConnectivityManager → NetworkCallback → Online / Offline UI
FeaturePrimary APIPermissions
Audio playbackMediaPlayer, ExoPlayerNone (local files)
Video playbackMediaPlayer + SurfaceView, ExoPlayerInternet (streaming)
BluetoothBluetoothAdapter, BluetoothLeScannerBLUETOOTH_CONNECT, BLUETOOTH_SCAN (12+)
Wi-Fi statusConnectivityManagerACCESS_NETWORK_STATE

1Audio Playback

Android supports playing audio from local files, raw resources, and streaming URLs. Manage audio focus so your app cooperates with other apps (calls, music players).

Play from raw resource

Kotlin — Play sound from res/raw/class SoundActivity : AppCompatActivity() { private var mediaPlayer: MediaPlayer? = null fun playNotificationSound() { mediaPlayer?.release() mediaPlayer = MediaPlayer.create(this, R.raw.notification_sound) mediaPlayer?.setOnCompletionListener { mp -> mp.release() mediaPlayer = null } mediaPlayer?.start() } override fun onDestroy() { mediaPlayer?.release() mediaPlayer = null super.onDestroy() } }

Audio focus (recommended for music apps)

Kotlin — Request audio focusprivate val audioManager by lazy { getSystemService(Context.AUDIO_SERVICE) as AudioManager } private fun requestAudioFocus(): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes( AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() ) .setOnAudioFocusChangeListener { focusChange -> when (focusChange) { AudioManager.AUDIOFOCUS_LOSS -> pausePlayback() AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> pausePlayback() AudioManager.AUDIOFOCUS_GAIN -> resumePlayback() } } .build() audioManager.requestAudioFocus(focusRequest) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED } else { @Suppress("DEPRECATION") audioManager.requestAudioFocus( null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN ) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED } }

Stream audio from URL

Kotlin — Stream MP3 from internetsuspend fun playStream(url: String) = withContext(Dispatchers.IO) { val player = MediaPlayer().apply { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) setDataSource(url) prepareAsync() setOnPreparedListener { it.start() } } }

2Video Playback

Video requires rendering frames to a SurfaceView, TextureView, or VideoView. For production apps, ExoPlayer (Media3) is recommended over raw MediaPlayer for streaming and adaptive bitrate.

Simple VideoView

XML — activity_video.xml<VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="240dp" />
Kotlin — Play local or online videoclass VideoActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_video) val videoView = findViewById<VideoView>(R.id.videoView) val mediaController = MediaController(this) mediaController.setAnchorView(videoView) videoView.setMediaController(mediaController) // Local file // val uri = Uri.parse("android.resource://$packageName/${R.raw.demo_video}") // Online stream val uri = Uri.parse("https://example.com/sample.mp4") videoView.setVideoURI(uri) videoView.setOnPreparedListener { it.start() } } override fun onPause() { super.onPause() findViewById<VideoView>(R.id.videoView).pause() } }

ExoPlayer (Media3 — recommended)

Kotlin — ExoPlayer setup// dependencies { implementation("androidx.media3:media3-exoplayer:1.2.1") } class ExoPlayerActivity : AppCompatActivity() { private var player: ExoPlayer? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_exo_player) player = ExoPlayer.Builder(this).build().also { exoPlayer -> binding.playerView.player = exoPlayer val mediaItem = MediaItem.fromUri("https://example.com/sample.mp4") exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.playWhenReady = true } } override fun onStop() { super.onStop() player?.release() player = null } }

Tip: Use ExoPlayer for HLS/DASH streaming, playlists, and subtitles. Use VideoView or MediaPlayer only for simple local or single-URL playback.

3MediaPlayer

MediaPlayer is the core Android class for audio and video playback. It supports local files, content URIs, and HTTP streams with playback controls.

Full MediaPlayer controller

Kotlin — MediaPlayerHelper.ktclass MediaPlayerHelper(private val context: Context) { private var mediaPlayer: MediaPlayer? = null fun play(filePath: String, onPrepared: (() -> Unit)? = null) { release() mediaPlayer = MediaPlayer().apply { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) setDataSource(filePath) setOnPreparedListener { it.start() onPrepared?.invoke() } setOnCompletionListener { release() } prepareAsync() } } fun pause() { mediaPlayer?.pause() } fun resume() { mediaPlayer?.start() } fun stop() { mediaPlayer?.stop(); release() } fun seekTo(positionMs: Int) { mediaPlayer?.seekTo(positionMs) } fun getDuration(): Int = mediaPlayer?.duration ?: 0 fun getCurrentPosition(): Int = mediaPlayer?.currentPosition ?: 0 fun isPlaying(): Boolean = mediaPlayer?.isPlaying == true fun release() { mediaPlayer?.release() mediaPlayer = null } }

MediaPlayer states

Idle → Initialized → Prepared → Started ↔ Paused → Stopped → Released ↑ async prepare() or prepareAsync()

UI controls wired to MediaPlayer

Kotlin — Play / pause / seek barval helper = MediaPlayerHelper(this) binding.btnPlay.setOnClickListener { if (helper.isPlaying()) helper.pause() else helper.resume() } binding.btnLoad.setOnClickListener { helper.play("/storage/emulated/0/Music/song.mp3") { binding.seekBar.max = helper.getDuration() } } binding.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { if (fromUser) helper.seekTo(progress) } override fun onStartTrackingTouch(seekBar: SeekBar?) {} override fun onStopTrackingTouch(seekBar: SeekBar?) {} }) // Update seek bar periodically while playing lifecycleScope.launch { while (isActive) { if (helper.isPlaying()) { binding.seekBar.progress = helper.getCurrentPosition() } delay(500) } }

4Bluetooth Basics

Bluetooth enables short-range wireless communication with headphones, speakers, wearables, and IoT devices. Android supports Classic Bluetooth and Bluetooth Low Energy (BLE).

Manifest permissions (Android 12+)

XML — AndroidManifest.xml<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <uses-feature android:name="android.hardware.bluetooth" android:required="false" />

Check Bluetooth availability

Kotlin — BluetoothAdapterprivate val bluetoothAdapter: BluetoothAdapter? by lazy { val manager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager manager.adapter } fun isBluetoothSupported(): Boolean = bluetoothAdapter != null @SuppressLint("MissingPermission") fun isBluetoothEnabled(): Boolean = bluetoothAdapter?.isEnabled == true @SuppressLint("MissingPermission") fun requestEnableBluetooth() { if (!isBluetoothEnabled()) { val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) enableBluetoothLauncher.launch(enableIntent) } } private val enableBluetoothLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { Toast.makeText(this, "Bluetooth enabled", Toast.LENGTH_SHORT).show() } }

Classic vs BLE

TypeUse CaseAPI
Classic BluetoothAudio headsets, file transferBluetoothAdapter, BluetoothSocket
Bluetooth LE (BLE)Fitness bands, beacons, IoT sensorsBluetoothLeScanner, BluetoothGatt

5Bluetooth Pairing

Pairing establishes a trusted connection between devices. Apps can list bonded (paired) devices, scan for nearby devices, and initiate pairing.

List paired devices

Kotlin — Get bonded devices@SuppressLint("MissingPermission") fun getPairedDevices(): List<BluetoothDevice> { return bluetoothAdapter?.bondedDevices?.toList() ?: emptyList() } @SuppressLint("MissingPermission") fun displayPairedDevices() { val devices = getPairedDevices() val names = devices.map { "${it.name ?: "Unknown"} (${it.address})" } binding.tvPairedDevices.text = names.joinToString("\n") }

BLE scan for nearby devices

Kotlin — ScanCallback@SuppressLint("MissingPermission") fun startBleScan() { val scanner = bluetoothAdapter?.bluetoothLeScanner ?: return val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { val device = result.device val name = device.name ?: "Unknown" val rssi = result.rssi Log.d("BLE", "Found: $name (${device.address}) RSSI: $rssi") addDeviceToList(device) } override fun onScanFailed(errorCode: Int) { Log.e("BLE", "Scan failed: $errorCode") } } scanner.startScan(scanCallback) // Stop after 10 seconds Handler(mainLooper).postDelayed({ scanner.stopScan(scanCallback) }, 10_000) }

Pair with a device

Kotlin — Initiate pairing@SuppressLint("MissingPermission") fun pairDevice(device: BluetoothDevice) { when (device.bondState) { BluetoothDevice.BOND_BONDED -> Toast.makeText(this, "Already paired", Toast.LENGTH_SHORT).show() BluetoothDevice.BOND_BONDING -> Toast.makeText(this, "Pairing in progress...", Toast.LENGTH_SHORT).show() else -> device.createBond() } } // Listen for bond state changes private val bondReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == BluetoothDevice.ACTION_BOND_STATE_CHANGED) { val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) val state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE) when (state) { BluetoothDevice.BOND_BONDED -> Log.d("BT", "Paired with ${device?.name}") BluetoothDevice.BOND_NONE -> Log.d("BT", "Pairing failed or unpaired") } } } }

Note: On Android 12+, always request BLUETOOTH_CONNECT and BLUETOOTH_SCAN at runtime before accessing device names or starting scans.

6WiFi Connectivity

Monitor network connectivity with ConnectivityManager and NetworkCallback. Detect Wi-Fi, cellular, and offline states to adapt UI and queue requests.

Manifest permission

XML — AndroidManifest.xml<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />

Check current connectivity

Kotlin — Is device online?fun isNetworkAvailable(context: Context): Boolean { val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val network = cm.activeNetwork ?: return false val capabilities = cm.getNetworkCapabilities(network) ?: return false return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) } fun isWifiConnected(context: Context): Boolean { val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val network = cm.activeNetwork ?: return false val capabilities = cm.getNetworkCapabilities(network) ?: return false return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) }

NetworkCallback — listen for changes

Kotlin — Real-time connectivity monitorclass NetworkMonitor(private val context: Context) { private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager private val networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { Log.d("Network", "Connected") updateUi(connected = true) } override fun onLost(network: Network) { Log.d("Network", "Disconnected") updateUi(connected = false) } override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) { val isWifi = caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) val isCellular = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) val label = when { isWifi -> "Wi-Fi" isCellular -> "Mobile Data" else -> "Other" } Log.d("Network", "Transport: $label") } } fun register() { val request = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build() connectivityManager.registerNetworkCallback(request, networkCallback) } fun unregister() { connectivityManager.unregisterNetworkCallback(networkCallback) } private fun updateUi(connected: Boolean) { // Update banner, enable/disable sync, etc. } }

Use in Activity lifecycle

Kotlin — MainActivity.ktclass MainActivity : AppCompatActivity() { private lateinit var networkMonitor: NetworkMonitor override fun onStart() { super.onStart() networkMonitor = NetworkMonitor(this) networkMonitor.register() } override fun onStop() { networkMonitor.unregister() super.onStop() } }

Open Wi-Fi settings

Kotlin — Launch system Wi-Fi panelbinding.btnWifiSettings.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { startActivity(Intent(Settings.Panel.ACTION_WIFI)) } else { startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) } }

7Hands-On Exercises

1

Play a sound from res/raw/ on button click. Release MediaPlayer in onDestroy().

2

Build a simple music player with MediaPlayer: play, pause, seek bar, and duration display.

3

Play an online MP4 video using VideoView with MediaController (play/pause/seek).

4

Check if Bluetooth is supported and enabled. Prompt the user to enable Bluetooth if off.

5

List all paired Bluetooth devices in a RecyclerView with name and MAC address.

6

Run a 10-second BLE scan and display discovered devices in a list.

7

Implement a NetworkCallback that shows a banner when offline and hides it when Wi-Fi or mobile data returns.

8

Bonus: Disable the sync button when offline; re-enable automatically when NetworkCallback.onAvailable fires.

Media, Bluetooth & WiFi MCQ Practice

10 Basic MCQs 10 Advanced MCQs

10 Basic Media, Bluetooth & WiFi MCQs

1

MediaPlayer plays?

ASQL queries
BAudio and video media
CLayouts only
DGradle tasks
Explanation: Stream from URL, file, or resource — remember release().
2

ExoPlayer (Media3) advantage?

ASQL only
BDeprecated
CModern streaming with adaptive formats
DGPS only
Explanation: Google's extensible player — DASH, HLS, customization.
3

BluetoothAdapter.getDefaultAdapter()?

ARoom DB
BWiFi manager
CCamera API
DEntry to device Bluetooth radio
Explanation: Check null if device lacks Bluetooth.
4

BLUETOOTH_CONNECT permission on?

AAndroid 12+ for connecting paired devices
BNever needed
CAPI 1 only
DReplaces INTERNET
Explanation: Runtime permission for Bluetooth on modern Android.
5

WiFi state checked via?

ASQLite
BConnectivityManager / NetworkCapabilities
CSensorManager
DManifest only
Explanation: Register NetworkCallback for connectivity changes.
6

VideoView uses?

ARoom migration
BBluetooth pairing
CSimple video playback widget
DNotification channel
Explanation: Wraps MediaPlayer — ExoPlayer preferred for advanced apps.
7

Audio focus request?

AGradle only
BAutomatic always
CBanned
DAudioManager.requestAudioFocus for polite playback
Explanation: Pause when call or other app needs audio.
8

Pair Bluetooth device requires?

APermissions and user pairing flow
BRoot only
CNo UI
DFirebase token
Explanation: SCAN, CONNECT permissions depending on API level.
9

INTERNET permission for?

ABluetooth pair only
BNetwork streaming and API calls
CCamera
DVibration only
Explanation: Normal permission declared in manifest.
10

release() on MediaPlayer?

AStarts playback
BOptional never
CFrees native resources — call when done
DCreates notification
Explanation: Failure to release causes resource leaks.

10 Advanced Media, Bluetooth & WiFi MCQs

11

BLE (Bluetooth Low Energy)?

AClassic audio only
BGATT protocol for sensors/wearables
CWiFi replacement
DSQL sync
Explanation: Scan for BLE devices, connect GATT, read/write characteristics.
12

NetworkCallback vs deprecated NetworkInfo?

ASame
BNetworkInfo preferred
CNetworkCallback reactive API preferred
DBoth removed
Explanation: Use ConnectivityManager.registerDefaultNetworkCallback.
13

MediaSession integrates?

ARoom
BSQL only
CGPS
DMedia controls on lock screen and Bluetooth headsets
Explanation: MediaSessionCompat with ExoPlayer for system media controls.
14

Bluetooth LE scan needs?

ABLUETOOTH_SCAN + location on older APIs sometimes
BNothing
CCamera
DExact alarm
Explanation: Scan permission and scan filters for battery/privacy.
15

Adaptive streaming HLS?

AMediaPlayer only
BExoPlayer handles HLS segments
CNot on Android
DSQLite
Explanation: ExoPlayer/Media3 supports adaptive bitrate streaming.
16

WifiNetworkSpecifier (Android 10+)?

ABanned
BSilent connect always
CConnect to specific WiFi programmatically with user approval
DRoot only
Explanation: NetworkRequest with WifiNetworkSpecifier for local IoT setup flows.
17

AudioAttributes usage USAGE_MEDIA?

ASensor rate
BEncryption
CNetwork type
DTells system this is media playback
Explanation: Usage and content type affect volume and routing.
18

A2DP Bluetooth profile?

AStereo audio streaming to headphones
BFile transfer
CNetwork tethering only
DGPS
Explanation: Classic Bluetooth audio uses A2DP profile.
19

Metered network detection?

AAlways unmetered
BConnectivityManager isActiveNetworkMetered
CWiFi always metered
DImpossible
Explanation: Defer large downloads on metered connections.
20

MediaPlayer prepareAsync?

AIllegal
BSync block UI
CNon-blocking prepare with OnPreparedListener
DReplaces ExoPlayer
Explanation: prepareAsync for network streams to avoid ANR.
Click an option to select, then check answers.

Media, Bluetooth & WiFi Interview Q&A

15 topic-focused questions for interviews and revision.

1Play audio file with MediaPlayer.easy
Answer: MediaPlayer.create(context, R.raw.sound) or setDataSource; prepare; start; release in onDestroy.
2Why use ExoPlayer over MediaPlayer.medium
Answer: Better streaming, caching, customization, MediaSession integration, active development in Media3.
3Check if WiFi connected.easy
Answer: ConnectivityManager getNetworkCapabilities active network has TRANSPORT_WIFI.
4Bluetooth permissions Android 12+.hard
Answer: BLUETOOTH_SCAN, BLUETOOTH_CONNECT declared and requested; never need location for scan on 12+ if neverForLocation flag.
5Handle audio focus loss.medium
Answer: Pause playback in onAudioFocusChange when AUDIOFOCUS_LOSS; resume on gain.
6Stream video in app.medium
Answer: ExoPlayer with PlayerView, set MediaItem from URI, prepare, play.
7Pair classic Bluetooth device.medium
Answer: Enable Bluetooth, discover devices (deprecated scan patterns), bond via device picker intent or BluetoothDevice.createBond.
8Listen for network changes.medium
Answer: registerDefaultNetworkCallback object overriding onAvailable/onLost.
9MediaPlayer lifecycle.medium
Answer: Idle → Prepared → Started → Paused → Stopped → Released; error states need reset/release.
10BLE scan overview.hard
Answer: BluetoothLeScanner startScan with ScanCallback; filter by service UUID; connect GATT on result.
11Reduce data on metered WiFi/cellular.medium
Answer: Check isActiveNetworkMetered; defer uploads; lower streaming quality.
12VideoView limitations.easy
Answer: Less control than ExoPlayer; not ideal for adaptive streaming or complex UI.
13Media notification for background playback.hard
Answer: Foreground service with MediaStyle notification tied to MediaSession.
14Stop Bluetooth scan to save battery.medium
Answer: stopScan when done; use scan filters; avoid infinite scanning.
15Security on open WiFi.hard
Answer: Use HTTPS; certificate pinning for sensitive apps; warn user on captive portals.