Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Building an Android audio player app is best done with Kotlin, Jetpack Media3, ExoPlayer, and MediaSessionService. This architecture supports local or HTTPS audio, playlists, seeking, background playback, lock-screen and notification controls, Bluetooth commands, audio focus, and activity recreation without making the Activity own the playback engine.

This tutorial builds a production-shaped minimum viable player: one Activity or Compose screen, a playlist of Media3 MediaItem objects, a background playback service, a media notification, and controls for play, pause, seek, previous, next, repeat, and shuffle.

The first implementation deliberately avoids accounts, cloud catalogs, subscriptions, and a complete music-library scanner. Those features can be added after the playback architecture works reliably.

Key takeaways

  • Jetpack Media3 ExoPlayer is the recommended default for this Android audio player app because it supports playlists, seeking, buffering, streaming, and extensibility.
  • A player that must continue when the screen is locked should keep ExoPlayer and MediaSession inside a MediaSessionService declared with the mediaPlayback foreground-service type.
  • The Activity should connect to the service with MediaController instead of creating a second ExoPlayer instance.
  • MediaItem metadata supplies the title, artist, album, artwork, and queue information used by notifications, lock-screen controls, Bluetooth devices, and other media clients.
  • Apps targeting Android API 35 or higher must account for stricter audio-focus rules, while Android 17 introduces additional background-audio hardening.

What will this Android audio player app include?

The completed minimum viable player will contain an Activity or Compose screen with a title, artist, artwork or placeholder, play/pause, a seek bar, elapsed and remaining time, previous and next buttons, repeat, shuffle, and an optional queue screen.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A separate playback service will own ExoPlayer and MediaSession. The service will expose playback through a media notification and system controls while the visible UI acts as a controller. The queue will initially contain a small set of local or remote tracks.

Product type What it requires Scope of this tutorial
Simple player One file or a fixed playlist and basic controls Yes
Local music player MediaStore, file selection, permissions, artwork, and library scanning Extension
Streaming player HTTPS media, buffering, authentication, caching, and possibly adaptive streaming Basic remote playback
Podcast or audiobook player Resume position, chapters, downloads, and variable speed Extension
Music service Catalog infrastructure, accounts, rights management, recommendations, and billing Not part of the first release

Why use Kotlin, Media3 ExoPlayer, and MediaSessionService?

Kotlin with Jetpack Media3 is the recommended modern implementation for this project. Media3 ExoPlayer is the default implementation of the Player interface and provides playlist management, seeking, buffering, track information, streaming support, and extension points. See the official Media3 ExoPlayer documentation.

The legacy android.media.MediaPlayer API can still be suitable for a very small app that plays one local file, but it is a poor default for a modern streaming player with queues, downloads, media sessions, and robust background behavior.

Use MediaSessionService when the app mainly exposes a playback queue and controls. Use MediaLibraryService later if Android Auto or another client must browse a hierarchical catalog such as albums, artists, playlists, or downloads. The MediaLibraryService documentation describes the additional browsing and search callbacks.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What do you need before starting?

Install Android Studio, the official Android IDE, and create a standard AndroidX application using Kotlin. You also need an Android emulator or physical device and either an app-bundled audio file or an HTTPS stream that you are legally allowed to use.

Useful Kotlin knowledge includes classes and interfaces, coroutines and ListenableFuture, lifecycle-aware UI, and basic Gradle usage. Device manufacturers can impose additional battery-management restrictions, so background playback must be tested on both an emulator and a physical device.

Media3 versions change. Do not copy an old version number into a new project. Before publishing, record the Android Studio release, compile SDK, target SDK, Media3 version, and device/API levels tested. Use the current stable Media3 version recommended by the official documentation or Android Studio dependency suggestions, and use the same version for every Media3 module.

How do you add the Media3 dependencies?

