Dengan mengintegrasikan Android SDK HappyOyster, Aplikasi Anda dapat memasuki dunia yang dihasilkan oleh AI secara real-time, menghadirkan pengalaman video interaktif real-time dalam tiga mode: Adventure (eksplorasi dunia), Directing (pengarahan real-time), dan Acting (bermain peran).
1. What You Can Do
- Mulai pengalaman (Travel): Masuk ke dunia yang siap dengan kredensial sekali pakai; SDK secara otomatis membangun koneksi video real-time.
- Pemutaran real-time: SDK mengembalikan View video yang Anda pasang ke dalam tata letak untuk memutar visual yang dihasilkan AI secara real-time.
- Real-time interaction:
- mode directing (directing): Kirim instruksi teks untuk menggerakkan alur cerita.
- acting: Kirim juga instruksi teks; jeda/lanjutkan tersedia; jangan putar ulang dan jangan gunakan
sendCommand. GunakanaspectRatiodari respons gabung untuk mengatur orientasi pemain (lihat §13 Adaptasi Mode). - mode adventure (adventure): Kirim perintah kontrol arah/sudut pandang/tindakan untuk berinteraksi dengan dunia.
- Kontrol proses: Jeda / lanjutkan (directing dan acting), mundur (hanya directing), akhiri (ketiga mode).
- Callback status dan error: Pantau status dan pengecualian pengalaman secara real-time melalui event listener.
2. Installation
Happy Oyster SDK (cn.happyoyster:opensdk) dipublikasikan di Maven Central; mesin komunikasi real-time yang mendasarinya (Alibaba Cloud ARTC) dipublikasikan di Alibaba Cloud Maven. Kedua repositori harus dideklarasikan.
Persyaratan Lingkungan
Item | Requirement |
|---|---|
minSdk | 24 (Android 7.0) dan lebih tinggi |
compileSdk | 36 |
JDK | Target bytecode JDK 11 (toolchain host: JDK 11 atau lebih tinggi direkomendasikan) |
Language | Kotlin (API coroutine |
ABI |
|
Network | Akses internet publik diperlukan |
settings.gradle.kts root proyek:
<version> di bawah ini dengan nomor versi yang tepat, dan tambahkan dependensi di modul build.gradle.kts:
com.aliyun.aio:AliVCSDK_ARTC gagal diresolusi.Permissions
Library SDK itu sendiri hanya mendeklarasikan INTERNET. Mesin komunikasi real-time secara otomatis menggabungkan sejumlah kecil izin tipe jaringan/Bluetooth/pengaturan audio; manifes library tidak menyertakan izin mikrofon atau kamera. Stream video adalah pemutaran khusus langganan, dan SDK tidak mengirim audio nyata ke sisi remote.
Host harus mendeklarasikan sendiri: Ketika targetSdk Anda adalah 33 atau lebih tinggi, Anda harus mendeklarasikan izin notifikasi di AndroidManifest.xml host (mesin komunikasi real-time menyertakan layanan latar depan):
sendCommand) — mendeklarasikan izin mikrofon disarankan: Perintah kontrol real-time mode petualangan menggunakan uplink yang dibawa oleh stream audio senyap yang menetapkan "identitas penerbit" lokal; SDK tidak merekam atau mengunggah audio asli Anda. RECORD_AUDIO bukanlah prasyarat mutlak untuk DataChannel—bahkan tanpanya, stream senyap tetap berdiri sebagai penerbit dan uplink biasanya tersedia. Namun, untuk stabilitas di berbagai perangkat, kami menyarankan bahwa, jika aplikasi Anda menggunakan sendCommand, Anda mendeklarasikan izin di host AndroidManifest.xml dan memintanya saat runtime sebelum memanggil.
105004: 105004 berarti saluran real-time belum siap / pengiriman gagal (misalnya interupsi DataChannel atau anomali saluran real-time). Ini bukanlah konsekuensi yang pasti dari izin yang hilang—ini tidak dipicu secara langsung oleh RECORD_AUDIO yang tidak diberikan. Mode pengarahan (sendInstruct) dan pemutaran video tidak terpengaruh. Jika aplikasi Anda tidak menggunakan mode petualangan, izin ini tidak diperlukan.
Untuk memangkas izin yang digabungkan, gunakan tools:node="remove".
3. Model Autentikasi
SDK tidak memperoleh atau menyegarkan token, sehingga tetap ringan. Autentikasi memiliki dua lapisan:
- API Key gateway Bailian (百炼): Disisipkan sebagai token Bearer oleh aplikasi Anda melalui
updateToken(token). SDK hanya menyimpan yang terbaru; SDK tidak menyimpannya secara permanen atau menyegarkannya, dan setelah Key berubah, Anda harus menyisipkannya kembali. Gateway mensyaratkan bahwa semua permintaan SDK, termasukstartTravel, menggunakan Bearer ini. Ketika Bearer Key kedaluwarsa atau tidak valid, SDK memunculkanSDKError(101002); dalam kasus ini, Anda harus mendapatkan kembali dan menyisipkan kembali Bearer Key (updateToken) alih-alih menukarkan tiket baru. Selama pengembangan / Demo, Anda dapat menggunakan API Key utama Bailian (百炼) Anda secara langsung sebagai Bearer (updateToken) agar alur dapat berjalan. Di lingkungan produksi, selalu beralih ke token berumur pendek yang diterbitkan oleh server Anda, dan jangan pernah menyertakan API Key berumur panjang ke dalam aplikasi yang didistribusikan. - Kredensial pengalaman satu kali
ticket: Dipertukarkan oleh server Anda melalui platform terbuka dan dikirimkan ke klien; hanya digunakan untuk satustartTravelsaja. Kredensial ini menjadi tidak valid setelah pengalaman berakhir (secara normal atau tidak normal) dan tidak dapat digunakan kembali. Error kredensial tingkat tiket diidentifikasi oleh kode server enam digit (misalnya,401010= tiket tidak valid / kedaluwarsa,401011= tiket sudah digunakan), yang diteruskan oleh SDK apa adanya.
SDKConfig.apiHost (berbentuk llm-xxxx.ap-southeast-1.maas.aliyuncs.com, disalin dari kolom "API Host" pada halaman API Key di konsol Bailian (百炼)) dan meneruskan SDKConfig.model yang wajib diisi dan tanpa nilai default (happyoyster-1.0-directing / happyoyster-1.0-acting / happyoyster-1.0-adventure, sesuai dengan entri Open API). SDK melengkapi URL permintaan sebagai https://{apiHost}/api/v2/apps/{model}/openapi/v1/{endpoint}, sehingga Anda tidak perlu menyusunnya sendiri.
Menghilangkan model saat membuat SDKConfig adalah kesalahan waktu kompilasi. Jika model kosong, initialize secara sinkron memunculkan SDKError(100002) (raw = "SDKConfig.model must not be blank"), tidak membuat atau mengganti runtime, dan tidak membuat permintaan jaringan. API Host, model, dan API Key yang disisipkan harus sesuai dengan akun, wilayah, dan otorisasi model yang dipersyaratkan, jika tidak, gateway biasanya mengembalikan AccessDenied (pada runtime ini dimunculkan sebagai SDKError(106003), dengan body AccessDenied asli tersedia di SDKError.raw; lihat baris 106003 pada tabel kode kesalahan Referensi API untuk daftar periksa pemecahan masalah). Untuk keamanan, kami sangat menyarankan klien untuk menyisipkan token berumur pendek yang diterbitkan oleh server Anda sebagai Bearer, alih-alih menyertakan API Key berumur panjang ke dalam aplikasi atau commit ke repositori kode.
4. Quick Start
5. Langganan Event & Penanganan Error
Gunakan onStatusChanged untuk menggerakkan state machine host dan membatasi kemampuan interaksi; gunakan onError untuk menerima error runtime secara seragam. Untuk antarmuka event dan kode error lengkap, lihat Referensi API Happy Oyster Android SDK.
Must
- Daftarkan listener segera setelah
HappyOyster.initialize(...)berhasil dikembalikan;addListener/removeListenerharus dipanggil setelahinitialize(memanggilnya sebelum inisialisasi akan melemparSDKError(100001)). - Gerbangkan pada
onStatusChanged(Running)—pemanggilan interaksi hanya diizinkan setelahrunning;sendCommandmode adventure hanya valid dalamrunning. - Tangani juga
onError; jangan hanya menangkapstartTravel. Error fatal juga mengakhiri pengalaman (lihat bagian kode error pada Referensi API).
- Panggil
removeListenerpada titik siklus hidup yang sesuai (sepertionDestroy) untuk menghindari kebocoran memori.
- Mendaftarkan listener secara berulang tanpa memanggil removeListener.
6. Mengirim Instruksi: sendInstruct dan sendCommand
sendInstruct (directing / acting)
sendInstruct digunakan dalam pengarahan dan akting untuk mengirimkan instruksi teks yang menggerakkan gambar; ini dapat dipanggil dalam status running atau paused. Dalam status jeda, SDK tidak melanjutkan secara otomatis—host memutuskan apakah akan memanggil resumeTravel terlebih dahulu dan kemudian mengirimkan instruksi (untuk detail kontrak seperti pembatasan dan validasi status, lihat Referensi API). creationModel dunia akting selalu Simple, sehingga batasan ScriptList hanya berlaku untuk pengarahan.
sendCommand (mode adventure)
sendCommand digunakan dalam mode petualangan (adventure) untuk mengirimkan perintah kontrol arah/sudut pandang/tindakan; ini hanya valid dalam running. SDK memiliki throttle latest-wins bawaan 42 ms (24 fps), sehingga host dapat memanggilnya pada frame rate game dan SDK akan menggabungkannya secara otomatis; tidak diperlukan pembatasan rate secara manual. Panggil sekali untuk tindakan satu kali. Untuk tindakan yang ditahan, terus panggil setiap frame saat ditahan dan kirimkan secara eksplisit satu reset None saat dilepaskan (untuk kontrak pembatasan dan penampilan kegagalan yang terperinci, lihat Referensi API).
Praktik yang disarankan: Dalam UI interaksi mode petualangan host, sediakan tiga titik masuk perintah independen (arah pergerakan + arah sudut pandang + interaksi tindakan), pertahankan nilai yang saat ini dipegang untuk setiap grup, dan kirimkan snapshot tiga bidang yang lengkap pada setiap panggilan. Gunakan "None" hanya untuk dimensi yang tidak aktif. Ketika input dari dimensi yang berbeda ditahan secara bersamaan, pertahankan dan kirimkan semua nilai aktif alih-alih mengatur ulang dimensi lain ke "None".
7. Jeda / Lanjutkan / Putar Ulang
Mode yang berlaku: jeda / lanjut berlaku untuk pengarahan dan akting, dan berperilaku identik pada keduanya (termasuk penghalang 3 detik di bawah ini); mundur hanya untuk pengarahan. Memanggil pauseTravel / resumeTravel / rewindTravel dalam mode petualangan ditolak oleh SDK dengan 103003. Selain itu, version yang dilaporkan oleh server harus berupa token v2 yang diperlukan oleh modenya (storyV2 untuk pengarahan, actingV2 untuk akting); jika tidak, jeda / lanjut akan mengembalikan 103002.
Jeda bersifat asinkron: Pengembalian dari metode pauseTravel hanya berarti telah diterima; jeda yang sebenarnya ditentukan oleh onStatusChanged(Paused). Antara "memanggil pauseTravel" dan "menerima panggilan balik Paused", host dapat menandai status pengalaman lokalnya sebagai pausing; hanya setelah menerima Paused Anda seharusnya mengizinkan pemanggilan resumeTravel atau rewindTravel yang bergantung pada status jeda.
Penghalang jeda→buka kembali internal SDK: setelah Paused diterima, host dapat memanggil resumeTravel / rewindTravel sesuai dengan kontrak. Jika panggilan jatuh di dalam jendela penyelesaian 3 detik setelah konfirmasi jeda, metode penangguhan SDK menunggu sisa waktu sebelum mengirimkan permintaan yang membuka kembali ruang real-time. Host tidak memerlukan penundaan jeda→lanjut ekstra, dan tidak ada penundaan yang ditambahkan setelah 3 detik berlalu secara alami.
Cooldown pemanggilan sisi host (direkomendasikan): Disarankan agar host menunda penerbitan pauseTravel lain dalam 3 s setelah resumeTravel berhasil dikembalikan, untuk menghindari peralihan yang terlalu sering. SDK itu sendiri tidak memberlakukan cooldown ini.
Mundur: rewindTravel hanya tersedia dalam status paused; setelah mundur, server melanjutkan secara otomatis dan SDK menyambungkan ulang RTC secara otomatis, tanpa perlu intervensi host. Urutan umum: pause → wait:paused → rewindTravel(sec). Detik mundur rewindToSec harus merupakan kelipatan dari 4 (misalnya, 4, 8, 12); nilai yang bukan kelipatan dibulatkan ke bawah oleh server (misalnya, 7→4), dan detik efektif yang sebenarnya ditentukan oleh resumedAtSec yang dikembalikan. Mundur hanya untuk pengarahan: memanggil rewindTravel dalam mode akting atau petualangan ditolak oleh SDK secara lokal dengan 103003, tanpa mengeluarkan permintaan HTTP apa pun; host sebaiknya menyembunyikan entri mundur alih-alih hanya mengaburkan tombol.
Untuk detail kontrak seperti semantik asinkron dan backoff percobaan ulang 3× (backoff resumeTravel sebesar 1 s / 2 s / 3 s), lihat Referensi API Happy Oyster Android SDK.
8. Logging
Tag Logcat SDK: HappyOysterSDK. SDK menyediakan dua jalur output log yang independen:
- Logcat bawaan (nonaktif secara default): SDK menulis ke Logcat hanya ketika
SDKConfig.logcatEnabled = true(defaultfalse, sepenuhnya senyap).SDKConfig.logLevelmemfilter level minimumnya;INFOdefault sudah membawa jangkar siklus hidup yang diperlukan untuk merekonstruksi sesi (inisialisasi, awal Travel / transisi status / akhir, gabung RTC / frame pertama). Turunkan keWARNuntuk error saja, atau tingkatkan keDEBUG/VERBOSEuntuk diagnosis yang lebih mendalam.logLeveltidak memengaruhilogHandler. - Panggilan balik host
logHandler(disarankan): menerima setiapLogRecorddari SDK (semua aliran data), sepenuhnya independen darilogLevel/logcatEnabled, dan dapat diteruskan ke sistem logging host sendiri (Logcat, file, platform crash, dll.). Panggilan balik harus cepat dan tidak memblokir serta tidak boleh memanggil kembali ke SDK; pengecualian yang dilemparkannya ditangkap secara senyap;LogRecord.messagedisamarkan dan tidak berisi token Bearer,ticket, atau token RTC dalam teks biasa.
travelId (yaitu encryptedTravelId) dalam log SDK dipancarkan secara utuh dan merupakan kunci sesi yang dikirim ke server — sertakan saat menyelidiki sesi atau mengajukan tiket untuk menyelaraskan log klien dan server. Setiap baris respons HTTP juga membawa requestId server (bidang reqId=, ditampilkan sebagai - jika tidak ada) untuk menentukan satu permintaan secara tepat; ID ini hanya muncul di log dan tidak pernah ditampilkan pada nilai pengembalian publik apa pun.
9. Siklus Hidup & Memori
- Panggil
initializediApplication.onCreate, satu kali secara global. - Inisialisasi ulang saat idle (misalnya untuk beralih wilayah API atau
model) menutup runtime idle sebelumnya dan mengatur ulang listener yang terdaftar serta status feature-gate; daftarkan ulang listener setelah metode ini kembali. Inisialisasi ulang ditolak dengan103004saat Travel sedang dimulai, aktif, atau berakhir: selalu tungguendTravel()terlebih dahulu. SDK tidak pernah membuang Travel yang aktif sebagai efek samping dariinitialize. - Pengalaman terikat pada siklus hidup host: panggil
endTraveldionDestroydariActivity/Fragment(atauonClearedViewModel) untuk memastikan koneksi dan sumber daya real-time dilepaskan. - Hapus View yang dikembalikan oleh
attachVideo()dari tata letak saat berakhir (container.removeAllViews()), dan panggilremoveListener. - SDK hanya menyimpan application context; demikian juga, jangan meneruskan Activity ke SDK.
10. Coroutines & Threading
- Method bisnis adalah
suspend; panggil dilifecycleScope/viewModelScopedari konteks coroutine mana pun. SDK mengoordinasikan status dan pekerjaan RTC pada dispatcher utamanya sementara HTTP tetap berada di luar main thread. - Jika coroutine pemanggil dibatalkan, SDK membatalkan permintaan HTTP yang sedang berjalan dari pemanggilan tersebut, jika ada, dan meneruskan
CancellationExceptiontanpa perubahan alih-alih mengonversinya keSDKError; jangan menangkap atau menelannya sebagai kegagalan operasional. Pembatalan tidak membatalkan permintaan yang telah diterima oleh server. - Panggil
attachVideo()dansendCommand()pada main thread; pemanggilan di luar main thread akan melemparIllegalStateExceptionsecara sinkron.
11. Manajemen Token
- Bearer API Key memiliki masa berlaku yang terbatas; disarankan untuk memastikan token masih baru sebelum memasuki pengalaman. Saat menerima
onError(101002)(token kedaluwarsa), dapatkan kembali Bearer Key dan panggilupdateToken—tidak perlu menukar dengan tiket baru.
12. Pemulihan Error
- Untuk error fatal: bersihkan status pengalaman saat ini (termasuk menghapus View video), beri tahu pengguna, dan izinkan memulai ulang.
- Untuk jitter jaringan (
106001) dan anomali layanan hulu sementara (106003): sejumlah terbatas percobaan ulang dapat dilakukan. 100002sinkron dari inisialisasi berartimodelkosong; berikan nama dan versi model yang lengkap, lalu inisialisasi ulang. Jikamodelyang tidak kosong memiliki nama atau versi yang salah, telah dihentikan, belum dipublikasikan, atau tidak diotorisasi, gateway biasanya mengembalikan AccessDenied, yang dipetakan ke106003; gunakanSDKError.rawdan verifikasi bahwamodel, API Host, API Key, akun, dan wilayah cocok.
13. Adaptasi Mode
- Gunakan
modeyang dikembalikan olehstartTraveluntuk memutuskan kemampuan interaksi mana yang akan diekspos: directing dan acting menggunakan instruksi tekssendInstruct(acting juga menggunakanaspectRatiountuk orientasi pemain dan menyembunyikan putar ulang); mode adventure menggunakan perintah kontrolsendCommand. - Dalam mode petualangan, Anda dapat menggunakan overload
startTravel(ticket, maxExperienceTimeSec)untuk membatasi durasi maksimum pengalaman ini (detik; sesi berakhir secara otomatis saat tercapai). Nilai yang diizinkan dikonfigurasi oleh server (saat ini60/90/120, default60); pengarahan dan akting mengabaikan nilai tersebut (server mengabaikannya dan menggemakannull). Meneruskan nilai yang tidak didukung membuat server mengembalikan400000dan awal ini gagal. Lihat Referensi API untuk detail parameter.
acting: Mengatur Orientasi Pemain dari aspectRatio
StartTravelData.aspectRatio bukan null hanya untuk akting: "9:16" (potret, default sisi server saat dunia dibuat) atau "16:9" (lanskap); nilainya null untuk petualangan dan pengarahan. Kanvas ditetapkan saat dunia dibuat (ditentukan oleh server Anda melalui Open API), sehingga bagi klien ini adalah hasil baca-saja. SDK mempertahankan nilai yang tidak dikenali apa adanya, sehingga host harus memperlakukan nilai apa pun yang tidak dikenalnya seperti null dan kembali ke orientasi defaultnya sendiri.
Waktu: tentukan orientasi kontainer pemutaran setelah startTravel() kembali dan sebelum memanggil attachVideo() serta memasang SurfaceView yang dikembalikan ke dalam tata letak Anda. SDK hanya mulai mengikat dan merender stream jarak jauh setelah tampilan host dilampirkan, sehingga menentukan orientasi pada titik tersebut masih mendahului frame yang dirender pertama kali. Nilai ini dikirimkan bersama nilai pengembalian startTravel() dan tidak dijamin tiba sebelum SDK bergabung dengan saluran komunikasi real-time — nilai ini hanya harus diterapkan sebelum attachVideo().
Konsekuensi: remote view terikat dengan mode render clip-to-fill — container yang orientasinya tidak sesuai dengan aspectRatio akan memotong gambar (misalnya, stream potret 9:16 yang ditempatkan dalam container 16:9 akan kehilangan sebagian besar bagian atas dan bawahnya) alih-alih memberinya letterbox.
startTravel gagal dengan 403007 (ditolak sebelum Travel dibuat), yang diteruskan oleh SDK apa adanya. Jangan mencoba ulang kode ini sebagai kapasitas penuh; minta pengguna untuk meminta pengaktifan sebagai gantinya.14. Contoh Lengkap (Snippet ViewModel + Activity)
15. Panduan Pemecahan Masalah DevOps
Ketika terjadi kesalahan selama integrasi (tidak dapat memasuki Travel, layar hitam tanpa video, stream terputus di tengah sesi, anomali jeda/lanjutkan, ...), membuka log SDK adalah cara tercepat untuk melokalisasi masalah. Bab ini memberikan alur pemecahan masalah standar — berguna baik untuk pemeriksaan mandiri Anda maupun untuk memberikan kami informasi yang cukup dalam satu putaran.
15.1 Mengaktifkan log
Pilih output log sesuai kebutuhan saat memecahkan masalah (lihat §8 Logging): untuk pemeriksaan mandiri cepat, atur logcatEnabled = true dan baca dengan adb logcat, tingkatkan logLevel ke DEBUG atau VERBOSE saat mendiagnosis (INFO default sudah membawa linimasa siklus hidup penuh; turunkan ke WARN untuk error saja); untuk memasukkan ke sistem Anda sendiri, gunakan logHandler untuk menerima setiap LogRecord (tidak terpengaruh oleh logLevel) dan tulis ke file atau platform crash Anda.
15.2 ID korelasi sesi: travelId
travelId (yaitu StartTravelData.encryptedTravelId) dalam log SDK diemisikan secara lengkap. Ini adalah satu-satunya identifier yang berjalan melalui satu sesi dan kunci sesi yang dikirim ke server. Ini adalah kunci untuk menyelaraskan log klien dengan catatan sesi sisi server — selalu sertakan travelId dari sesi yang gagal saat melaporkan masalah.
15.3 Mengumpulkan log
Saat mereproduksi masalah, simpan log SDK ke dalam file:
15.4 Apa yang perlu disertakan saat melaporkan masalah
Untuk menghindari beberapa kali bolak-balik komunikasi, harap lampirkan hal berikut:
Item | Notes |
|---|---|
SDK version |
|
Session |
|
Time of occurrence | perkiraan waktu (tingkat menit sudah cukup) |
Kode error |
|
Reproduction steps | jalur tindakan + hasil yang diharapkan + hasil aktual |
Environment | model perangkat, versi Android, jaringan (WiFi/seluler) |
Log file | log |
15.5 Tentang penyuntingan dan kemampuan berbagi log
Log SDK dirancang agar aman untuk dibagikan: kredensial (token Bearer, tiket Travel, token RTC), pengenal internal RTC, dan URL media disamarkan sebelum ditulis, sehingga tidak pernah muncul dalam teks biasa; travelId adalah pengenal sesi (bukan kredensial) dan disimpan secara utuh hanya untuk korelasi. Meskipun demikian, kami menyarankan untuk mentransfer file log melalui saluran tepercaya daripada menempelkannya secara publik di platform yang tidak terkendali.