Bỏ qua để đến nội dung
VLivev1.1.2

04 — API Reference

Tài liệu tham chiếu đầy đủ các API thuộc package vn.interactive của SDK Interactive Android.

Xem Markdown

Tất cả API dưới đây thuộc package gốc vn.interactive.

class OverlayManager(
activity: Activity, // phải là FragmentActivity/AppCompatActivity
overlayView: OverlayView, // view trong layout, phủ vùng video
overlayData: OverlayData, // cấu hình môi trường + tenant
overlayEventListener: OverlayEventListener? = null
) : OnOverlayListener, LifecycleOverlay
Thành phầnKiểuMô tả
valueTimePlayInt (chỉ đọc)Giây phát gần nhất mà app đã bơm vào qua receiveTrackingTime
receiveTrackingTime(Int) -> UnitBơm thời gian phát (giây) cho luồng VOD. Gọi như hàm: overlayManager.receiveTrackingTime(12)
HàmMô tảGhi chú
initToken(token: String, userId: String, bjName: String = "")Khai báo/xoá phiên đăng nhậpGọi trước joinRoom. Đăng xuất: initToken("", ""). Nếu đang Live sẽ tự vào lại phòng
joinRoom(mediaId: String, type: Int)Bắt đầu phiên tương tác cho một nội dungtype = 1 LIVE, type = 2 VOD. Tự cleanUp() phiên cũ
releaseAll()Giải phóng toàn bộ: socket, WebView, dialog, trackingGọi ở onDestroy() hoặc khi thoát nội dung
fetchInteractiveStatus(mediaId: String, callback: (Boolean) -> Unit)Hỏi server nội dung này có tương tác khôngLỗi mạng → trả false
showChartsInteractive(mediaId: String, userId: String, backgroundColorHeader: String? = null)Mở bảng xếp hạng (DialogFragment toàn màn hình)backgroundColorHeader là mã hex, ví dụ "#139DED"
hideChartsInteractive()Đóng bảng xếp hạng
isDialogCharShowing(): BooleanBảng xếp hạng có đang hiển thị không
addPlayerListener(listener: PlayerChangeListener)Cấp trạng thái player cho SDK (phục vụ sự kiện ckst)Gọi sau joinRoom để listener được gắn cả vào socket
sendAction(data: JSONObject)(implement OnOverlayListener) Xử lý hành động từ WebViewSDK tự gọi, app không cần gọi
onClickAdsOverlay(url: String)(implement OnOverlayListener) Mở URL quảng cáo bằng trình duyệt ngoàiSDK tự gọi

LifecycleOverlay hiện là interface rỗng (các hàm onResume/onStop/onDestroy đã được comment trong mã) — SDK không tự bám vòng đời Activity ngoài việc observe LiveData.

val overlayData = OverlayData.Builder()
.setEnvironment(EnvInteractive.PROD) // mặc định PROD
.setTenantId("vtvlive") // mặc định "" — nên luôn set
.setDebug(false) // mặc định false
.build()
Thuộc tínhKiểuMặc địnhẢnh hưởng
envInteractiveEnvInteractivePRODURL socket, URL REST, URL bảng xếp hạng
tenantIdString""Header X-TENANT-ID (socket + REST), query BXH, luật đăng nhập của tenant vtvlive
debugBooleanfalseCờ dự phòng, hiện chưa đổi hành vi log (log phụ thuộc BuildConfig.DEBUG của SDK)
mediaId, userIdString?nullĐược SDK gán khi mở bảng xếp hạng
enum class EnvInteractive { DEV, STG, PROD }

3. OverlayEventListener / DefaultOverlayEventListener

