Penjelasan tentang cara memulai cepat
Apa yang Twilio lakukan?
Itu melakukan semua pekerjaan berat dalam mengelola pengguna di sebuah ruangan dan mengirimkan trek video dan audio di antara mereka. Pada dasarnya yang perlu kita lakukan hanyalah…
- Siapkan UI dan lingkungan untuk koneksi
- Menangani acara pengguna
Cara menggunakan Video yang Dapat Diprogram Twilio
Segala sesuatu di artikel ini diambil dari dokumentasi Twilio dan proyek mulai cepat.
Pertama kita tambahkan SDK Twilio yang disediakan. Ini mencakup semua fungsi dan objek yang diperlukan.
// inside our app's build.gradle // Twilio video sdk implementation 'com.twilio:video-android:$version'
Atur tampilan tampilan
Kami kemudian dapat menggunakan videoView dari SDK untuk menampilkan video di layar
import com.twilio.video.VideoView;
Versi xmlnya adalah
<com.twilio.video.VideoView
android:id="@+id/primary_video_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:keepScreenOn="true"
/>
dan versi kodenya adalah
VideoView v = new VideoView(context);
v.setKeepScreenOn(true);
Jaga agar perangkat tetap terjaga
Perhatikan saya memasang atribut setKeepScreenon karena kemungkinan besar kita tidak ingin ponsel tertidur selama panggilan video. Sangat mudah bahwa keepScreenOn
dapat digunakan dengan tampilan anak mana pun dan akan bekerja dengan cara yang sama seperti pada tampilan induk.
Menghubungkan ke Ruangan
Buat Token Akses
Setiap pengguna diharuskan menggunakan Token Akses untuk terhubung ke suatu ruangan. Ini unik untuk setiap pengguna di setiap ruang pertemuan. Langkah ini biasanya dilakukan di backend.
// taken from
https://www.twilio.com/docs/iam/access-tokens?code-sample=code-creating-an-access-token-video-2&code-language=Java&code-sdk-version=7.ximport com.twilio.jwt.accesstoken.AccessToken; import com.twilio.jwt.accesstoken.VideoGrant; public class TokenGenerator { public static void main(String[] args) { // Required for all types of tokens String twilioAccountSid = "ACxxxxxxxxxxxx"; String twilioApiKey = "SKxxxxxxxxxxxx"; String twilioApiSecret = "xxxxxxxxxxxxxx"; // Required for Video String identity = "user"; // Create Video grant VideoGrant grant = new VideoGrant().setRoom("cool room"); // Create access token AccessToken token = new AccessToken.Builder( twilioAccountSid, twilioApiKey, twilioApiSecret ).identity(identity).grant(grant).build(); System.out.println(token.toJwt()); } }
Kemudian di aplikasi front end kita, kita dapat terhubung ke ruangan menggunakan token akses. RoomName sudah ditentukan saat membuat token akses, jadi argumen di sini tidak akan memengaruhi ruangan mana yang sebenarnya akan kita sambungkan.
// taken from https://www.twilio.com/docs/video/android-getting-started public void connectToRoom(String roomName) { ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken) .roomName(roomName) .audioTracks(localAudioTracks) .videoTracks(localVideoTracks) .dataTracks(localDataTracks) .build(); room = Video.connect(context, connectOptions, roomListener); }
Buat trek video dan audio lokal
Agar connectToRoom()
berfungsi, Kita perlu membagikan video dan suara kita kepada peserta lain melalui trek.
private void createAudioAndVideoTracks() { // Share your microphone localAudioTrack = LocalAudioTrack.create(this, true, LOCAL_AUDIO_TRACK_NAME); // Share your camera cameraCapturerCompat = new CameraCapturerCompat(this, getAvailableCameraSource()); localVideoTrack = LocalVideoTrack.create(this, true, cameraCapturerCompat.getVideoCapturer(), LOCAL_VIDEO_TRACK_NAME); primaryVideoView.setMirror(true); localVideoTrack.addRenderer(primaryVideoView); localVideoView = primaryVideoView; }
Minta izin untuk mikrofon dan kamera
Dalam manifes kita, kita akan membutuhkan semua ini.
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Lalu akhirnya kami bisa memeriksa dan meminta izin.
private boolean checkPermissionForCameraAndMicrophone() { int resultCamera = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA); int resultMic = ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO); return resultCamera == PackageManager.PERMISSION_GRANTED && resultMic == PackageManager.PERMISSION_GRANTED; } private void requestPermissionForCameraAndMicrophone() { // request permission in fragment requestPermissions( new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, CAMERA_MIC_PERMISSION_REQUEST_CODE); }
Dan kita perlu menangkap peristiwa tersebut ketika izin diberikan
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == CAMERA_MIC_PERMISSION_REQUEST_CODE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED ) { Toast.makeText(context, "Permission granted", Toast.LENGTH_LONG).show(); } }
Menangani Acara Pengguna
Twilio akan melaporkan kejadian seperti peserta terhubung, terputus melalui panggilan balik. Kita harus menyediakan antarmuka roomListener()
saat kita terhubung ke sebuah ruangan.
Selain mengatur pendengar untuk ruangan tersebut, kita juga harus memasang pendengar untuk setiap peserta di ruangan tersebut. Pendengar ini akan melacak status video dan audio peserta tertentu.
Kita dapat melihat metode lengkap untuk panggilan balik ini dengan membaca contoh memulai cepat Twilio.
Di bawah ini adalah contoh untuk roomListener()
, yang ingin kita lakukan di sini adalah segera setelah onConnected()
dipanggil, kita mengumpulkan semua peserta dalam ruangan dan melampirkan remoteParticipantListener()
ke masing-masing peserta.
Tentu saja, kita juga perlu melampirkan pendengar ke setiap peserta yang bergabung dalam ruangan tersebut di masa mendatang.
private Room.Listener roomListener() { return new Room.Listener() { @Override public void onConnected(Room room) { Toast.makeText(MainActivity.this, "Connected to room " + room.getName(), Toast.LENGTH_LONG).show(); localParticipant = room.getLocalParticipant(); List<RemoteParticipant> remoteParticipants = room.getRemoteParticipants(); for (RemoteParticipant remoteParticipant : remoteParticipants) { addRemoteParticipant(remoteParticipant); } // adding the participant does not mean their video track is ready to be subscribed // display the videos in the onVideoTrackSubscribed callback } @Override public void onParticipantConnected(Room room, RemoteParticipant remoteParticipant) { addRemoteParticipant(remoteParticipant); } @Override public void onParticipantDisconnected(Room room, RemoteParticipant remoteParticipant) { removeRemoteParticipant(remoteParticipant); } }
Karena ini adalah antarmuka Java, kita harus menyelesaikan semua metode yang diperlukan. Namun untungnya nama metodenya cukup jelas dan logika untuk menampilkan dan menghapus video peserta dari UI sangatlah mudah.
Di bawah ini adalah contoh panggilan balik remoteParticipantListener()
. Ingat ini adalah pendengar untuk setiap peserta, jadi perbarui tampilan yang benar untuk peserta yang benar.
// add listener to each participant when you joined a room @SuppressLint("SetTextI18n") private RemoteParticipant.Listener remoteParticipantListener() { return new RemoteParticipant.Listener() { @Override public void onAudioTrackPublished(RemoteParticipant remoteParticipant, RemoteAudioTrackPublication remoteAudioTrackPublication) { Log.i(TAG, String.format("onAudioTrackPublished: " + "[RemoteParticipant: identity=%s], " + "[RemoteAudioTrackPublication: sid=%s, enabled=%b, " + "subscribed=%b, name=%s]", remoteParticipant.getIdentity(), remoteAudioTrackPublication.getTrackSid(), remoteAudioTrackPublication.isTrackEnabled(), remoteAudioTrackPublication.isTrackSubscribed(), remoteAudioTrackPublication.getTrackName())); } @Override public void onAudioTrackUnpublished(RemoteParticipant remoteParticipant, RemoteAudioTrackPublication remoteAudioTrackPublication) { Log.i(TAG, String.format("onAudioTrackUnpublished: " + "[RemoteParticipant: identity=%s], " + "[RemoteAudioTrackPublication: sid=%s, enabled=%b, " + "subscribed=%b, name=%s]", remoteParticipant.getIdentity(), remoteAudioTrackPublication.getTrackSid(), remoteAudioTrackPublication.isTrackEnabled(), remoteAudioTrackPublication.isTrackSubscribed(), remoteAudioTrackPublication.getTrackName())); } ......
Bersihkan dan lepaskan sumber daya
Terakhir ingatlah untuk menangani penyambungan kembali dan pemutusan hubungan sesuai dengan siklus hidup aktivitas kita.
Jika beberapa aplikasi lain dengan prioritas lebih tinggi mengganggu aplikasi kita atau pengguna mematikan layar secara manual dengan mengklik tombol daya, kita harus memutuskan sambungan dari ruangan. Karena pengguna mungkin tidak kembali dan Twilio akan terus menghitung menit layanan dan menagih uang.
Oleh karena itu, metode onPause() kita harus meminimalkan pemutusan sambungan dari ruangan dan melepaskan sumber daya kamera dan mikrofon ponsel kita.
@Override public void onPause(){ super.onPause(); /* * Release the local video track before going in the background. This ensures that the * camera can be used by other applications while this app is in the background. */ if (localVideoTrack != null) { /* * If this local video track is being shared in a Room, unpublish from room before * releasing the video track. Participants will be notified that the track has been * unpublished. */ if (localParticipant != null) { localParticipant.unpublishTrack(localVideoTrack); } localVideoTrack.release(); localVideoTrack = null; } /* * Always disconnect from the room before leaving the Activity to * ensure any memory allocated to the Room resource is freed. */ if (room != null && room.getState() != Room.State.DISCONNECTED) { room.disconnect(); clearVideoDisplays(); } |
Dan di onResume()
kami akan menghubungkan kembali pengguna ke ruangan jika pengguna kembali ke aktivitas kami.
Cara mengeluarkan suara ke perangkat yang berbeda
Jika pengguna memasang bug telinga atau terhubung ke headphone Bluetooth, aplikasi kita perlu mendeteksi peristiwa ini dan merutekan trek suara ke perangkat itu.
Perpustakaan AudioSwitch Twilio memungkinkan kita melakukan itu.
Perpustakaan akan secara otomatis memilih perangkat berdasarkan prioritas berikut: BluetoothHeadset -> WiredHeadset -> Earpiece -> Speakerphone
.
Jika kami melakukan aplikasi konferensi video, kami lebih memilih speaker ponsel daripada lubang suara. Kita dapat mengatur urutan prioritas di konstruktor.
List<Class<? extends AudioDevice>> preferredDevices = new ArrayList<>(); preferredDevices.add(BluetoothHeadset.class); preferredDevices.add(WiredHeadset.class); preferredDevices.add(Speakerphone.class); AudioSwitch audioSwitch = new AudioSwitch(context, false, focusChange -> {}, preferredDevices);
- buat objek audioSwitch dengan daftar prioritas
- daftarkan panggilan balik audioSwitch.start() sebelum panggilan aktif
- panggil audioSwitch.activate() saat connectToRoom
- panggil audioSwitch.deactive() saat terputus dari ruangan
- panggil audioSwitch.stop() di onDestroy()
Cara mengubah layar menjadi hitam ketika peserta lain menonaktifkan videonya
Anda mungkin memperhatikan layar Anda akan menampilkan bingkai terakhir peserta lain yang dibekukan saat dia menonaktifkan videonya. Cara yang lebih ideal untuk menangani hal ini adalah dengan menampilkan layar hitam.
Saya tidak menemukan pengaturan apa pun untuk mengubah layar menjadi hitam secara otomatis. Jadi akhirnya saya membuat tata letak batasan dengan latar belakang disetel menjadi hitam. Awalnya tandai visibilitasnya ke GONE, dan ketika peserta menonaktifkan panggilan balik video, saya mengatur tampilan kembali ke Terlihat untuk menutupi bingkai terakhir yang dibekukan.
Cara mendeteksi speaker utama
Suatu saat kita mungkin ingin menanggapi seorang pembicara. Seperti menempatkan video peserta yang berbicara saat ini ke jendela utama.
Twilio memberi kami pengaturan enableDominantSpeaker
untuk mendeteksi peristiwa ini.
Lihat https://www.twilio.com/docs/video/detecting-dominant-speaker untuk mengaktifkan pengaturan ini di connectOptions.
Sekarang kita memiliki onDominantSpeakerChanged
panggilan balik.
Bagaimana menghindari mendengar gema
Saya memang mengalami masalah gema audio antara Samsung dan iPhone. Seorang pengguna akan mendengar suaranya kembali dari perangkat.
Menerapkan pengaturan yang disarankan dari https://github.com/twilio/video-quickstart-android#troubleshooting-audio memperbaiki masalah ini.