Bagikan melalui


Aktifkan pemutaran audio dari perangkat yang terhubung dengan Bluetooth jarak jauh

Artikel ini menunjukkan kepada Anda cara menggunakan AudioPlaybackConnection untuk mengaktifkan perangkat jarak jauh yang terhubung dengan Bluetooth untuk memutar kembali audio di komputer lokal.

Dimulai dengan Windows 10, sumber audio jarak jauh versi 2004 dapat mengalirkan audio ke perangkat Windows, memungkinkan skenario seperti mengonfigurasi PC agar berperilaku seperti speaker Bluetooth dan memungkinkan pengguna mendengar audio dari ponsel mereka. Implementasi menggunakan komponen Bluetooth di OS untuk memproses data audio masuk dan memutarnya di titik akhir audio sistem pada sistem seperti speaker PC bawaan atau headphone kabel. Pengaktifan sink Bluetooth A2DP yang mendasarinya dikelola oleh aplikasi, yang bertanggung jawab atas skenario pengguna akhir, bukan oleh sistem.

Kelas AudioPlaybackConnection digunakan untuk mengaktifkan dan menonaktifkan koneksi dari perangkat jarak jauh serta untuk membuat koneksi, memungkinkan pemutaran audio jarak jauh dimulai.

Menambahkan antarmuka pengguna

Untuk contoh dalam artikel ini, kami akan menggunakan antarmuka pengguna XAML sederhana berikut yang menentukan kontrol ListView untuk menampilkan perangkat jarak jauh yang tersedia, TextBlock untuk menampilkan status koneksi, dan tiga tombol untuk mengaktifkan, menonaktifkan, dan membuka koneksi.

<Grid x:Name="MainGrid" Loaded="MainGrid_Loaded">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Connection state: "/>
        <TextBlock x:Name="ConnectionState" Grid.Row="0" Text="Disconnected."/>
    </StackPanel>
    <ListView x:Name="DeviceListView" ItemsSource="{x:Bind devices}" Grid.Row="1">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="enumeration:DeviceInformation">
                <StackPanel Orientation="Horizontal" Margin="6">
                    <SymbolIcon Symbol="Audio" Margin="0,0,12,0"/>
                    <StackPanel>
                        <TextBlock Text="{x:Bind Name}" FontWeight="Bold"/>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <StackPanel Orientation="Vertical" Grid.Row="2">
        <Button x:Name="EnableAudioPlaybackConnectionButton" Content="Enable Audio Playback Connection" Click="EnableAudioPlaybackConnectionButton_Click"/>
        <Button x:Name="ReleaseAudioPlaybackConnectionButton" Content="Release Audio Playback Connection" Click="ReleaseAudioPlaybackConnectionButton_Click"/>
        <Button x:Name="OpenAudioPlaybackConnectionButtonButton" Content="Open Connection" Click="OpenAudioPlaybackConnectionButtonButton_Click" IsEnabled="False"/>
    </StackPanel>
     
</Grid>

Menggunakan DeviceWatcher untuk memantau perangkat jarak jauh

Kelas DeviceWatcher memungkinkan Anda mendeteksi perangkat yang terhubung. Metode AudioPlaybackConnection.GetDeviceSelector mengembalikan string yang memberi tahu pengamat perangkat jenis perangkat yang harus diwaspadai. Teruskan string ini ke konstruktor DeviceWatcher .

Peristiwa DeviceWatcher.Added dinaikkan untuk setiap perangkat yang terhubung saat pengamat perangkat dimulai serta untuk perangkat apa pun yang terhubung saat pengamat perangkat berjalan. Peristiwa DeviceWatcher.Removed dinaikkan jika perangkat yang terhubung sebelumnya terputus.

Panggil DeviceWatcher.Start untuk mulai menonton perangkat yang terhubung yang mendukung koneksi pemutaran audio. Dalam contoh ini kita akan memulai manajer perangkat ketika kontrol Grid utama di UI dimuat. Untuk informasi selengkapnya tentang menggunakan DeviceWatcher, lihat Menghitung Perangkat.