In the app module’s Gradle file, add ExoPlayer and the session library. Add the UI library only if you use Media3’s PlayerView.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
dependencies {
    implementation("androidx.media3:media3-exoplayer:<current-version>")
    implementation("androidx.media3:media3-session:<current-version>")
    implementation("androidx.media3:media3-ui:<current-version>") // If using PlayerView
}

Replace <current-version> with the current compatible stable version. Keep all Media3 artifacts on the same version unless the official release guidance explicitly says otherwise. Continue using the project’s normal AndroidX, Activity, lifecycle, Compose, or Views dependencies.

How do you play your first audio file?

Start with a minimal player before adding a service. This isolates URL, codec, output, and dependency problems.

val player = ExoPlayer.Builder(context).build()

val mediaItem = MediaItem.fromUri(
    "https://your-domain.example/audio/sample.mp3"
)

player.setMediaItem(mediaItem)
player.prepare()
player.play()

Use an author-controlled HTTPS URL or a legally distributable sample file. Do not embed an arbitrary third-party URL that may disappear or that you do not have permission to stream.

Call Purpose
setMediaItem() Loads one item into the player.
setMediaItems() Loads a playlist.
prepare() Prepares the media source for playback.
play() Starts or resumes playback.
pause() Pauses without clearing the queue.
seekTo() Moves to a specified position.
release() Frees the player’s resources.

The expected result is audible playback and a changing position. If playback fails, check the URL, HTTPS redirects, the server’s media type, range-request support, device volume, mute state, Bluetooth routing, and Logcat for Media3 playback exceptions. Supported formats depend on Media3, platform decoders, containers, codecs, and the device; ExoPlayer does not support every audio format on every device.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do you create a playlist with metadata?

Use MediaItem metadata rather than displaying filenames. Metadata becomes important later because the notification, lock screen, Bluetooth controls, and external media clients use the same session information.

val items = listOf(
    MediaItem.Builder()
        .setUri("https://your-domain.example/audio/track-1.mp3")
        .setMediaId("track-1")
        .setMediaMetadata(
            MediaMetadata.Builder()
                .setTitle("Track One")
                .setArtist("Example Artist")
                .setAlbumTitle("Example Album")
                .build()
        )
        .build(),
    MediaItem.Builder()
        .setUri("https://your-domain.example/audio/track-2.mp3")
        .setMediaId("track-2")
        .setMediaMetadata(
            MediaMetadata.Builder()
                .setTitle("Track Two")
                .setArtist("Example Artist")
                .setAlbumTitle("Example Album")
                .build()
        )
        .build()
)

player.setMediaItems(items)
player.prepare()

A queue has a current item, a current index, a playback position, repeat mode, and shuffle mode. The Media3 Player interface documentation covers queue operations, position queries, seeking, repeat, shuffle, speed, volume, and playback state.

player.play()
player.pause()
player.seekTo(30_000L)
player.skipToNext()
player.skipToPrevious()
player.repeatMode = Player.REPEAT_MODE_ALL
player.shuffleModeEnabled = true

Define the previous-button behavior explicitly. A common product rule is to seek to zero when the current track has progressed beyond a threshold; otherwise, move to the previous queue item. Do not assume every player’s previous-button behavior matches your desired UX.

Why should playback move into a MediaSessionService?

Playback belongs in a MediaSessionService when it must continue after the Activity is hidden, recreated, or no longer visible. The service owns the player and session; the Activity connects to that existing session.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
class PlaybackService : MediaSessionService() {

    private var mediaSession: MediaSession? = null

    override fun onCreate() {
        super.onCreate()

        val player = ExoPlayer.Builder(this)
            .build()

        mediaSession = MediaSession.Builder(this, player)
            .build()
    }

    override fun onGetSession(
        controllerInfo: MediaSession.ControllerInfo
    ): MediaSession? {
        return mediaSession
    }

    override fun onDestroy() {
        mediaSession?.let { session ->
            session.player.release()
            session.release()
        }
        mediaSession = null

        super.onDestroy()
    }
}

