You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需Google Home App,通过代码实现Android屏幕完整镜像到Chromecast

Hey Ezekiel, nice question! If you want to replicate that full Android screen mirroring functionality (the exact same "cast your Android screen" feature from Google Home) via code without relying on the app, here's a practical, step-by-step breakdown using Google's Cast SDK and Android's built-in media projection tools:

Core Concept

Under the hood, Google Home's screen mirroring uses the Google Cast SDK paired with Android's MediaProjection API. The workflow is straightforward: capture your device's screen/audio stream, encode it, and push it to a connected Chromecast device. We'll replicate this directly in code.

Prerequisites

First, set up your project with the required dependencies and permissions:

  1. Add the Cast SDK dependency to your app-level build.gradle (Module):
dependencies {
    implementation 'com.google.android.gms:play-services-cast-framework:21.3.0'
}
  1. Declare necessary permissions in your AndroidManifest.xml:
<!-- For audio capture and foreground service -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- Required for Cast SDK configuration -->
<meta-data
    android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.yourpackage.YourCastOptionsProvider" />
Step-by-Step Implementation

1. Initialize Cast Context

First, create a custom CastOptionsProvider to enable screen casting support, and initialize the Cast Context in your Application class:

CastOptionsProvider Class

package com.yourpackage

import android.content.Context
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.SessionProvider
import com.google.android.gms.cast.framework.media.CastMediaControlIntent
import com.google.android.gms.cast.framework.screencast.CastScreenProvider

class YourCastOptionsProvider : OptionsProvider {
    override fun getCastOptions(context: Context): CastOptions {
        return CastOptions.Builder()
            // Use the default media receiver (works for screen mirroring)
            .setReceiverApplicationId(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID)
            .build()
    }

    override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
        // Enable screen casting support
        val screenProvider = CastScreenProvider(context)
        return listOf(screenProvider)
    }
}

Application Class Initialization

package com.yourpackage

import android.app.Application
import com.google.android.gms.cast.framework.CastContext

class YourApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // Initialize Cast Context once when the app starts
        CastContext.getSharedInstance(this)
    }
}

Don't forget to update your AndroidManifest.xml to use this application class:

<application
    android:name=".YourApplication"
    ...>
    <!-- Other components -->
</application>

2. Request Screen Capture Permission

Android requires user consent to capture the screen. We'll use MediaProjectionManager to request this permission:

import android.content.Intent
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.Toast

class MirroringActivity : AppCompatActivity() {
    private val REQUEST_CODE_SCREEN_CAPTURE = 1001
    private lateinit var mediaProjectionManager: MediaProjectionManager
    private var mediaProjection: MediaProjection? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_mirroring)
        
        mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        // Trigger permission request when your UI button is clicked
        val startMirrorButton = findViewById<Button>(R.id.start_mirror_button)
        startMirrorButton.setOnClickListener {
            requestScreenCapturePermission()
        }
    }

    private fun requestScreenCapturePermission() {
        val captureIntent = mediaProjectionManager.createScreenCaptureIntent()
        startActivityForResult(captureIntent, REQUEST_CODE_SCREEN_CAPTURE)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE_SCREEN_CAPTURE && resultCode == RESULT_OK) {
            data?.let {
                mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, it)
                // Now connect to Chromecast and start mirroring
                connectToChromecastAndStartMirroring()
            }
        } else {
            Toast.makeText(this, "Screen capture permission denied", Toast.LENGTH_SHORT).show()
        }
    }
}

3. Connect to Chromecast & Start Mirroring

Use the Cast SDK's SessionManager to discover and connect to a Chromecast device, then start screen mirroring:

import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManagerListener

class MirroringActivity : AppCompatActivity() {
    // ... previous code ...
    
    private lateinit var castContext: CastContext
    private var castSession: CastSession? = null
    private lateinit var sessionManagerListener: SessionManagerListener<CastSession>

    override fun onCreate(savedInstanceState: Bundle?) {
        // ... previous onCreate code ...
        
        castContext = CastContext.getSharedInstance(this)
        setupCastSessionListener()
    }

    private fun setupCastSessionListener() {
        sessionManagerListener = object : SessionManagerListener<CastSession> {
            override fun onSessionStarted(session: CastSession, sessionId: String) {
                castSession = session
                // Session connected, start mirroring
                startScreenMirroring()
            }

            override fun onSessionEnded(session: CastSession, error: Int) {
                castSession = null
                Toast.makeText(this@MirroringActivity, "Disconnected from Chromecast", Toast.LENGTH_SHORT).show()
            }

            // Implement other optional callbacks as needed
            override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {}
            override fun onSessionSuspended(session: CastSession, reason: Int) {}
            override fun onSessionStarting(session: CastSession) {}
            override fun onSessionEnding(session: CastSession) {}
        }
        castContext.sessionManager.addSessionManagerListener(sessionManagerListener, CastSession::class.java)
    }

    private fun connectToChromecastAndStartMirroring() {
        // Launch Google's default Cast device picker dialog
        val castDialogIntent = castContext.sessionManager.startSessionDialogIntent
        startActivityForResult(castDialogIntent, 1002)
    }

    private fun startScreenMirroring() {
        castSession?.let { session ->
            mediaProjection?.let { projection ->
                session.startScreenCapture(projection)
                    .addOnSuccessListener {
                        runOnUiThread {
                            Toast.makeText(this, "Screen mirroring started!", Toast.LENGTH_SHORT).show()
                        }
                    }
                    .addOnFailureListener { exception ->
                        runOnUiThread {
                            Toast.makeText(this, "Failed to start mirroring: ${exception.message}", Toast.LENGTH_LONG).show()
                        }
                    }
            }
        }
    }

    // Add a method to stop mirroring when needed
    private fun stopScreenMirroring() {
        castSession?.stopScreenCapture()
        mediaProjection?.stop()
        mediaProjection = null
        castSession = null
        Toast.makeText(this, "Screen mirroring stopped", Toast.LENGTH_SHORT).show()
    }

    override fun onDestroy() {
        super.onDestroy()
        stopScreenMirroring()
        castContext.sessionManager.removeSessionManagerListener(sessionManagerListener, CastSession::class.java)
    }
}
Important Notes
  • Foreground Service Requirement: For Android 8.0+, you need to run the screen capture in a foreground service to prevent the system from killing your app while mirroring. Add a foreground service with a persistent notification.
  • Audio Capture: If you want to mirror audio along with the screen, ensure you request the RECORD_AUDIO permission dynamically (Android 6.0+).
  • Device Compatibility: Make sure the target Chromecast device supports screen mirroring (all modern Chromecasts do, but older models may not). Your Android device needs to be running Android 5.0+.
  • Error Handling: Add robust error handling for cases like permission denial, Chromecast disconnection, or unsupported devices.

内容的提问来源于stack exchange,提问作者Ezekiel Baniaga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:44:23