private void MainGrid_Loaded(object sender, RoutedEventArgs e)
{
    audioPlaybackConnections = new Dictionary<string, AudioPlaybackConnection>();

    // Start watching for paired Bluetooth devices. 
    this.deviceWatcher = DeviceInformation.CreateWatcher(AudioPlaybackConnection.GetDeviceSelector());

    // Register event handlers before starting the watcher. 
    this.deviceWatcher.Added += this.DeviceWatcher_Added;
    this.deviceWatcher.Removed += this.DeviceWatcher_Removed;

    this.deviceWatcher.Start();
}

Dalam peristiwa Ditambahkan pengamat perangkat, setiap perangkat yang ditemukan diwakili oleh objek DeviceInformation. Tambahkan setiap perangkat yang ditemukan ke koleksi yang dapat diamati yang terikat ke kontrol ListView di UI.

private ObservableCollection<Windows.Devices.Enumeration.DeviceInformation> devices =
    new ObservableCollection<Windows.Devices.Enumeration.DeviceInformation>();

private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
{
    // Collections bound to the UI are updated in the UI thread. 
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
    {
        this.devices.Add(deviceInfo);
    });
}

Mengaktifkan dan merilis koneksi pemutaran audio

Sebelum membuka koneksi dengan perangkat, koneksi harus diaktifkan. Ini menginformasikan sistem bahwa ada aplikasi baru yang ingin audio dari perangkat jarak jauh diputar di PC, tetapi audio tidak mulai diputar sampai koneksi dibuka, yang ditampilkan di langkah selanjutnya.

Di penangan klik untuk tombol Aktifkan Koneksi Pemutaran Audio, dapatkan ID perangkat yang terkait dengan perangkat yang saat ini dipilih di kontrol ListView . Contoh ini mempertahankan kamus objek AudioPlaybackConnection yang telah diaktifkan. Metode ini pertama-tama memeriksa untuk melihat apakah sudah ada entri dalam kamus untuk perangkat yang dipilih. Selanjutnya, metode mencoba membuat AudioPlaybackConnection untuk perangkat yang dipilih dengan memanggil TryCreateFromId dan meneruskan ID perangkat yang dipilih.

Jika koneksi berhasil dibuat, tambahkan objek AudioPlaybackConnection baru ke kamus aplikasi, daftarkan handler untuk peristiwa StateChanged objek, dan panggilStartAsync untuk memberi tahu sistem bahwa koneksi baru diaktifkan.

private Dictionary<String, AudioPlaybackConnection> audioPlaybackConnections;
private async void EnableAudioPlaybackConnectionButton_Click(object sender, RoutedEventArgs e)
{
    if (! (DeviceListView.SelectedItem is null))
    {
        var selectedDeviceId = (DeviceListView.SelectedItem as DeviceInformation).Id;
        if (!this.audioPlaybackConnections.ContainsKey(selectedDeviceId))
        {
            // Create the audio playback connection from the selected device id and add it to the dictionary. 
            // This will result in allowing incoming connections from the remote device. 
            var playbackConnection = AudioPlaybackConnection.TryCreateFromId(selectedDeviceId);

            if (playbackConnection != null)
            {
                // The device has an available audio playback connection. 
                playbackConnection.StateChanged += this.AudioPlaybackConnection_ConnectionStateChanged;
                this.audioPlaybackConnections.Add(selectedDeviceId, playbackConnection);
                await playbackConnection.StartAsync();
                OpenAudioPlaybackConnectionButtonButton.IsEnabled = true;
            }
        }
    }
}

Buka koneksi pemutaran audio

Pada langkah sebelumnya, koneksi pemutaran audio dibuat, tetapi suara tidak mulai diputar hingga koneksi dibuka dengan memanggil Buka atau OpenAsync. Di tombol Buka Koneksi Pemutaran Audio klik handler, dapatkan perangkat yang saat ini dipilih dan gunakan ID untuk mengambil AudioPlaybackConnection dari kamus koneksi aplikasi. Tunggu panggilan ke OpenAsync dan centang nilai Status objek AudioPlaybackConnectionOpenResultStatus yang dikembalikan untuk melihat apakah koneksi berhasil dibuka dan, jika demikian, perbarui kotak teks status koneksi.