The official playback-app implementation guide recommends creating the player and session in onCreate(), returning the session from onGetSession(), and releasing both in onDestroy(). Releasing the player and session exactly once prevents leaks and conflicting playback engines.

Activity or Compose UI
        |
        | MediaController
        v
MediaSessionService
        |
        +-- MediaSession
        |
        +-- ExoPlayer
                |
                +-- MediaItem queue
                +-- Audio focus
                +-- Notification and system controls
                +-- Local or remote media source

An Activity-owned player may work for a short demonstration, but it is the wrong default for lock-screen playback. Activity recreation, screen locking, external controllers, and process lifecycle changes become much harder when the Activity owns the playback state.

What manifest declarations does background playback require?

For a current background-playback implementation, declare the generic foreground-service permission, the media-playback-specific permission, and a service whose foreground-service type is mediaPlayback.

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission
    android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">

    <intent-filter>
        <action
            android:name="androidx.media3.session.MediaSessionService" />
    </intent-filter>
</service>

The official background-playback documentation lists both permissions and requires a service type that includes mediaPlayback. The MediaSessionService reference also notes that apps targeting API level 28 or higher must request FOREGROUND_SERVICE to make the service foreground.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If the app must be discoverable by clients using the platform or legacy browser interface, add the optional action:

<action android:name="android.media.browse.MediaBrowserService" />

Do not treat the manifest as a way to bypass Android background restrictions. Start playback through an allowed user-initiated path, inspect target-SDK behavior, and follow the current platform documentation.

How does the Activity connect with MediaController?

The Activity should build a MediaController from a SessionToken and release the asynchronous controller future when the Activity stops.

private var controllerFuture: ListenableFuture<MediaController>? = null
private var mediaController: MediaController? = null

override fun onStart() {
    super.onStart()

    val sessionToken = SessionToken(
        this,
        ComponentName(this, PlaybackService::class.java)
    )

    controllerFuture = MediaController.Builder(this, sessionToken)
        .buildAsync()

    controllerFuture?.addListener(
        {
            mediaController = controllerFuture?.get()
            // With Views, attach it to a PlayerView:
            // playerView.player = mediaController
        },
        ContextCompat.getMainExecutor(this)
    )
}

override fun onStop() {
    mediaController = null
    controllerFuture?.let { MediaController.releaseFuture(it) }
    controllerFuture = null

    super.onStop()
}

MediaController implements the Player interface, so familiar calls work through the service:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
mediaController?.play()
mediaController?.pause()
mediaController?.seekTo(30_000L)
mediaController?.skipToNext()
mediaController?.skipToPrevious()

Follow the lifecycle pattern in the official Media3 playback guide. The Activity must not construct a second independent ExoPlayer. Two players can compete for audio focus, show inconsistent state, and produce duplicate notifications.

With Jetpack Compose, keep the service-bound controller in a lifecycle-aware state holder or ViewModel rather than storing it directly in a composable. Collect playback state while the screen is active and cancel collection when the lifecycle stops.

How do you build the player controls?

For a Views-based prototype, Media3’s PlayerView provides a quick control surface. A polished audio-only UI will usually need custom controls because a generic video-oriented surface may not match the desired design.

For Compose, observe isPlaying, currentPosition, duration, and currentMediaItem. Button handlers should invoke controller methods, while the seek bar should update at a controlled interval rather than on every recomposition.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
mediaController?.let { controller ->
    playButton.setOnClickListener {
        if (controller.isPlaying) controller.pause() else controller.play()
    }

    nextButton.setOnClickListener { controller.skipToNext() }
    previousButton.setOnClickListener { controller.skipToPrevious() }
    shuffleButton.setOnClickListener {
        controller.shuffleModeEnabled = !controller.shuffleModeEnabled
    }
    repeatButton.setOnClickListener {
        controller.repeatMode = when (controller.repeatMode) {
            Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ALL
            Player.REPEAT_MODE_ALL -> Player.REPEAT_MODE_ONE
            else -> Player.REPEAT_MODE_OFF
        }
    }
}