Phần tiêu đề “3. OverlayEventListener / DefaultOverlayEventListener”
interface OverlayEventListener {
fun onHandleMessage(msg: EventOverlay)
fun onHandleLiveViews(liveViews: Int)
fun onShowITR(show: Boolean)
fun onFocusOverlay(
takeControl: Boolean = false,
webViewError: Boolean = false,
overlayConfig: OverlayConfig? = null
)
}
interface DefaultOverlayEventListener : OverlayEventListener // alias, không thêm hàm
CallbackKhi nào được gọiViệc app nên làm
onHandleMessage(NEED_LOGIN)Người dùng thao tác với overlay yêu cầu đăng nhậpMở màn hình đăng nhập, sau đó gọi initToken()
onHandleMessage(NEED_PAY_ONG)Server trả PM402 (không đủ OnG)Mở màn hình nạp
onHandleLiveViews(n)Socket liveviewsHiển thị số người xem (đã cộng 230)
onShowITR(true)Overlay mở phần thống kê/dialogẨn bớt UI của app nếu cần
onFocusOverlay(takeControl = true, …)WebView nạp xong (onPageFinished)Điều chỉnh layout nếu overlay là popup
onFocusOverlay(webViewError = true, …)Lỗi tải trang / HTTP / SSLGhi log, có thể báo người dùng
onFocusOverlay(takeControl = false, …)Overlay bị gỡ (INTERACTIVE_HIDE_ANALYTICS)Khôi phục layout
enum class EventOverlay {
NEED_LOGIN, // SDK có phát
NEED_PAY_ONG, // SDK có phát
TOURNAMENT_BET, // đã khai báo, chưa dùng
SUCCESSFUL_REPLY_SUBMITTED, // đã khai báo, chưa dùng
FAILED_REPLY_SUBMITTED, // đã khai báo, chưa dùng
TAKE_FOCUS // đã khai báo, chưa dùng
}
interface PlayerChangeListener {
suspend fun currentPosition(): Long
fun onPlayerStateChanged(): Pair<Boolean, Int> // (isPlaying, playbackState)
}

playbackState theo quy ước ExoPlayer: 1 = IDLE, 2 = BUFFERING, 3 = READY, 4 = ENDED. SDK ánh xạ: 1 → "idle", 3 → isPlaying ? "playing" : "paused", còn lại → "".

ConstraintLayout tuỳ biến, là khung chứa mọi overlay.

Thành phần công khaiMô tả
overlayList: HashMap<OverlayWebView, OverlayConfig>Các WebView đang gắn
addListener(eventListener, overlayListener)SDK tự gọi trong OverlayManager.init
getCurrentOrientation(): IntHướng màn hình hiện tại
getLastOverlay(): OverlayWebView?WebView gắn gần nhất
getOverlayConfig(): OverlayConfig?Config của overlay dạng popup (nếu có)
removeWebView(view), removeWebViews(), clearViews()Gỡ view và huỷ tracking tương ứng

App chỉ cần khai báo view này trong XML; các hàm còn lại do SDK dùng.

TrườngKiểuÝ nghĩa
srcStringURL template web
metadataMetadata(pos, size)Vị trí + kích thước theo tỉ lệ
durationLongThời lượng hiển thị (giây)
targetsString?Nền tảng áp dụng (all, androidmobile, androidtv…)
timelineIdString?Định danh mốc kịch bản (khoá chống trùng, chống trả lời lại)
mediaContentIdString?Nội dung áp dụng
typeTimelineInt?0/1/2 mini game, 3 predict, 4 headline, 5 lucky
isPopupOverlayBooleantrue → dùng ràng buộc popup theo 9 vị trí; false → inline trên/dưới
allowAnonymousBooleanCho phép người chưa đăng nhập xem/tương tác
requiredFanClubBoolean?Bắt buộc là fanclub
startTimeShowOverlayLong?(VOD) giây bắt đầu hiện
requiredFocus, frequencyLimit, ts, sendTime, serverTimeTrường phụ trợ từ server
data class Metadata(val pos: OverlayPosition, val size: OverlaySize)
data class OverlayPosition(val x: Int, val y: Int, var alignment: OverlayAlignment? = null)
data class OverlaySize(val w: Float, val h: Float) // 0..1 — tỉ lệ so với OverlayView