private async void OpenAudioPlaybackConnectionButtonButton_Click(object sender, RoutedEventArgs e)
{
    var selectedDevice = (DeviceListView.SelectedItem as DeviceInformation).Id;
    AudioPlaybackConnection selectedConnection;

    if (this.audioPlaybackConnections.TryGetValue(selectedDevice, out selectedConnection))
    {
        if ((await selectedConnection.OpenAsync()).Status == AudioPlaybackConnectionOpenResultStatus.Success)
        {
            // Notify that the AudioPlaybackConnection is connected. 
            ConnectionState.Text = "Connected";
        }
        else
        {
            // Notify that the connection attempt did not succeed. 
            ConnectionState.Text = "Disconnected (attempt failed)";
        }
    }
}

Memantau status koneksi pemutaran audio

Peristiwa AudioPlaybackConnection.ConnectionStateChanged dinaikkan setiap kali status koneksi berubah. Dalam contoh ini, handler untuk kejadian ini memperbarui kotak teks status. Ingatlah untuk memperbarui UI di dalam panggilan ke Dispatcher.RunAsync untuk memastikan pembaruan dilakukan pada utas UI.

private async void AudioPlaybackConnection_ConnectionStateChanged(AudioPlaybackConnection sender, object args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        if (sender.State == AudioPlaybackConnectionState.Closed)
        {
            ConnectionState.Text = "Disconnected";
        }
        else if (sender.State == AudioPlaybackConnectionState.Opened)
        {
            ConnectionState.Text = "Connected";
        }
        else
        {
            ConnectionState.Text = "Unknown";
        }
    });
}

Rilis koneksi dan tangani perangkat yang dihapus

Contoh ini menyediakan tombol Rilis Koneksi Pemutaran Audio untuk memungkinkan pengguna merilis koneksi pemutaran audio. Di handler untuk kejadian ini, kita mendapatkan perangkat yang saat ini dipilih dan menggunakan ID perangkat untuk mencari AudioPlaybackConnection di kamus. Panggil Buang untuk merilis referensi dan membebaskan sumber daya terkait dan menghapus koneksi dari kamus.


private void ReleaseAudioPlaybackConnectionButton_Click(object sender, RoutedEventArgs e)
{
    // Check if an audio playback connection was already created for the selected device Id. If it was then release its reference to deactivate it. 
    // The underlying transport is deactivated when all references are released. 
    if (!(DeviceListView.SelectedItem is null))
    {
        var selectedDeviceId = (DeviceListView.SelectedItem as DeviceInformation).Id;
        if (audioPlaybackConnections.ContainsKey(selectedDeviceId))
        {
            AudioPlaybackConnection connectionToRemove = audioPlaybackConnections[selectedDeviceId];
            connectionToRemove.Dispose();
            this.audioPlaybackConnections.Remove(selectedDeviceId);

            // Notify that the media device has been deactivated. 
            ConnectionState.Text = "Disconnected";
            OpenAudioPlaybackConnectionButtonButton.IsEnabled = false;
        }
    }
}

Anda harus menangani kasus di mana perangkat dihapus saat koneksi diaktifkan atau terbuka. Untuk melakukan ini, terapkan handler untuk peristiwa DeviceWatcher.Removed pengamat perangkat. Pertama, ID perangkat yang dihapus digunakan untuk menghapus perangkat dari koleksi yang dapat diamati yang terikat ke kontrol ListView aplikasi. Selanjutnya, jika koneksi yang terkait dengan perangkat ini ada di kamus aplikasi, Buang dipanggil untuk membebaskan sumber daya terkait dan kemudian koneksi dihapus dari kamus. Semua ini dilakukan dalam panggilan ke Dispatcher.RunAsync untuk memastikan pembaruan UI dilakukan pada utas UI.

private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
    // Collections bound to the UI are updated in the UI thread. 
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        // Find the device for the given id and remove it from the list. 
        foreach (DeviceInformation device in this.devices)
        {
            if (device.Id == deviceInfoUpdate.Id)
            {
                this.devices.Remove(device);
                break;
            }
        }

        if (audioPlaybackConnections.ContainsKey(deviceInfoUpdate.Id))
        {
            AudioPlaybackConnection connectionToRemove = audioPlaybackConnections[deviceInfoUpdate.Id];
            connectionToRemove.Dispose();
            this.audioPlaybackConnections.Remove(deviceInfoUpdate.Id);
        }
    });
}

Pemutaran Media