A lifecycle-aware coroutine can periodically read the controller position, update elapsed time, and stop polling when the UI is inactive. Avoid a blocking loop in the UI thread. Show a loading state while a remote item buffers and an explicit error state such as “Unable to load this track” with Retry, Skip, or Remove actions.

How do notifications and lock-screen controls work?

MediaSession connects player state and metadata to Android’s external media controls. Media3 can provide a default media-style notification through a MediaSessionService; the result still depends on metadata, permissions, OS behavior, and whether the app supplies a custom notification provider. See the Media3 media-session control documentation.

Set complete metadata for each item, including title, artist, album, artwork URI or bitmap when available, duration, queue position, and supported actions. Test the notification shade, lock screen, Bluetooth headset buttons, wired headset controls where available, Android Auto or other relevant clients, rotation, and playback after the Activity is swiped away.

Every device and Bluetooth accessory does not expose every control. OEM lock screens and accessory behavior vary, so document the devices tested instead of promising identical controls everywhere.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How should the app handle audio focus and interruptions?

A serious audio player must respond appropriately when another app requests audio focus. The player may pause or duck during calls, navigation prompts, alarms, or other transient audio, and it should respond to headphone disconnection.

Test at least these cases:

  • Start another music app and observe whether the player pauses or ducks.
  • Start a navigation prompt and verify that speech is not made unintelligible.
  • Receive a phone call and verify that playback does not resume unexpectedly.
  • Disconnect Bluetooth headphones and verify the product’s chosen pause behavior.
  • Switch between speaker, wired output, and Bluetooth where supported.

Media3 can cover ordinary playback interactions, but custom audio-focus behavior may still be needed for the product’s interruption and resume rules. For apps targeting API level 35 or higher, an app cannot request audio focus unless it is the top app or is running a foreground service. A failed request returns AUDIOFOCUS_REQUEST_FAILED, according to the AudioFocusRequest reference. Android versions, audio outputs, and OEM implementations can produce different ducking and interruption behavior.

What changed for Android 15 and Android 17?

Target SDK matters. Android 15/API 35 introduces stricter audio-focus conditions for apps targeting API 35 or later, so background playback should use the documented foreground-service architecture. Android 17/API 37 documentation describes additional background-audio hardening for apps targeting Android 17 or higher. Consult the Android 17 behavior changes before release.

Because platform policies evolve, record these values in the article or project README:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Android Studio release and release channel;
  • compile SDK and target SDK;
  • Media3 version;
  • minimum supported API;
  • emulator and physical-device API levels tested;
  • device manufacturers tested for background restrictions.

Do not use undocumented workarounds to defeat foreground-service or background-audio restrictions.

How do you support local audio files?

The safest first demonstration uses an app-bundled resource or Android’s Storage Access Framework with ACTION_OPEN_DOCUMENT. A user-selected document can be retained with persistable URI permission when the app needs access after a restart; temporary access and persisted access are different.

A full local music library is a separate feature. It may require MediaStore indexing, runtime permissions, scoped-storage handling, artwork extraction, duplicate detection, and recovery when files are deleted or moved. Large libraries and unsupported codecs also require careful testing.

Do not request broad storage permissions merely to demonstrate one selected file. Start with bundled content or the system file picker, then add library scanning only when the product needs it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How should remote streaming handle failures?

Use HTTPS for remote media and show meaningful buffering and error states. A remote URL can expire, redirect, require headers, reject range requests, return the wrong content type, or disappear. A successful URL test today does not make the URL permanent.

When preparation fails, distinguish a malformed URL, an unreachable server, an unsupported codec, and an authorization failure in logs or diagnostics. The visible UI can use a safe message such as “Unable to load this track,” with Retry, Skip to next, or Remove unavailable item actions.