x: 0 trái, 1 giữa, 2 phải. y: 0 trên, 1 giữa, 2 dưới → OverlayAlignment.{LeftTop, LeftCenter, LeftBottom, CenterTop, Center, CenterBottom, RightTop, RightCenter, RightBottom}.

OverlayConfig — thông tin kèm callback onFocusOverlay

Phần tiêu đề “OverlayConfig — thông tin kèm callback onFocusOverlay”
data class OverlayConfig(
val popupOverlay: Boolean = false, // true nếu là overlay inline dạng dải trên/dưới
val alignment: String? = null, // "top" | "bottom" | "left" | "right"
val ratio: Float = 0F // tỉ lệ chiều cao so với OverlayView
)
data class ActionReportResponse(
var success: Boolean = false,
var result: ActionResponseMessage = ActionResponseMessage(), // message, status, description, data
var failureReason: String? = null,
var failureStep: String? = null,
var error: String? = null,
)
Tên sự kiệnHằng sốKiểu dữ liệuXử lý
overlayConst.OVERLAYJSONObjectOverlay realtime
ex-overlayConst.EX_OVERLAYJSONObjectOverlay bù (bỏ nếu duration <= 10)
overlay-recallConst.OVERLAY_RECALLJSONObject | ByteArrayThu hồi overlay theo timelineId
predict-timelineConst.PREDICT_TIMELINEByteArrayACTIVE / INACTIVE / POWER / END
lucky-eventConst.LUCKY_EVENTByteArrayACTIVE / INACTIVE / POWER / END
predict-resultConst.PREDICT_RESULTByteArraySố liệu answer1 / answer2
update-resultConst.UPDATE_RESULTByteArrayĐẩy xuống web qua UPDATE_DATA_INTERACTIVE
liveviewsConst.LIVE_VIEWSJSONObjectSố người xem
dataConst.FAN_CLUBByteArrayTrạng thái fanclub
ckstConst.CKSTJSONObjectServer hỏi trạng thái player
TênKhi nàoPayload
join-roomSau khi socket connect{deviceId, mediaContentId, os, versionSDK, tenantId, isActivelyDisconnectSocket}
leave-roomleaveRoom()như trên
receive-messagePayload có traceLock = truePayload gốc (ByteArray UTF-8)
emit-ackCác mốc trackingXem 05 — Tracking
ckstTrả lời sự kiện ckst{action: "CHECK_PLAYER_STATUS", sessionId, data: {deviceId, os, mediaContentId, playerStatus}}
HeaderGiá trị
X-TENANT-IDtenantId
vBuildConfig.BUILD_VERSION (ngày build SDK)
osBuildConfig.DEVICE_TYPE (androidmobile / androidtv)
deviceIdSettings.Secure.ANDROID_ID
AuthorizationBearer <jwt> hoặc cookie nguyên văn

Tuỳ chọn kết nối: chỉ dùng websocket, tự reconnect, delay 5000ms (cả reconnectionDelay lẫn reconnectionDelayMax), randomizationFactor = 0.4.

Base URL = Const.INTERACTIVE_URL (suy ra từ EnvInteractive). Interceptor của BaseRequest tự thêm header X-TENANT-ID.

MethodĐường dẫnHeaderDùng cho
GET/api/ctc/scenario/v2/vod/{mediaContentId}/{os}AuthorizationTải kịch bản VOD
GET/api/scenario/getActiveOverlay/{mediaContentId}—Lấy overlay đang hoạt động (bù)
POST/api/actionsAuthorizationGửi hành động / câu trả lời
GET/api/public/vip-statusAuthorizationKiểm tra VIP trước khi trả lời
GET/api/media/interactive-status/{mediaId}x-tenant-id, CookieNội dung có tương tác không

Thân request /api/actions (SDK bổ sung vào JSON do web gửi lên):

