drgame-cc 1.0.42 → 1.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/drres/prefab/ExitWin.prefab +764 -764
- package/drres/prefab/HelperWin.prefab +128 -4
- package/drres/prefab/HelperWin.prefab.meta +9 -0
- package/drscript/HelperWin.ts +1 -2
- package/drscript/PlatformAdapter.ts +7 -9
- package/drscript/ad-sdk/README.md +344 -344
- package/drscript/ad-sdk/ad-sdk.d.ts +59 -59
- package/drscript/ad-sdk/ad-sdk.js +322 -322
- package/drscript/ad-sdk/adapters/xiaomi-adapter.d.ts +29 -29
- package/drscript/ad-sdk/adapters/xiaomi-adapter.js +449 -449
- package/drscript/ad-sdk/event-emitter.d.ts +12 -12
- package/drscript/ad-sdk/event-emitter.js +65 -65
- package/drscript/ad-sdk/leaderboard/leaderboard.d.ts +23 -23
- package/drscript/ad-sdk/leaderboard/leaderboard.js +193 -193
- package/drscript/ad-sdk/package.json +46 -46
- package/drscript/ad-sdk/reporters/reporter.d.ts +40 -40
- package/drscript/ad-sdk/reporters/reporter.js +217 -217
- package/drscript/ad-sdk/types/enums.d.ts +64 -64
- package/drscript/ad-sdk/types/enums.js +111 -111
- package/drscript/ad-sdk/types/index.d.ts +6 -6
- package/drscript/ad-sdk/types/index.js +15 -15
- package/drscript/ad-sdk/types/interfaces.d.ts +333 -333
- package/drscript/interface/ILobbyBridge.ts +5 -5
- package/package.json +1 -1
|
@@ -1,449 +1,449 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 聚合广告 SDK - 小米电视适配器
|
|
3
|
-
*
|
|
4
|
-
* 底层通过 JSBridge 与电视应用商店客户端通信:
|
|
5
|
-
* H5 → Native: window.AppBridge.call(json)
|
|
6
|
-
* Native → H5: window.onNativeBridgeCallback(action, data)
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { AdPlatform, AdEvent, AdErrorCode } = require('../types/enums');
|
|
10
|
-
const { EventEmitter } = require('../event-emitter');
|
|
11
|
-
const KEY_EVENT_NAME = '__key_event__';
|
|
12
|
-
|
|
13
|
-
// ────────────────────────────────────────
|
|
14
|
-
// JSBridge 底层封装
|
|
15
|
-
// ────────────────────────────────────────
|
|
16
|
-
|
|
17
|
-
/** 获取 JSBridge 全局对象 */
|
|
18
|
-
function getAppBridge() {
|
|
19
|
-
if (typeof window === 'undefined') return null;
|
|
20
|
-
return window.AppBridge || null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** 检测是否在原生环境中 */
|
|
24
|
-
function isNativeEnv() {
|
|
25
|
-
return !!getAppBridge();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** 调用 JSBridge */
|
|
29
|
-
function bridgeCall(msg) {
|
|
30
|
-
const bridge = getAppBridge();
|
|
31
|
-
if (!bridge) {
|
|
32
|
-
console.warn('[AdSdk:Xiaomi] Not in native environment, bridge call ignored.');
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
bridge.call(JSON.stringify(msg));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// ────────────────────────────────────────
|
|
39
|
-
// 适配器实现
|
|
40
|
-
// ────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
class XiaomiAdapter {
|
|
43
|
-
constructor() {
|
|
44
|
-
this.platform = AdPlatform.Xiaomi;
|
|
45
|
-
this._config = {};
|
|
46
|
-
this._emitter = new EventEmitter();
|
|
47
|
-
this._cbId = 0;
|
|
48
|
-
this._callbacks = new Map();
|
|
49
|
-
this._deviceCallbacks = new Map();
|
|
50
|
-
this._accountCallbacks = new Map();
|
|
51
|
-
this._adInProgress = false;
|
|
52
|
-
this._originalCallback = null;
|
|
53
|
-
this._exitResolve = null;
|
|
54
|
-
this._keyHandlers = [];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* 初始化适配器
|
|
59
|
-
* @param {import('../types/interfaces').IAdapterConfig} config
|
|
60
|
-
*/
|
|
61
|
-
async init(config) {
|
|
62
|
-
this._config = config || {};
|
|
63
|
-
|
|
64
|
-
// 保存已有的 onNativeBridgeCallback,避免覆盖
|
|
65
|
-
if (typeof window !== 'undefined' && window.onNativeBridgeCallback) {
|
|
66
|
-
this._originalCallback = window.onNativeBridgeCallback;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 注册全局回调
|
|
70
|
-
const self = this;
|
|
71
|
-
window.onNativeBridgeCallback = function (action, data) {
|
|
72
|
-
// 先调用原有回调
|
|
73
|
-
if (self._originalCallback) {
|
|
74
|
-
try {
|
|
75
|
-
self._originalCallback(action, data);
|
|
76
|
-
} catch (_) {
|
|
77
|
-
// ignore
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
self._handleNativeCallback(action, data);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
console.log('[AdSdk:Xiaomi] Adapter initialized.');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* 请求播放广告
|
|
88
|
-
* @param {import('../types/interfaces').IAdRequest} request
|
|
89
|
-
* @returns {Promise<import('../types/interfaces').IAdRewardResult>}
|
|
90
|
-
*/
|
|
91
|
-
requestAd(request) {
|
|
92
|
-
const self = this;
|
|
93
|
-
return new Promise(function (resolve, reject) {
|
|
94
|
-
if (!isNativeEnv()) {
|
|
95
|
-
reject({
|
|
96
|
-
code: AdErrorCode.PlatformNotSupported,
|
|
97
|
-
message: 'Not in native JSBridge environment',
|
|
98
|
-
platform: self.platform,
|
|
99
|
-
requestId: '',
|
|
100
|
-
});
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (self._adInProgress) {
|
|
105
|
-
reject({
|
|
106
|
-
code: AdErrorCode.AdInProgress,
|
|
107
|
-
message: 'An ad is already in progress',
|
|
108
|
-
platform: self.platform,
|
|
109
|
-
requestId: '',
|
|
110
|
-
});
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
self._adInProgress = true;
|
|
115
|
-
const callbackId = 'ad_' + (++self._cbId);
|
|
116
|
-
|
|
117
|
-
self._callbacks.set(callbackId, { resolve: resolve, reject: reject });
|
|
118
|
-
|
|
119
|
-
// 发出 loaded 事件
|
|
120
|
-
self._emitter.emit(AdEvent.Loaded, { request: request });
|
|
121
|
-
|
|
122
|
-
bridgeCall({
|
|
123
|
-
action: 'requestAd',
|
|
124
|
-
data: {
|
|
125
|
-
cp_id: request.cpId || self._config.cpId,
|
|
126
|
-
reward_type: request.rewardType,
|
|
127
|
-
trigger_scene: request.triggerScene,
|
|
128
|
-
...(request.extra || {}),
|
|
129
|
-
},
|
|
130
|
-
callbackId: callbackId,
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 获取设备信息
|
|
137
|
-
* @returns {Promise<import('../types/interfaces').IDeviceInfo>}
|
|
138
|
-
*/
|
|
139
|
-
getDeviceInfo() {
|
|
140
|
-
const self = this;
|
|
141
|
-
return new Promise(function (resolve, reject) {
|
|
142
|
-
if (!isNativeEnv()) {
|
|
143
|
-
reject({
|
|
144
|
-
code: AdErrorCode.PlatformNotSupported,
|
|
145
|
-
message: 'Not in native JSBridge environment',
|
|
146
|
-
platform: self.platform,
|
|
147
|
-
requestId: '',
|
|
148
|
-
});
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const callbackId = 'dev_' + (++self._cbId);
|
|
153
|
-
self._deviceCallbacks.set(callbackId, { resolve: resolve, reject: reject });
|
|
154
|
-
|
|
155
|
-
bridgeCall({
|
|
156
|
-
action: 'getDeviceInfo',
|
|
157
|
-
data: {},
|
|
158
|
-
callbackId: callbackId,
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* 获取玩家账户信息
|
|
165
|
-
* @returns {Promise<import('../types/interfaces').IAccountInfo>}
|
|
166
|
-
*/
|
|
167
|
-
getAccount() {
|
|
168
|
-
const self = this;
|
|
169
|
-
return new Promise(function (resolve, reject) {
|
|
170
|
-
if (!isNativeEnv()) {
|
|
171
|
-
reject({
|
|
172
|
-
code: AdErrorCode.PlatformNotSupported,
|
|
173
|
-
message: 'Not in native JSBridge environment',
|
|
174
|
-
platform: self.platform,
|
|
175
|
-
requestId: '',
|
|
176
|
-
});
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const callbackId = 'acc_' + (++self._cbId);
|
|
181
|
-
self._accountCallbacks.set(callbackId, { resolve: resolve, reject: reject });
|
|
182
|
-
|
|
183
|
-
bridgeCall({
|
|
184
|
-
action: 'getAccount',
|
|
185
|
-
data: {},
|
|
186
|
-
callbackId: callbackId,
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* 通知游戏加载完成
|
|
193
|
-
* @param {string} version
|
|
194
|
-
*/
|
|
195
|
-
onGameReady(version) {
|
|
196
|
-
bridgeCall({
|
|
197
|
-
action: 'onGameReady',
|
|
198
|
-
data: { version: version },
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/** 通知游戏暂停 */
|
|
203
|
-
onGamePause() {
|
|
204
|
-
bridgeCall({
|
|
205
|
-
action: 'onGamePause',
|
|
206
|
-
data: {},
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** 通知游戏恢复 */
|
|
211
|
-
onGameResume() {
|
|
212
|
-
bridgeCall({
|
|
213
|
-
action: 'onGameResume',
|
|
214
|
-
data: {},
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* 退出游戏
|
|
220
|
-
* @returns {Promise<void>}
|
|
221
|
-
*/
|
|
222
|
-
exitGame() {
|
|
223
|
-
const self = this;
|
|
224
|
-
return new Promise(function (resolve) {
|
|
225
|
-
if (!isNativeEnv()) {
|
|
226
|
-
resolve();
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
self._exitResolve = resolve;
|
|
230
|
-
bridgeCall({
|
|
231
|
-
action: 'exitGame',
|
|
232
|
-
data: {},
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* 监听遥控器按键事件
|
|
239
|
-
* @param {Function} handler - 回调函数,接收 { key, action } 对象
|
|
240
|
-
*/
|
|
241
|
-
onKeyEvent(handler) {
|
|
242
|
-
if (typeof handler === 'function' && this._keyHandlers.indexOf(handler) === -1) {
|
|
243
|
-
this._keyHandlers.push(handler);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* 取消监听遥控器按键事件
|
|
249
|
-
* @param {Function} [handler] - 不传则清除所有
|
|
250
|
-
*/
|
|
251
|
-
offKeyEvent(handler) {
|
|
252
|
-
if (!handler) {
|
|
253
|
-
this._keyHandlers = [];
|
|
254
|
-
} else {
|
|
255
|
-
var idx = this._keyHandlers.indexOf(handler);
|
|
256
|
-
if (idx !== -1) {
|
|
257
|
-
this._keyHandlers.splice(idx, 1);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* 监听事件
|
|
264
|
-
* @param {string} event
|
|
265
|
-
* @param {Function} handler
|
|
266
|
-
*/
|
|
267
|
-
on(event, handler) {
|
|
268
|
-
this._emitter.on(event, handler);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* 取消事件
|
|
273
|
-
* @param {string} event
|
|
274
|
-
* @param {Function} [handler]
|
|
275
|
-
*/
|
|
276
|
-
off(event, handler) {
|
|
277
|
-
this._emitter.off(event, handler);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/** 销毁适配器 */
|
|
281
|
-
destroy() {
|
|
282
|
-
this._callbacks.clear();
|
|
283
|
-
this._deviceCallbacks.clear();
|
|
284
|
-
this._accountCallbacks.clear();
|
|
285
|
-
this._emitter.removeAllListeners();
|
|
286
|
-
this._adInProgress = false;
|
|
287
|
-
this._exitResolve = null;
|
|
288
|
-
this._keyHandlers = [];
|
|
289
|
-
|
|
290
|
-
// 恢复原有回调
|
|
291
|
-
if (this._originalCallback && typeof window !== 'undefined') {
|
|
292
|
-
window.onNativeBridgeCallback = this._originalCallback;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// ────────────────────────────────────────
|
|
297
|
-
// 内部方法
|
|
298
|
-
// ────────────────────────────────────────
|
|
299
|
-
|
|
300
|
-
/** @private 处理 Native 回调 */
|
|
301
|
-
_handleNativeCallback(action, data) {
|
|
302
|
-
console.log(`[AdSdk:Xiaomi] Received native callback: ${action}`, data);
|
|
303
|
-
switch (action) {
|
|
304
|
-
// ── 通用回调(getDeviceInfo / getAccount 等) ──
|
|
305
|
-
case 'onBridgeCallback': {
|
|
306
|
-
const cbId = data.callbackId;
|
|
307
|
-
const code = data.code;
|
|
308
|
-
|
|
309
|
-
// getDeviceInfo 回调
|
|
310
|
-
if (this._deviceCallbacks.has(cbId)) {
|
|
311
|
-
const entry = this._deviceCallbacks.get(cbId);
|
|
312
|
-
this._deviceCallbacks.delete(cbId);
|
|
313
|
-
if (code === 0) {
|
|
314
|
-
entry.resolve(data.data || {});
|
|
315
|
-
} else {
|
|
316
|
-
entry.reject({
|
|
317
|
-
code: code,
|
|
318
|
-
message: data.message || 'getDeviceInfo failed',
|
|
319
|
-
platform: this.platform,
|
|
320
|
-
requestId: cbId,
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// getAccount 回调
|
|
327
|
-
if (this._accountCallbacks.has(cbId)) {
|
|
328
|
-
const entry = this._accountCallbacks.get(cbId);
|
|
329
|
-
this._accountCallbacks.delete(cbId);
|
|
330
|
-
if (code === 0) {
|
|
331
|
-
entry.resolve(data.data || {});
|
|
332
|
-
} else {
|
|
333
|
-
entry.reject({
|
|
334
|
-
code: code,
|
|
335
|
-
message: data.message || 'getAccount failed',
|
|
336
|
-
platform: this.platform,
|
|
337
|
-
requestId: cbId,
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
break;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// ── 广告奖励 ──
|
|
346
|
-
case 'onReward': {
|
|
347
|
-
const cbId = data.callbackId;
|
|
348
|
-
const result = {
|
|
349
|
-
isCompleted: true,
|
|
350
|
-
requestId: cbId,
|
|
351
|
-
};
|
|
352
|
-
this._adInProgress = false;
|
|
353
|
-
|
|
354
|
-
this._emitter.emit(AdEvent.Reward, result);
|
|
355
|
-
|
|
356
|
-
if (this._callbacks.has(cbId)) {
|
|
357
|
-
const entry = this._callbacks.get(cbId);
|
|
358
|
-
this._callbacks.delete(cbId);
|
|
359
|
-
entry.resolve(result);
|
|
360
|
-
}
|
|
361
|
-
break;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// ── 广告关闭 ──
|
|
365
|
-
case 'onAdClosed': {
|
|
366
|
-
const cbId = data.callbackId;
|
|
367
|
-
const isCompleted = !!data.is_completed;
|
|
368
|
-
const closedResult = {
|
|
369
|
-
isCompleted: isCompleted,
|
|
370
|
-
requestId: cbId,
|
|
371
|
-
};
|
|
372
|
-
this._adInProgress = false;
|
|
373
|
-
|
|
374
|
-
this._emitter.emit(AdEvent.Closed, closedResult);
|
|
375
|
-
|
|
376
|
-
if (this._callbacks.has(cbId)) {
|
|
377
|
-
const entry = this._callbacks.get(cbId);
|
|
378
|
-
this._callbacks.delete(cbId);
|
|
379
|
-
|
|
380
|
-
if (isCompleted) {
|
|
381
|
-
entry.resolve({
|
|
382
|
-
isCompleted: true,
|
|
383
|
-
requestId: cbId,
|
|
384
|
-
});
|
|
385
|
-
} else {
|
|
386
|
-
entry.reject({
|
|
387
|
-
code: AdErrorCode.Unknown,
|
|
388
|
-
message: 'Ad closed by user before completion',
|
|
389
|
-
platform: this.platform,
|
|
390
|
-
requestId: cbId,
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
break;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// ── 广告失败 ──
|
|
398
|
-
case 'onAdFailed': {
|
|
399
|
-
const cbId = data.callbackId;
|
|
400
|
-
const errorCode = data.code;
|
|
401
|
-
const errorMsg = data.message;
|
|
402
|
-
this._adInProgress = false;
|
|
403
|
-
|
|
404
|
-
const adError = {
|
|
405
|
-
code: errorCode,
|
|
406
|
-
message: errorMsg,
|
|
407
|
-
platform: this.platform,
|
|
408
|
-
requestId: cbId,
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
this._emitter.emit(AdEvent.Error, adError);
|
|
412
|
-
|
|
413
|
-
if (this._callbacks.has(cbId)) {
|
|
414
|
-
const entry = this._callbacks.get(cbId);
|
|
415
|
-
this._callbacks.delete(cbId);
|
|
416
|
-
entry.reject(adError);
|
|
417
|
-
}
|
|
418
|
-
break;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// ── 退出确认 ──
|
|
422
|
-
case 'onExitConfirmed': {
|
|
423
|
-
if (this._exitResolve) {
|
|
424
|
-
this._exitResolve();
|
|
425
|
-
this._exitResolve = null;
|
|
426
|
-
}
|
|
427
|
-
break;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// ── 遥控器按键 ──
|
|
431
|
-
case 'onKeyEvent': {
|
|
432
|
-
var keyEvent = {
|
|
433
|
-
key: data.key || '',
|
|
434
|
-
action: data.action || 'down',
|
|
435
|
-
};
|
|
436
|
-
for (var i = 0; i < this._keyHandlers.length; i++) {
|
|
437
|
-
try {
|
|
438
|
-
this._keyHandlers[i](keyEvent);
|
|
439
|
-
} catch (e) {
|
|
440
|
-
console.error('[AdSdk:Xiaomi] Key event handler error:', e);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
break;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
module.exports = { XiaomiAdapter };
|
|
1
|
+
/**
|
|
2
|
+
* 聚合广告 SDK - 小米电视适配器
|
|
3
|
+
*
|
|
4
|
+
* 底层通过 JSBridge 与电视应用商店客户端通信:
|
|
5
|
+
* H5 → Native: window.AppBridge.call(json)
|
|
6
|
+
* Native → H5: window.onNativeBridgeCallback(action, data)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { AdPlatform, AdEvent, AdErrorCode } = require('../types/enums');
|
|
10
|
+
const { EventEmitter } = require('../event-emitter');
|
|
11
|
+
const KEY_EVENT_NAME = '__key_event__';
|
|
12
|
+
|
|
13
|
+
// ────────────────────────────────────────
|
|
14
|
+
// JSBridge 底层封装
|
|
15
|
+
// ────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
/** 获取 JSBridge 全局对象 */
|
|
18
|
+
function getAppBridge() {
|
|
19
|
+
if (typeof window === 'undefined') return null;
|
|
20
|
+
return window.AppBridge || null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** 检测是否在原生环境中 */
|
|
24
|
+
function isNativeEnv() {
|
|
25
|
+
return !!getAppBridge();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** 调用 JSBridge */
|
|
29
|
+
function bridgeCall(msg) {
|
|
30
|
+
const bridge = getAppBridge();
|
|
31
|
+
if (!bridge) {
|
|
32
|
+
console.warn('[AdSdk:Xiaomi] Not in native environment, bridge call ignored.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
bridge.call(JSON.stringify(msg));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ────────────────────────────────────────
|
|
39
|
+
// 适配器实现
|
|
40
|
+
// ────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
class XiaomiAdapter {
|
|
43
|
+
constructor() {
|
|
44
|
+
this.platform = AdPlatform.Xiaomi;
|
|
45
|
+
this._config = {};
|
|
46
|
+
this._emitter = new EventEmitter();
|
|
47
|
+
this._cbId = 0;
|
|
48
|
+
this._callbacks = new Map();
|
|
49
|
+
this._deviceCallbacks = new Map();
|
|
50
|
+
this._accountCallbacks = new Map();
|
|
51
|
+
this._adInProgress = false;
|
|
52
|
+
this._originalCallback = null;
|
|
53
|
+
this._exitResolve = null;
|
|
54
|
+
this._keyHandlers = [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 初始化适配器
|
|
59
|
+
* @param {import('../types/interfaces').IAdapterConfig} config
|
|
60
|
+
*/
|
|
61
|
+
async init(config) {
|
|
62
|
+
this._config = config || {};
|
|
63
|
+
|
|
64
|
+
// 保存已有的 onNativeBridgeCallback,避免覆盖
|
|
65
|
+
if (typeof window !== 'undefined' && window.onNativeBridgeCallback) {
|
|
66
|
+
this._originalCallback = window.onNativeBridgeCallback;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 注册全局回调
|
|
70
|
+
const self = this;
|
|
71
|
+
window.onNativeBridgeCallback = function (action, data) {
|
|
72
|
+
// 先调用原有回调
|
|
73
|
+
if (self._originalCallback) {
|
|
74
|
+
try {
|
|
75
|
+
self._originalCallback(action, data);
|
|
76
|
+
} catch (_) {
|
|
77
|
+
// ignore
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
self._handleNativeCallback(action, data);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
console.log('[AdSdk:Xiaomi] Adapter initialized.');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 请求播放广告
|
|
88
|
+
* @param {import('../types/interfaces').IAdRequest} request
|
|
89
|
+
* @returns {Promise<import('../types/interfaces').IAdRewardResult>}
|
|
90
|
+
*/
|
|
91
|
+
requestAd(request) {
|
|
92
|
+
const self = this;
|
|
93
|
+
return new Promise(function (resolve, reject) {
|
|
94
|
+
if (!isNativeEnv()) {
|
|
95
|
+
reject({
|
|
96
|
+
code: AdErrorCode.PlatformNotSupported,
|
|
97
|
+
message: 'Not in native JSBridge environment',
|
|
98
|
+
platform: self.platform,
|
|
99
|
+
requestId: '',
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (self._adInProgress) {
|
|
105
|
+
reject({
|
|
106
|
+
code: AdErrorCode.AdInProgress,
|
|
107
|
+
message: 'An ad is already in progress',
|
|
108
|
+
platform: self.platform,
|
|
109
|
+
requestId: '',
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
self._adInProgress = true;
|
|
115
|
+
const callbackId = 'ad_' + (++self._cbId);
|
|
116
|
+
|
|
117
|
+
self._callbacks.set(callbackId, { resolve: resolve, reject: reject });
|
|
118
|
+
|
|
119
|
+
// 发出 loaded 事件
|
|
120
|
+
self._emitter.emit(AdEvent.Loaded, { request: request });
|
|
121
|
+
|
|
122
|
+
bridgeCall({
|
|
123
|
+
action: 'requestAd',
|
|
124
|
+
data: {
|
|
125
|
+
cp_id: request.cpId || self._config.cpId,
|
|
126
|
+
reward_type: request.rewardType,
|
|
127
|
+
trigger_scene: request.triggerScene,
|
|
128
|
+
...(request.extra || {}),
|
|
129
|
+
},
|
|
130
|
+
callbackId: callbackId,
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 获取设备信息
|
|
137
|
+
* @returns {Promise<import('../types/interfaces').IDeviceInfo>}
|
|
138
|
+
*/
|
|
139
|
+
getDeviceInfo() {
|
|
140
|
+
const self = this;
|
|
141
|
+
return new Promise(function (resolve, reject) {
|
|
142
|
+
if (!isNativeEnv()) {
|
|
143
|
+
reject({
|
|
144
|
+
code: AdErrorCode.PlatformNotSupported,
|
|
145
|
+
message: 'Not in native JSBridge environment',
|
|
146
|
+
platform: self.platform,
|
|
147
|
+
requestId: '',
|
|
148
|
+
});
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const callbackId = 'dev_' + (++self._cbId);
|
|
153
|
+
self._deviceCallbacks.set(callbackId, { resolve: resolve, reject: reject });
|
|
154
|
+
|
|
155
|
+
bridgeCall({
|
|
156
|
+
action: 'getDeviceInfo',
|
|
157
|
+
data: {},
|
|
158
|
+
callbackId: callbackId,
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 获取玩家账户信息
|
|
165
|
+
* @returns {Promise<import('../types/interfaces').IAccountInfo>}
|
|
166
|
+
*/
|
|
167
|
+
getAccount() {
|
|
168
|
+
const self = this;
|
|
169
|
+
return new Promise(function (resolve, reject) {
|
|
170
|
+
if (!isNativeEnv()) {
|
|
171
|
+
reject({
|
|
172
|
+
code: AdErrorCode.PlatformNotSupported,
|
|
173
|
+
message: 'Not in native JSBridge environment',
|
|
174
|
+
platform: self.platform,
|
|
175
|
+
requestId: '',
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const callbackId = 'acc_' + (++self._cbId);
|
|
181
|
+
self._accountCallbacks.set(callbackId, { resolve: resolve, reject: reject });
|
|
182
|
+
|
|
183
|
+
bridgeCall({
|
|
184
|
+
action: 'getAccount',
|
|
185
|
+
data: {},
|
|
186
|
+
callbackId: callbackId,
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 通知游戏加载完成
|
|
193
|
+
* @param {string} version
|
|
194
|
+
*/
|
|
195
|
+
onGameReady(version) {
|
|
196
|
+
bridgeCall({
|
|
197
|
+
action: 'onGameReady',
|
|
198
|
+
data: { version: version },
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** 通知游戏暂停 */
|
|
203
|
+
onGamePause() {
|
|
204
|
+
bridgeCall({
|
|
205
|
+
action: 'onGamePause',
|
|
206
|
+
data: {},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** 通知游戏恢复 */
|
|
211
|
+
onGameResume() {
|
|
212
|
+
bridgeCall({
|
|
213
|
+
action: 'onGameResume',
|
|
214
|
+
data: {},
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* 退出游戏
|
|
220
|
+
* @returns {Promise<void>}
|
|
221
|
+
*/
|
|
222
|
+
exitGame() {
|
|
223
|
+
const self = this;
|
|
224
|
+
return new Promise(function (resolve) {
|
|
225
|
+
if (!isNativeEnv()) {
|
|
226
|
+
resolve();
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
self._exitResolve = resolve;
|
|
230
|
+
bridgeCall({
|
|
231
|
+
action: 'exitGame',
|
|
232
|
+
data: {},
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* 监听遥控器按键事件
|
|
239
|
+
* @param {Function} handler - 回调函数,接收 { key, action } 对象
|
|
240
|
+
*/
|
|
241
|
+
onKeyEvent(handler) {
|
|
242
|
+
if (typeof handler === 'function' && this._keyHandlers.indexOf(handler) === -1) {
|
|
243
|
+
this._keyHandlers.push(handler);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* 取消监听遥控器按键事件
|
|
249
|
+
* @param {Function} [handler] - 不传则清除所有
|
|
250
|
+
*/
|
|
251
|
+
offKeyEvent(handler) {
|
|
252
|
+
if (!handler) {
|
|
253
|
+
this._keyHandlers = [];
|
|
254
|
+
} else {
|
|
255
|
+
var idx = this._keyHandlers.indexOf(handler);
|
|
256
|
+
if (idx !== -1) {
|
|
257
|
+
this._keyHandlers.splice(idx, 1);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* 监听事件
|
|
264
|
+
* @param {string} event
|
|
265
|
+
* @param {Function} handler
|
|
266
|
+
*/
|
|
267
|
+
on(event, handler) {
|
|
268
|
+
this._emitter.on(event, handler);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* 取消事件
|
|
273
|
+
* @param {string} event
|
|
274
|
+
* @param {Function} [handler]
|
|
275
|
+
*/
|
|
276
|
+
off(event, handler) {
|
|
277
|
+
this._emitter.off(event, handler);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** 销毁适配器 */
|
|
281
|
+
destroy() {
|
|
282
|
+
this._callbacks.clear();
|
|
283
|
+
this._deviceCallbacks.clear();
|
|
284
|
+
this._accountCallbacks.clear();
|
|
285
|
+
this._emitter.removeAllListeners();
|
|
286
|
+
this._adInProgress = false;
|
|
287
|
+
this._exitResolve = null;
|
|
288
|
+
this._keyHandlers = [];
|
|
289
|
+
|
|
290
|
+
// 恢复原有回调
|
|
291
|
+
if (this._originalCallback && typeof window !== 'undefined') {
|
|
292
|
+
window.onNativeBridgeCallback = this._originalCallback;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ────────────────────────────────────────
|
|
297
|
+
// 内部方法
|
|
298
|
+
// ────────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
/** @private 处理 Native 回调 */
|
|
301
|
+
_handleNativeCallback(action, data) {
|
|
302
|
+
console.log(`[AdSdk:Xiaomi] Received native callback: ${action}`, data);
|
|
303
|
+
switch (action) {
|
|
304
|
+
// ── 通用回调(getDeviceInfo / getAccount 等) ──
|
|
305
|
+
case 'onBridgeCallback': {
|
|
306
|
+
const cbId = data.callbackId;
|
|
307
|
+
const code = data.code;
|
|
308
|
+
|
|
309
|
+
// getDeviceInfo 回调
|
|
310
|
+
if (this._deviceCallbacks.has(cbId)) {
|
|
311
|
+
const entry = this._deviceCallbacks.get(cbId);
|
|
312
|
+
this._deviceCallbacks.delete(cbId);
|
|
313
|
+
if (code === 0) {
|
|
314
|
+
entry.resolve(data.data || {});
|
|
315
|
+
} else {
|
|
316
|
+
entry.reject({
|
|
317
|
+
code: code,
|
|
318
|
+
message: data.message || 'getDeviceInfo failed',
|
|
319
|
+
platform: this.platform,
|
|
320
|
+
requestId: cbId,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// getAccount 回调
|
|
327
|
+
if (this._accountCallbacks.has(cbId)) {
|
|
328
|
+
const entry = this._accountCallbacks.get(cbId);
|
|
329
|
+
this._accountCallbacks.delete(cbId);
|
|
330
|
+
if (code === 0) {
|
|
331
|
+
entry.resolve(data.data || {});
|
|
332
|
+
} else {
|
|
333
|
+
entry.reject({
|
|
334
|
+
code: code,
|
|
335
|
+
message: data.message || 'getAccount failed',
|
|
336
|
+
platform: this.platform,
|
|
337
|
+
requestId: cbId,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ── 广告奖励 ──
|
|
346
|
+
case 'onReward': {
|
|
347
|
+
const cbId = data.callbackId;
|
|
348
|
+
const result = {
|
|
349
|
+
isCompleted: true,
|
|
350
|
+
requestId: cbId,
|
|
351
|
+
};
|
|
352
|
+
this._adInProgress = false;
|
|
353
|
+
|
|
354
|
+
this._emitter.emit(AdEvent.Reward, result);
|
|
355
|
+
|
|
356
|
+
if (this._callbacks.has(cbId)) {
|
|
357
|
+
const entry = this._callbacks.get(cbId);
|
|
358
|
+
this._callbacks.delete(cbId);
|
|
359
|
+
entry.resolve(result);
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ── 广告关闭 ──
|
|
365
|
+
case 'onAdClosed': {
|
|
366
|
+
const cbId = data.callbackId;
|
|
367
|
+
const isCompleted = !!data.is_completed;
|
|
368
|
+
const closedResult = {
|
|
369
|
+
isCompleted: isCompleted,
|
|
370
|
+
requestId: cbId,
|
|
371
|
+
};
|
|
372
|
+
this._adInProgress = false;
|
|
373
|
+
|
|
374
|
+
this._emitter.emit(AdEvent.Closed, closedResult);
|
|
375
|
+
|
|
376
|
+
if (this._callbacks.has(cbId)) {
|
|
377
|
+
const entry = this._callbacks.get(cbId);
|
|
378
|
+
this._callbacks.delete(cbId);
|
|
379
|
+
|
|
380
|
+
if (isCompleted) {
|
|
381
|
+
entry.resolve({
|
|
382
|
+
isCompleted: true,
|
|
383
|
+
requestId: cbId,
|
|
384
|
+
});
|
|
385
|
+
} else {
|
|
386
|
+
entry.reject({
|
|
387
|
+
code: AdErrorCode.Unknown,
|
|
388
|
+
message: 'Ad closed by user before completion',
|
|
389
|
+
platform: this.platform,
|
|
390
|
+
requestId: cbId,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ── 广告失败 ──
|
|
398
|
+
case 'onAdFailed': {
|
|
399
|
+
const cbId = data.callbackId;
|
|
400
|
+
const errorCode = data.code;
|
|
401
|
+
const errorMsg = data.message;
|
|
402
|
+
this._adInProgress = false;
|
|
403
|
+
|
|
404
|
+
const adError = {
|
|
405
|
+
code: errorCode,
|
|
406
|
+
message: errorMsg,
|
|
407
|
+
platform: this.platform,
|
|
408
|
+
requestId: cbId,
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
this._emitter.emit(AdEvent.Error, adError);
|
|
412
|
+
|
|
413
|
+
if (this._callbacks.has(cbId)) {
|
|
414
|
+
const entry = this._callbacks.get(cbId);
|
|
415
|
+
this._callbacks.delete(cbId);
|
|
416
|
+
entry.reject(adError);
|
|
417
|
+
}
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ── 退出确认 ──
|
|
422
|
+
case 'onExitConfirmed': {
|
|
423
|
+
if (this._exitResolve) {
|
|
424
|
+
this._exitResolve();
|
|
425
|
+
this._exitResolve = null;
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// ── 遥控器按键 ──
|
|
431
|
+
case 'onKeyEvent': {
|
|
432
|
+
var keyEvent = {
|
|
433
|
+
key: data.key || '',
|
|
434
|
+
action: data.action || 'down',
|
|
435
|
+
};
|
|
436
|
+
for (var i = 0; i < this._keyHandlers.length; i++) {
|
|
437
|
+
try {
|
|
438
|
+
this._keyHandlers[i](keyEvent);
|
|
439
|
+
} catch (e) {
|
|
440
|
+
console.error('[AdSdk:Xiaomi] Key event handler error:', e);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
module.exports = { XiaomiAdapter };
|