Do not assume every MP3 server supports seeking. Use adaptive streaming when the product requires quality changes, and use a cache for repeated playback or offline support. Never expose private signed URLs in logs or analytics.

How do downloads differ from caching?

A cache used to improve playback is not automatically a user-visible offline download. Offline playback requires downloading content, retaining it, decoding it locally, and having the legal and technical right to keep and play it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Media3 provides download APIs including DownloadManager, DownloadIndex, DownloadService, schedulers, and cache integration. The Media3 downloading documentation covers these building blocks.

A production download feature should expose progress, pause, resume, cancel, retry, and delete actions. Decide whether downloads require Wi-Fi, charging, or sufficient free storage. Also plan for expired or revoked content, encryption, DRM, duplicate downloads, and foreground-service requirements for download work. Downloading arbitrary streaming content may not be technically or legally permissible.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How do you persist playback state and resume later?

A useful player can persist the current media ID, queue, current index, position, repeat mode, shuffle mode, and whether the user intentionally paused. Store durable state in Room or another appropriate persistence layer, and save meaningful changes rather than writing to storage every millisecond.

Restore state only when the user expects resumption. Clear the queue when the user deliberately discards it, and distinguish process death from an explicit Stop action. The Media3 background-playback guidance treats playback resumption as an extension of the service lifecycle.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What security and rights issues must the app address?

  • Use HTTPS-only media URLs.
  • Never hard-code API secrets in the APK.
  • Handle authenticated requests with secure token storage and short-lived credentials where appropriate.
  • Validate server responses and fail safely when content is unavailable.
  • Request only the permissions required for the selected feature.
  • Disclose analytics, listening history, and data retention in the privacy documentation.
  • Obtain copyright and licensing rights for bundled and streamed audio.
  • Use the required DRM and entitlement system for protected catalogs.
  • Protect downloaded files and remove them when the user requests deletion.

How do you test the Android audio player app?

Test the queue, service, lifecycle, interruptions, network, and device matrix rather than only the happy path.

Area Tests
Playback Play, pause, seek, next, previous, end-of-item transition, repeat-one, repeat-all, shuffle, empty queue, one-item queue, corrupt media, unsupported format, network loss, and recovery.
Lifecycle Rotate, background and foreground, lock and unlock, swipe away the Activity, kill and relaunch the process, and reconnect the controller.
Audio output Speaker, wired headset where available, Bluetooth connection and disconnection, output switching, calls, and navigation prompts.
Service Verify service startup, notification appearance, appropriate foreground behavior, exactly-once cleanup, and the absence of duplicate service declarations.
Devices At least one current emulator, one physical device, one older supported API, portrait and landscape, and battery-saver or restricted-background conditions.

Use the Gradle wrapper commands generated by the project:

./gradlew assembleDebug
./gradlew test
./gradlew connectedAndroidTest

On Windows, use:

gradlew.bat assembleDebug
gradlew.bat test
gradlew.bat connectedAndroidTest

connectedAndroidTest requires a connected device or a running emulator. assembleDebug normally places a debug APK under the module’s build/outputs/apk/ directory, while test produces local unit-test results. Module names and custom build configurations can change exact output paths.

What are the most common failures?

Symptom Likely cause Fix
Audio works only while the app is open The Activity still owns ExoPlayer. Move ExoPlayer and MediaSession into MediaSessionService.
ForegroundServiceStartNotAllowedException Background start, incomplete declarations, or target-SDK restrictions. Start from an allowed user action, use the documented service pattern, and inspect the exact target-SDK exception.
No notification Service did not start correctly, permissions or type are missing, or playback never began. Check the service declaration, permissions, mediaPlayback type, notification behavior, and Logcat.
Notification metadata is poor MediaItem metadata or artwork is missing. Set title, artist, album, artwork, duration, queue information, and supported actions.
UI stops updating The UI created a separate player or failed to connect its controller. Connect to the service’s MediaSession and collect state with lifecycle cancellation.
Playback restarts after rotation The Activity reconstructs the player. Reconnect the Activity to the existing MediaController.
Audio-focus request fails For API 35+ targets, the app is neither topmost nor running an eligible foreground service. Verify the audio-focus and foreground-service conditions.
Playback continues after the user expects Stop Pause, Stop, and service destruction were not given separate semantics. Add an explicit Stop action and define when the service releases or leaves the foreground.