{
"type": "INTERACTIVE_ACTION_REPORT",
"deviceId": "<android-id>", // SDK thêm
"os": "(os, androidmobile)", // SDK thêm
"data": {
"timelineId": "...",
"typeTimeline": 1,
"betAmount": 0,
"allowAnonymous": false,
"requiredFanClub": false,
"media": "<mediaId>", // SDK thêm
"socket_id": "<socket id>" // SDK thêm (chỉ khi Live)
// ...các trường do template web gửi
}
}

Tên interface: Android (Const.JS_INTERFACE_NAME).

Android.postMessage(JSON.stringify({ key: "LOADED_OVERLAY" }));
Android.postMessage(JSON.stringify({ type: "INTERACTIVE_ACTION_REPORT", data: {...} }));
Giá trịHằng sốÝ nghĩa
key = LOADED_OVERLAYConst.LOADED_OVERLAYTemplate sẵn sàng nhận dữ liệu
type = INTERACTIVE_SHOW_ANALYTICSOverlay hiển thị
type = INTERACTIVE_HIDE_ANALYTICSOverlay đóng
type = INTERACTIVE_ACTION_REPORTTrả lời / hành động (có data.action = "CLICK_ADS" cho quảng cáo)
type = INTERACTIVE_OPEN_ANALYTICSMở dialog predict/lucky
type = INTERACTIVE_CLOSE_ANALYTICSĐóng dialog predict/lucky
window.addEventListener("message", (e) => { /* e.data chứa key + data */ });
keyNội dung
GET_DATA_INTERACTIVEDữ liệu overlay ban đầu
UPDATE_DATA_INTERACTIVECập nhật kết quả realtime
UPDATE_CONFIRMXác nhận trả lời thành công
UPDATE_COUTERSố liệu predict (answer1, answer2)
UPDATE_NUMBER_LUCKYKết quả lucky

Tham sốKhi nào được thêm
os=<deviceType>Nếu src chưa có &os
logged=falseChưa đăng nhập và overlay không allowAnonymous
duration=<giây còn lại>Luôn (tính từ missTime)
fanclub=falseOverlay yêu cầu fanclub nhưng người dùng chưa thuộc fanclub
u=<userId>Riêng PredictDialog / LuckyDialog
timelineId, tenantId, deviceType, osRiêng overlay VOD (dựng trong parseTimeLineListForVOD)
Const.VIDEO_LIVE // = 1
Const.VIDEO_VOD // = 2

Các biến toàn cục do SDK quản lý (app không nên ghi trực tiếp): Const.USER_COOKIE, Const.USER_ID, Const.BJ_NAME, Const.IS_FAN_CLUB, Const.IS_VIP, Const.BET_AMOUNT, Const.INTERACTIVE_URL, Const.INTERACTIVE_SOCKET_URL.

12. Dialog gợi ý (SuggestType) — SDK tự hiển thị

Phần tiêu đề “12. Dialog gợi ý (SuggestType) — SDK tự hiển thị”
LoạiNội dung hiển thịKích hoạt bởi
SUGGEST_FAN_CLUBCảnh báo cần vào fanclub (kèm Const.BJ_NAME)Overlay requiredFanClub
SUGGEST_BET“Bạn có đồng ý sử dụng N OnG để trả lời không?”betAmount > 0 và không phải VIP
SUGGEST_ANSWER_REJECTdescription từ API, mặc định “Trả lời không thành công!”API trả success = false
SUGGEST_ANSWER_PAYMENT_REJECT“Vui lòng nạp OnG!”Mã PM402
SUGGEST_PREDICT_END“Dự đoán đã kết thúc!”Sự kiện predict END
SUGGEST_LUCKY_END“Sự kiện đã kết thúc!”Lucky kết thúc
SUGGEST_ANSWER_SUCCESS, SUGGEST_ERROR_OCCUR, SUGGEST_LOGINĐã định nghĩa, chưa dùng trong luồng hiện tại