如何无需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:
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.
First, set up your project with the required dependencies and permissions:
- 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' }
- 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" />
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) } }
- 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_AUDIOpermission 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