What should you add after the first working player?

Add features in response to the product rather than building an entire music service before validating playback.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Local files: add Storage Access Framework selection first, then MediaStore indexing if a full library is needed.
  • Downloads: add Media3 download APIs, progress, storage policy, cancellation, and rights enforcement.
  • Resume: persist queue and position in Room or another durable store.
  • Browsable catalog: move to MediaLibraryService when external clients need root discovery, child browsing, or search.
  • Backend: add authentication, catalog APIs, signed URLs, analytics, and cloud storage only when remote content requires them.
  • Distribution: use Google Play Console for testing and release management after privacy, licensing, identity, and policy requirements are ready.

Google Play’s official registration guidance states a one-time US$25 registration fee. Publishing is not the same as approval; identity verification, testing requirements for some personal accounts, policy compliance, privacy disclosures, and content rights also apply.

Firebase can be useful for Crashlytics, Analytics, App Distribution, Remote Config, Cloud Messaging, authentication, or a backend catalog. It is unnecessary for a self-contained local player. Check the Firebase Android setup documentation and current Firebase pricing and quotas before enabling services, because billing, privacy, retention, and product-specific limits vary.

A streaming product may additionally need object storage, a CDN, signed URLs, range-request support, bandwidth monitoring, transcoding, DRM, or entitlement enforcement. Choose those services only after separate cost, region, bandwidth, and codec research.

Production checklist

  • Player and MediaSession are service-owned and released exactly once.
  • The Activity reconnects through MediaController and never creates a duplicate player.
  • Foreground-service permissions and the mediaPlayback service type match the target SDK.
  • MediaItem metadata appears correctly in the notification and lock screen.
  • Audio focus, calls, navigation prompts, headset removal, and Bluetooth changes have been tested.
  • Network, codec, range-request, authentication, and expired-URL failures have recovery paths.
  • Local-file permissions are limited to the chosen access method.
  • Downloads, caching, DRM, and offline rights are treated as separate features.
  • Queue, position, repeat, shuffle, and intentional pause state have clear persistence rules.
  • Audio content is legally licensed and user data is disclosed and protected.
  • Android Studio, compile SDK, target SDK, Media3 version, and tested devices are documented.

Frequently Asked Questions

Should an Android audio player use MediaPlayer or ExoPlayer?

Use Jetpack Media3 ExoPlayer as the default for a modern Android audio player with streaming, playlists, buffering, background playback, and media controls. Platform MediaPlayer remains reasonable for a narrow single-file or legacy compatibility case.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How does Android audio continue when the screen is locked?

Keep ExoPlayer and MediaSession in a MediaSessionService declared as a mediaPlayback foreground service, then connect the Activity through MediaController. Android background-start rules, target SDK requirements, battery restrictions, and user force-stop behavior still apply.

Why is the audio-player notification missing?

Check that the MediaSessionService is declared correctly, both applicable foreground-service permissions are present, the service type is mediaPlayback, playback actually started, and notification behavior is not being suppressed by custom provider code or device settings.

Can this Android audio player play local files offline?

Yes, but local playback and a complete music library are different features. Start with an app-bundled file or ACTION_OPEN_DOCUMENT, then add persisted URI access, MediaStore indexing, permissions, artwork, missing-file recovery, and codec handling as needed.

The Bottom Line

The dependable foundation for an Android audio player app is Kotlin, Jetpack Media3 ExoPlayer, MediaSession, and a service-owned playback lifecycle. Make one queue play correctly first, then add metadata, background controls, audio focus, persistence, downloads, catalogs, and backend services only when the product requires them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.