1119 lines
34 KiB
Markdown
1119 lines
34 KiB
Markdown
# TSGame JSBridge 接口文档 - 高级功能与扩展
|
||
|
||
**版本**: v1.9
|
||
**更新时间**: 2025年7月13日
|
||
**文档类型**: 接口规范文档 - 第四部分
|
||
|
||
## 文档说明
|
||
|
||
本文档是TSGame JSBridge接口规范文档的第四部分,专注于高级功能与扩展相关接口,包括录音准备、设备震动控制、社交分享等功能。
|
||
|
||
**适用平台**: Android / HarmonyOS
|
||
**接口范围**: 录音控制、震动反馈、社交分享
|
||
|
||
### 本文档包含的接口
|
||
|
||
| 接口名称 | 调用方向 | 主要功能 | 使用场景 |
|
||
|----------|----------|----------|----------|
|
||
| `prepareaudio` | WebView→App | 录音准备 | 语音录制准备 |
|
||
| `vibrator` | WebView→App | 单次震动 | 触觉反馈 |
|
||
| `repeatvibrator` | WebView→App | 重复震动 | 持续触觉反馈 |
|
||
| `canclevibrator` | WebView→App | 取消震动 | 停止震动反馈 |
|
||
| `friendsSharetypeUrlToptitleDescript` | WebView→App | 社交分享 | 微信/抖音分享 |
|
||
|
||
---
|
||
|
||
## 1. 录音准备接口 (prepareaudio)
|
||
|
||
### 接口概述
|
||
当WebView需要进行语音录制时,通过此接口初始化录音设备和准备录音环境。该接口会配置麦克风权限、创建录音文件、初始化MediaRecorder等录音前的准备工作。
|
||
|
||
### 工作流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 用户
|
||
participant WebView as WebView
|
||
participant App as App
|
||
participant AudioManager as 录音管理器
|
||
participant MediaRecorder as 媒体录制器
|
||
participant FileSystem as 文件系统
|
||
participant Microphone as 麦克风
|
||
|
||
User->>WebView: 触发录音准备
|
||
WebView->>App: 调用prepareaudio接口
|
||
App->>App: 检查录音权限
|
||
App->>App: 停止当前播放的音频
|
||
|
||
alt 有权限且满足条件
|
||
App->>AudioManager: 调用prepareAudio方法
|
||
AudioManager->>FileSystem: 创建录音文件目录
|
||
AudioManager->>FileSystem: 生成录音文件名
|
||
AudioManager->>MediaRecorder: 初始化录制器
|
||
MediaRecorder->>Microphone: 设置音频源为麦克风
|
||
MediaRecorder->>MediaRecorder: 配置输出格式(AMR)
|
||
MediaRecorder->>MediaRecorder: 设置音频编码器
|
||
MediaRecorder->>MediaRecorder: 准备录制环境
|
||
MediaRecorder->>AudioManager: 开始录制
|
||
AudioManager->>App: 录音准备完成
|
||
App->>WebView: 返回准备结果
|
||
else 权限不足或条件不满足
|
||
App->>WebView: 返回错误信息
|
||
end
|
||
```
|
||
|
||
### 参数规范
|
||
|
||
#### 调用格式
|
||
```javascript
|
||
WebViewJavascriptBridge.callHandler('prepareaudio', '', function(response) {
|
||
console.log('录音准备完成');
|
||
});
|
||
```
|
||
|
||
#### 参数说明
|
||
| 参数 | 类型 | 必需 | 说明 | 取值 |
|
||
|------|------|------|------|------|
|
||
| data | string | ✓ | 固定传入空字符串 | "" |
|
||
|
||
### 接口调用示例
|
||
|
||
#### 基础录音准备
|
||
```javascript
|
||
// 录音准备
|
||
function prepareRecording() {
|
||
WebViewJavascriptBridge.callHandler('prepareaudio', '', function(response) {
|
||
console.log('录音准备已完成');
|
||
// 录音准备完成后可以开始录制
|
||
showRecordingUI();
|
||
});
|
||
}
|
||
|
||
// 显示录音界面
|
||
function showRecordingUI() {
|
||
const recordButton = document.getElementById('recordButton');
|
||
recordButton.textContent = '正在录音...';
|
||
recordButton.classList.add('recording');
|
||
}
|
||
```
|
||
|
||
#### 录音状态管理器
|
||
```javascript
|
||
// 录音管理器
|
||
const RecordingManager = {
|
||
isRecording: false,
|
||
recordingStartTime: null,
|
||
maxRecordingTime: 60000, // 最大录音时间60秒
|
||
|
||
// 开始录音流程
|
||
startRecording() {
|
||
if (this.isRecording) {
|
||
console.log('正在录音中,请先停止当前录音');
|
||
return;
|
||
}
|
||
|
||
// 检查麦克风权限
|
||
this.checkMicrophonePermission(() => {
|
||
// 准备录音
|
||
this.prepareRecording();
|
||
});
|
||
},
|
||
|
||
// 检查麦克风权限
|
||
checkMicrophonePermission(callback) {
|
||
// 在实际应用中应该检查权限
|
||
console.log('检查麦克风权限...');
|
||
callback();
|
||
},
|
||
|
||
// 准备录音
|
||
prepareRecording() {
|
||
console.log('开始录音准备...');
|
||
|
||
WebViewJavascriptBridge.callHandler('prepareaudio', '', (response) => {
|
||
console.log('录音准备完成');
|
||
this.isRecording = true;
|
||
this.recordingStartTime = Date.now();
|
||
|
||
// 更新UI
|
||
this.updateRecordingUI(true);
|
||
|
||
// 设置录音超时
|
||
this.setRecordingTimeout();
|
||
});
|
||
},
|
||
|
||
// 停止录音
|
||
stopRecording() {
|
||
if (!this.isRecording) {
|
||
console.log('当前没有在录音');
|
||
return;
|
||
}
|
||
|
||
this.isRecording = false;
|
||
this.recordingStartTime = null;
|
||
|
||
// 清除超时定时器
|
||
if (this.recordingTimeout) {
|
||
clearTimeout(this.recordingTimeout);
|
||
this.recordingTimeout = null;
|
||
}
|
||
|
||
// 更新UI
|
||
this.updateRecordingUI(false);
|
||
|
||
console.log('录音已停止');
|
||
},
|
||
|
||
// 设置录音超时
|
||
setRecordingTimeout() {
|
||
this.recordingTimeout = setTimeout(() => {
|
||
console.log('录音时间超过限制,自动停止');
|
||
this.stopRecording();
|
||
showMessage('录音时间过长,已自动停止');
|
||
}, this.maxRecordingTime);
|
||
},
|
||
|
||
// 更新录音UI
|
||
updateRecordingUI(isRecording) {
|
||
const recordButton = document.getElementById('recordButton');
|
||
const recordStatus = document.getElementById('recordStatus');
|
||
|
||
if (isRecording) {
|
||
recordButton.textContent = '停止录音';
|
||
recordButton.classList.add('recording');
|
||
recordStatus.textContent = '正在录音...';
|
||
|
||
// 开始录音动画
|
||
this.startRecordingAnimation();
|
||
} else {
|
||
recordButton.textContent = '开始录音';
|
||
recordButton.classList.remove('recording');
|
||
recordStatus.textContent = '录音已完成';
|
||
|
||
// 停止录音动画
|
||
this.stopRecordingAnimation();
|
||
}
|
||
},
|
||
|
||
// 录音动画
|
||
startRecordingAnimation() {
|
||
const recordIndicator = document.getElementById('recordIndicator');
|
||
if (recordIndicator) {
|
||
recordIndicator.classList.add('pulse');
|
||
}
|
||
},
|
||
|
||
stopRecordingAnimation() {
|
||
const recordIndicator = document.getElementById('recordIndicator');
|
||
if (recordIndicator) {
|
||
recordIndicator.classList.remove('pulse');
|
||
}
|
||
},
|
||
|
||
// 获取录音时长
|
||
getRecordingDuration() {
|
||
if (!this.isRecording || !this.recordingStartTime) {
|
||
return 0;
|
||
}
|
||
|
||
return Date.now() - this.recordingStartTime;
|
||
}
|
||
};
|
||
|
||
// 录音按钮事件
|
||
function handleRecordButtonClick() {
|
||
if (RecordingManager.isRecording) {
|
||
RecordingManager.stopRecording();
|
||
} else {
|
||
RecordingManager.startRecording();
|
||
}
|
||
}
|
||
```
|
||
|
||
### HarmonyOS实现要点
|
||
- **接口名称**: `prepareaudio`
|
||
- **调用方向**: WebView → App
|
||
- **参数格式**: 空字符串
|
||
- **权限要求**: 需要RECORD_AUDIO权限
|
||
- **文件管理**: 创建录音文件目录和生成文件名
|
||
- **录制配置**: 音频源(麦克风)、输出格式(AMR)、编码器设置
|
||
- **状态管理**: 管理录音准备、开始、停止状态
|
||
|
||
---
|
||
|
||
## 2. 单次震动接口 (vibrator)
|
||
|
||
### 接口概述
|
||
当WebView需要提供触觉反馈时,通过此接口触发设备震动指定的时长。常用于按钮点击、操作确认、提醒通知等场景。
|
||
|
||
### 工作流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 用户
|
||
participant WebView as WebView
|
||
participant App as App
|
||
participant VibratorUtil as 震动工具类
|
||
participant SystemVibrator as 系统震动服务
|
||
|
||
User->>WebView: 触发震动操作
|
||
WebView->>App: 调用vibrator接口
|
||
App->>App: 解析震动时长参数
|
||
App->>VibratorUtil: 调用震动方法
|
||
VibratorUtil->>SystemVibrator: 获取系统震动服务
|
||
SystemVibrator->>SystemVibrator: 执行震动指定时长
|
||
SystemVibrator->>VibratorUtil: 震动完成
|
||
VibratorUtil->>App: 返回执行结果
|
||
App->>WebView: 返回震动结果
|
||
```
|
||
|
||
### 参数规范
|
||
|
||
#### 调用格式
|
||
```javascript
|
||
WebViewJavascriptBridge.callHandler('vibrator', '500', function(response) {
|
||
console.log('震动已执行');
|
||
});
|
||
```
|
||
|
||
#### 参数说明
|
||
| 参数 | 类型 | 必需 | 说明 | 示例值 |
|
||
|------|------|------|------|--------|
|
||
| duration | string | ✓ | 震动时长(毫秒) | "500", "1000", "200" |
|
||
|
||
### 接口调用示例
|
||
|
||
#### 基础震动反馈
|
||
```javascript
|
||
// 按钮点击震动
|
||
function buttonClickVibrate() {
|
||
WebViewJavascriptBridge.callHandler('vibrator', '100', function(response) {
|
||
console.log('按钮点击震动完成');
|
||
});
|
||
}
|
||
|
||
// 操作成功震动
|
||
function successVibrate() {
|
||
WebViewJavascriptBridge.callHandler('vibrator', '200', function(response) {
|
||
console.log('成功操作震动完成');
|
||
});
|
||
}
|
||
|
||
// 错误提醒震动
|
||
function errorVibrate() {
|
||
WebViewJavascriptBridge.callHandler('vibrator', '500', function(response) {
|
||
console.log('错误提醒震动完成');
|
||
});
|
||
}
|
||
```
|
||
|
||
#### 震动反馈管理器
|
||
```javascript
|
||
// 震动管理器
|
||
const VibrationManager = {
|
||
// 震动模式配置
|
||
vibrationModes: {
|
||
light: '50', // 轻微震动
|
||
medium: '150', // 中等震动
|
||
strong: '300', // 强烈震动
|
||
long: '800' // 长时间震动
|
||
},
|
||
|
||
// 用户震动设置
|
||
isVibrationEnabled: true,
|
||
|
||
// 执行震动
|
||
vibrate(duration, callback) {
|
||
if (!this.isVibrationEnabled) {
|
||
console.log('用户已禁用震动');
|
||
if (callback) callback('disabled');
|
||
return;
|
||
}
|
||
|
||
// 验证震动时长
|
||
const numDuration = parseInt(duration);
|
||
if (isNaN(numDuration) || numDuration <= 0) {
|
||
console.error('无效的震动时长:', duration);
|
||
if (callback) callback('invalid_duration');
|
||
return;
|
||
}
|
||
|
||
// 限制最大震动时长
|
||
const maxDuration = 2000; // 最大2秒
|
||
const safeDuration = Math.min(numDuration, maxDuration);
|
||
|
||
WebViewJavascriptBridge.callHandler('vibrator', safeDuration.toString(), (response) => {
|
||
console.log(`震动执行完成,时长: ${safeDuration}ms`);
|
||
if (callback) callback(null, safeDuration);
|
||
});
|
||
},
|
||
|
||
// 预设震动模式
|
||
vibrateWithMode(mode, callback) {
|
||
const duration = this.vibrationModes[mode];
|
||
if (!duration) {
|
||
console.error('未知的震动模式:', mode);
|
||
if (callback) callback('unknown_mode');
|
||
return;
|
||
}
|
||
|
||
this.vibrate(duration, callback);
|
||
},
|
||
|
||
// 按钮交互震动
|
||
buttonFeedback() {
|
||
this.vibrateWithMode('light');
|
||
},
|
||
|
||
// 操作成功震动
|
||
successFeedback() {
|
||
this.vibrateWithMode('medium');
|
||
},
|
||
|
||
// 错误反馈震动
|
||
errorFeedback() {
|
||
this.vibrateWithMode('strong');
|
||
},
|
||
|
||
// 警告震动
|
||
warningFeedback() {
|
||
this.vibrateWithMode('long');
|
||
},
|
||
|
||
// 设置震动开关
|
||
setVibrationEnabled(enabled) {
|
||
this.isVibrationEnabled = enabled;
|
||
console.log('震动设置:', enabled ? '已启用' : '已禁用');
|
||
|
||
// 保存到本地存储
|
||
localStorage.setItem('vibration_enabled', enabled.toString());
|
||
},
|
||
|
||
// 从本地存储加载震动设置
|
||
loadVibrationSettings() {
|
||
const saved = localStorage.getItem('vibration_enabled');
|
||
if (saved !== null) {
|
||
this.isVibrationEnabled = saved === 'true';
|
||
}
|
||
}
|
||
};
|
||
|
||
// 页面加载时初始化
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
VibrationManager.loadVibrationSettings();
|
||
});
|
||
|
||
// 使用示例
|
||
function setupButtonVibration() {
|
||
// 为所有按钮添加震动反馈
|
||
const buttons = document.querySelectorAll('button, .btn');
|
||
buttons.forEach(button => {
|
||
button.addEventListener('click', function() {
|
||
VibrationManager.buttonFeedback();
|
||
});
|
||
});
|
||
}
|
||
```
|
||
|
||
### HarmonyOS实现要点
|
||
- **接口名称**: `vibrator`
|
||
- **调用方向**: WebView → App
|
||
- **参数格式**: 字符串类型的毫秒数
|
||
- **权限要求**: 需要VIBRATE权限
|
||
- **时长限制**: 建议限制最大震动时长避免过度震动
|
||
- **设备兼容**: 检查设备是否支持震动功能
|
||
|
||
---
|
||
|
||
## 3. 重复震动接口 (repeatvibrator)
|
||
|
||
### 接口概述
|
||
当需要持续或重复的震动反馈时,通过此接口设置重复震动模式。支持连续震动和停止重复震动的控制。
|
||
|
||
### 工作流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant WebView as WebView
|
||
participant App as App
|
||
participant VibratorUtil as 震动工具类
|
||
participant SystemVibrator as 系统震动服务
|
||
|
||
WebView->>App: 调用repeatvibrator接口
|
||
App->>App: 解析重复模式参数
|
||
|
||
alt 启动重复震动 (repeat=1)
|
||
App->>VibratorUtil: 启动重复震动
|
||
VibratorUtil->>SystemVibrator: 设置震动模式
|
||
SystemVibrator->>SystemVibrator: 开始重复震动
|
||
loop 重复震动循环
|
||
SystemVibrator->>SystemVibrator: 震动-停止-震动
|
||
end
|
||
else 停止重复震动 (repeat=-1)
|
||
App->>VibratorUtil: 停止重复震动
|
||
VibratorUtil->>SystemVibrator: 取消震动模式
|
||
SystemVibrator->>SystemVibrator: 停止所有震动
|
||
end
|
||
|
||
App->>WebView: 返回操作结果
|
||
```
|
||
|
||
### 参数规范
|
||
|
||
#### 调用格式
|
||
```javascript
|
||
// 启动重复震动
|
||
WebViewJavascriptBridge.callHandler('repeatvibrator', '1', function(response) {
|
||
console.log('重复震动已启动');
|
||
});
|
||
|
||
// 停止重复震动
|
||
WebViewJavascriptBridge.callHandler('repeatvibrator', '-1', function(response) {
|
||
console.log('重复震动已停止');
|
||
});
|
||
```
|
||
|
||
#### 参数说明
|
||
| 参数 | 类型 | 必需 | 说明 | 取值 |
|
||
|------|------|------|------|------|
|
||
| repeat | string | ✓ | 重复震动模式 | "1"=启动重复震动, "-1"=停止重复震动 |
|
||
|
||
### 接口调用示例
|
||
|
||
#### 重复震动控制
|
||
```javascript
|
||
// 重复震动控制器
|
||
const RepeatVibrationController = {
|
||
isRepeating: false,
|
||
|
||
// 开始重复震动
|
||
startRepeatVibration() {
|
||
if (this.isRepeating) {
|
||
console.log('重复震动已在运行中');
|
||
return;
|
||
}
|
||
|
||
WebViewJavascriptBridge.callHandler('repeatvibrator', '1', (response) => {
|
||
console.log('重复震动已启动');
|
||
this.isRepeating = true;
|
||
this.updateUI(true);
|
||
});
|
||
},
|
||
|
||
// 停止重复震动
|
||
stopRepeatVibration() {
|
||
if (!this.isRepeating) {
|
||
console.log('重复震动未运行');
|
||
return;
|
||
}
|
||
|
||
WebViewJavascriptBridge.callHandler('repeatvibrator', '-1', (response) => {
|
||
console.log('重复震动已停止');
|
||
this.isRepeating = false;
|
||
this.updateUI(false);
|
||
});
|
||
},
|
||
|
||
// 切换重复震动状态
|
||
toggleRepeatVibration() {
|
||
if (this.isRepeating) {
|
||
this.stopRepeatVibration();
|
||
} else {
|
||
this.startRepeatVibration();
|
||
}
|
||
},
|
||
|
||
// 更新UI显示
|
||
updateUI(isRepeating) {
|
||
const toggleButton = document.getElementById('vibrationToggle');
|
||
const statusText = document.getElementById('vibrationStatus');
|
||
|
||
if (toggleButton) {
|
||
toggleButton.textContent = isRepeating ? '停止震动' : '开始震动';
|
||
toggleButton.classList.toggle('active', isRepeating);
|
||
}
|
||
|
||
if (statusText) {
|
||
statusText.textContent = isRepeating ? '震动中...' : '震动已停止';
|
||
}
|
||
}
|
||
};
|
||
```
|
||
|
||
#### 游戏场景中的重复震动
|
||
```javascript
|
||
// 游戏震动管理器
|
||
const GameVibrationManager = {
|
||
// 不同游戏状态的震动
|
||
gameStates: {
|
||
waiting: false,
|
||
playing: false,
|
||
warning: false
|
||
},
|
||
|
||
// 等待状态震动(心跳效果)
|
||
startWaitingVibration() {
|
||
if (this.gameStates.waiting) return;
|
||
|
||
this.gameStates.waiting = true;
|
||
RepeatVibrationController.startRepeatVibration();
|
||
console.log('等待状态震动已启动');
|
||
},
|
||
|
||
// 停止等待震动
|
||
stopWaitingVibration() {
|
||
if (!this.gameStates.waiting) return;
|
||
|
||
this.gameStates.waiting = false;
|
||
RepeatVibrationController.stopRepeatVibration();
|
||
console.log('等待状态震动已停止');
|
||
},
|
||
|
||
// 警告震动(危险提醒)
|
||
startWarningVibration() {
|
||
if (this.gameStates.warning) return;
|
||
|
||
this.gameStates.warning = true;
|
||
RepeatVibrationController.startRepeatVibration();
|
||
console.log('警告震动已启动');
|
||
|
||
// 10秒后自动停止
|
||
setTimeout(() => {
|
||
this.stopWarningVibration();
|
||
}, 10000);
|
||
},
|
||
|
||
// 停止警告震动
|
||
stopWarningVibration() {
|
||
if (!this.gameStates.warning) return;
|
||
|
||
this.gameStates.warning = false;
|
||
RepeatVibrationController.stopRepeatVibration();
|
||
console.log('警告震动已停止');
|
||
},
|
||
|
||
// 清理所有震动
|
||
stopAllVibrations() {
|
||
Object.keys(this.gameStates).forEach(state => {
|
||
this.gameStates[state] = false;
|
||
});
|
||
RepeatVibrationController.stopRepeatVibration();
|
||
console.log('所有游戏震动已清理');
|
||
}
|
||
};
|
||
```
|
||
|
||
### HarmonyOS实现要点
|
||
- **接口名称**: `repeatvibrator`
|
||
- **调用方向**: WebView → App
|
||
- **参数格式**: 字符串类型的重复模式标识
|
||
- **震动模式**: 1=启动重复,-1=停止重复
|
||
- **资源管理**: 及时停止重复震动避免电量消耗
|
||
- **用户体验**: 提供用户控制震动开关的选项
|
||
|
||
---
|
||
|
||
## 4. 取消震动接口 (canclevibrator)
|
||
|
||
### 接口概述
|
||
当需要立即停止所有震动效果时,通过此接口取消当前正在执行的震动,包括单次震动和重复震动。
|
||
|
||
### 工作流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant WebView as WebView
|
||
participant App as App
|
||
participant VibratorUtil as 震动工具类
|
||
participant SystemVibrator as 系统震动服务
|
||
|
||
WebView->>App: 调用canclevibrator接口
|
||
App->>VibratorUtil: 调用取消震动方法
|
||
VibratorUtil->>SystemVibrator: 停止所有震动
|
||
SystemVibrator->>SystemVibrator: 取消当前震动
|
||
SystemVibrator->>SystemVibrator: 清理震动队列
|
||
SystemVibrator->>VibratorUtil: 震动已取消
|
||
VibratorUtil->>App: 返回取消结果
|
||
App->>WebView: 返回操作确认
|
||
```
|
||
|
||
### 参数规范
|
||
|
||
#### 调用格式
|
||
```javascript
|
||
WebViewJavascriptBridge.callHandler('canclevibrator', '', function(response) {
|
||
console.log('所有震动已取消');
|
||
});
|
||
```
|
||
|
||
#### 参数说明
|
||
| 参数 | 类型 | 必需 | 说明 | 取值 |
|
||
|------|------|------|------|------|
|
||
| data | string | ✓ | 固定传入空字符串 | "" |
|
||
|
||
### 接口调用示例
|
||
|
||
#### 震动紧急停止
|
||
```javascript
|
||
// 紧急停止所有震动
|
||
function emergencyStopVibration() {
|
||
WebViewJavascriptBridge.callHandler('canclevibrator', '', function(response) {
|
||
console.log('紧急停止震动完成');
|
||
updateVibrationStatus('stopped');
|
||
});
|
||
}
|
||
|
||
// 更新震动状态显示
|
||
function updateVibrationStatus(status) {
|
||
const statusElement = document.getElementById('vibrationStatus');
|
||
if (statusElement) {
|
||
statusElement.textContent = status === 'stopped' ? '震动已停止' : '震动运行中';
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 综合震动管理系统
|
||
```javascript
|
||
// 震动系统管理器
|
||
const VibrationSystemManager = {
|
||
activeVibrations: new Set(),
|
||
|
||
// 注册震动
|
||
registerVibration(vibrationId) {
|
||
this.activeVibrations.add(vibrationId);
|
||
console.log(`震动已注册: ${vibrationId}`);
|
||
},
|
||
|
||
// 注销震动
|
||
unregisterVibration(vibrationId) {
|
||
this.activeVibrations.delete(vibrationId);
|
||
console.log(`震动已注销: ${vibrationId}`);
|
||
},
|
||
|
||
// 执行单次震动
|
||
executeSingleVibration(duration, vibrationId = null) {
|
||
const id = vibrationId || 'single_' + Date.now();
|
||
this.registerVibration(id);
|
||
|
||
WebViewJavascriptBridge.callHandler('vibrator', duration.toString(), (response) => {
|
||
this.unregisterVibration(id);
|
||
console.log(`单次震动完成: ${id}`);
|
||
});
|
||
|
||
return id;
|
||
},
|
||
|
||
// 开始重复震动
|
||
startRepeatVibration(vibrationId = null) {
|
||
const id = vibrationId || 'repeat_' + Date.now();
|
||
this.registerVibration(id);
|
||
|
||
WebViewJavascriptBridge.callHandler('repeatvibrator', '1', (response) => {
|
||
console.log(`重复震动开始: ${id}`);
|
||
});
|
||
|
||
return id;
|
||
},
|
||
|
||
// 停止重复震动
|
||
stopRepeatVibration(vibrationId) {
|
||
if (vibrationId) {
|
||
this.unregisterVibration(vibrationId);
|
||
}
|
||
|
||
WebViewJavascriptBridge.callHandler('repeatvibrator', '-1', (response) => {
|
||
console.log('重复震动已停止');
|
||
});
|
||
},
|
||
|
||
// 取消所有震动
|
||
cancelAllVibrations() {
|
||
console.log('正在取消所有震动...');
|
||
|
||
WebViewJavascriptBridge.callHandler('canclevibrator', '', (response) => {
|
||
// 清理所有注册的震动
|
||
this.activeVibrations.clear();
|
||
console.log('所有震动已取消');
|
||
|
||
// 更新UI状态
|
||
this.updateAllVibrationUI(false);
|
||
|
||
// 触发震动停止事件
|
||
this.triggerVibrationStoppedEvent();
|
||
});
|
||
},
|
||
|
||
// 更新所有震动相关UI
|
||
updateAllVibrationUI(isActive) {
|
||
// 更新所有震动按钮状态
|
||
const vibrationButtons = document.querySelectorAll('.vibration-btn');
|
||
vibrationButtons.forEach(btn => {
|
||
btn.classList.toggle('active', isActive);
|
||
btn.disabled = false;
|
||
});
|
||
|
||
// 更新状态指示器
|
||
const indicators = document.querySelectorAll('.vibration-indicator');
|
||
indicators.forEach(indicator => {
|
||
indicator.classList.toggle('active', isActive);
|
||
});
|
||
},
|
||
|
||
// 触发震动停止事件
|
||
triggerVibrationStoppedEvent() {
|
||
const event = new CustomEvent('vibrationStopped', {
|
||
detail: {
|
||
timestamp: Date.now(),
|
||
stoppedCount: this.activeVibrations.size
|
||
}
|
||
});
|
||
window.dispatchEvent(event);
|
||
},
|
||
|
||
// 获取当前震动状态
|
||
getVibrationStatus() {
|
||
return {
|
||
activeCount: this.activeVibrations.size,
|
||
activeVibrations: Array.from(this.activeVibrations),
|
||
hasActiveVibrations: this.activeVibrations.size > 0
|
||
};
|
||
}
|
||
};
|
||
|
||
// 监听震动停止事件
|
||
window.addEventListener('vibrationStopped', function(event) {
|
||
console.log('震动停止事件:', event.detail);
|
||
showMessage('所有震动已停止');
|
||
});
|
||
|
||
// 页面卸载时清理震动
|
||
window.addEventListener('beforeunload', function() {
|
||
VibrationSystemManager.cancelAllVibrations();
|
||
});
|
||
```
|
||
|
||
### HarmonyOS实现要点
|
||
- **接口名称**: `canclevibrator`
|
||
- **调用方向**: WebView → App
|
||
- **参数格式**: 空字符串
|
||
- **清理范围**: 取消所有类型的震动(单次、重复)
|
||
- **即时生效**: 立即停止正在执行的震动
|
||
- **资源释放**: 清理震动相关的系统资源
|
||
|
||
---
|
||
|
||
## 5. 社交分享接口 (friendsSharetypeUrlToptitleDescript)
|
||
|
||
### 接口概述
|
||
当WebView需要分享内容到社交平台时,通过此接口实现微信好友、微信朋友圈、抖音等平台的内容分享功能。支持链接分享和自定义分享内容。
|
||
|
||
### 工作流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 用户
|
||
participant WebView as WebView
|
||
participant App as App
|
||
participant SharePanel as 分享面板
|
||
participant WeChatSDK as 微信SDK
|
||
participant Platform as 分享平台
|
||
|
||
User->>WebView: 触发分享操作
|
||
WebView->>App: 调用friendsSharetypeUrlToptitleDescript接口
|
||
App->>App: 解析分享参数JSON
|
||
App->>App: 检查分享类型(好友/朋友圈)
|
||
|
||
alt 朋友圈分享 (sharefriend="2")
|
||
App->>WeChatSDK: 直接调用微信分享
|
||
WeChatSDK->>Platform: 打开微信朋友圈
|
||
Platform->>User: 显示分享界面
|
||
User->>Platform: 确认分享
|
||
Platform->>WeChatSDK: 分享完成回调
|
||
WeChatSDK->>App: 返回分享结果
|
||
else 好友分享 (sharefriend="1")
|
||
App->>SharePanel: 显示分享选择面板
|
||
SharePanel->>User: 展示可用分享方式
|
||
User->>SharePanel: 选择分享平台
|
||
SharePanel->>WeChatSDK: 调用对应平台SDK
|
||
WeChatSDK->>Platform: 执行分享操作
|
||
Platform->>User: 完成分享流程
|
||
end
|
||
|
||
App->>WebView: 返回分享结果
|
||
```
|
||
|
||
### 参数规范
|
||
|
||
#### 调用格式
|
||
```javascript
|
||
const shareData = {
|
||
sharefriend: "1", // 1=好友分享, 2=朋友圈分享
|
||
webpageUrl: "https://example.com/game",
|
||
title: "游戏分享标题",
|
||
description: "游戏分享描述",
|
||
type: "1",
|
||
sharetype: "1"
|
||
};
|
||
|
||
WebViewJavascriptBridge.callHandler('friendsSharetypeUrlToptitleDescript', JSON.stringify(shareData), function(response) {
|
||
console.log('分享请求已发送');
|
||
});
|
||
```
|
||
|
||
#### 参数说明
|
||
| 参数 | 类型 | 必需 | 说明 | 示例值 |
|
||
|------|------|------|------|--------|
|
||
| sharefriend | string | ✓ | 分享类型 | "1"=好友分享, "2"=朋友圈分享 |
|
||
| webpageUrl | string | ✓ | 分享链接地址 | "https://game.example.com/share" |
|
||
| title | string | ✓ | 分享标题 | "精彩游戏邀请您体验" |
|
||
| description | string | ✓ | 分享描述 | "快来加入我们的游戏吧!" |
|
||
| type | string | ✗ | 分享内容类型 | "1"=链接分享, "3"=图片分享 |
|
||
| sharetype | string | ✗ | 分享方式类型 | "1"=普通分享, "3"=图片链接分享 |
|
||
|
||
#### 分享类型说明
|
||
| sharefriend值 | 分享目标 | 说明 | 用户体验 |
|
||
|---------------|----------|------|----------|
|
||
| "1" | 好友分享 | 显示分享选择面板 | 可选择多种分享方式 |
|
||
| "2" | 朋友圈分享 | 直接调用微信朋友圈 | 直接跳转到微信 |
|
||
|
||
### 接口调用示例
|
||
|
||
#### 游戏成就分享
|
||
```javascript
|
||
// 分享游戏成就到朋友圈
|
||
function shareAchievementToMoments(achievementData) {
|
||
const shareData = {
|
||
sharefriend: "2", // 朋友圈分享
|
||
webpageUrl: `https://game.example.com/achievement/${achievementData.id}`,
|
||
title: `我在游戏中获得了"${achievementData.title}"成就!`,
|
||
description: `${achievementData.description} 快来挑战吧!`,
|
||
type: "1",
|
||
sharetype: "1"
|
||
};
|
||
|
||
WebViewJavascriptBridge.callHandler('friendsSharetypeUrlToptitleDescript', JSON.stringify(shareData), function(response) {
|
||
console.log('成就分享到朋友圈已发送');
|
||
trackShareEvent('achievement', 'moments');
|
||
});
|
||
}
|
||
|
||
// 分享邀请给好友
|
||
function shareInviteToFriends(inviteCode) {
|
||
const shareData = {
|
||
sharefriend: "1", // 好友分享
|
||
webpageUrl: `https://game.example.com/invite/${inviteCode}`,
|
||
title: "游戏邀请",
|
||
description: `我邀请你一起来玩游戏!邀请码:${inviteCode}`,
|
||
type: "1",
|
||
sharetype: "1"
|
||
};
|
||
|
||
WebViewJavascriptBridge.callHandler('friendsSharetypeUrlToptitleDescript', JSON.stringify(shareData), function(response) {
|
||
console.log('邀请分享已发送');
|
||
trackShareEvent('invite', 'friends');
|
||
});
|
||
}
|
||
```
|
||
|
||
#### 完整的分享管理系统
|
||
```javascript
|
||
// 分享管理器
|
||
const ShareManager = {
|
||
// 分享配置
|
||
shareConfig: {
|
||
baseUrl: 'https://game.example.com',
|
||
defaultImage: 'https://game.example.com/images/share-default.jpg',
|
||
appName: '精彩游戏'
|
||
},
|
||
|
||
// 分享模板
|
||
shareTemplates: {
|
||
achievement: {
|
||
title: '我在{appName}中获得了"{achievementName}"成就!',
|
||
description: '快来挑战这个{difficulty}难度的成就吧!'
|
||
},
|
||
invite: {
|
||
title: '{appName}游戏邀请',
|
||
description: '我邀请你一起来玩{appName}!使用邀请码{inviteCode}可以获得特殊奖励。'
|
||
},
|
||
score: {
|
||
title: '我在{appName}中获得了{score}分!',
|
||
description: '快来超越我的记录吧!'
|
||
}
|
||
},
|
||
|
||
// 生成分享链接
|
||
generateShareUrl(type, params = {}) {
|
||
const baseUrl = this.shareConfig.baseUrl;
|
||
const queryParams = new URLSearchParams({
|
||
shareType: type,
|
||
timestamp: Date.now(),
|
||
...params
|
||
});
|
||
|
||
return `${baseUrl}/share/${type}?${queryParams.toString()}`;
|
||
},
|
||
|
||
// 渲染分享模板
|
||
renderTemplate(templateKey, data) {
|
||
const template = this.shareTemplates[templateKey];
|
||
if (!template) {
|
||
console.error('未找到分享模板:', templateKey);
|
||
return null;
|
||
}
|
||
|
||
const result = {
|
||
title: this.replacePlaceholders(template.title, data),
|
||
description: this.replacePlaceholders(template.description, data)
|
||
};
|
||
|
||
return result;
|
||
},
|
||
|
||
// 替换模板占位符
|
||
replacePlaceholders(text, data) {
|
||
return text.replace(/\{(\w+)\}/g, (match, key) => {
|
||
return data[key] || match;
|
||
});
|
||
},
|
||
|
||
// 执行分享
|
||
share(shareType, targetType, shareData) {
|
||
// 生成分享内容
|
||
const content = this.renderTemplate(shareType, shareData);
|
||
if (!content) {
|
||
console.error('生成分享内容失败');
|
||
return;
|
||
}
|
||
|
||
// 生成分享链接
|
||
const shareUrl = this.generateShareUrl(shareType, shareData);
|
||
|
||
// 构建分享参数
|
||
const shareParams = {
|
||
sharefriend: targetType, // "1"=好友, "2"=朋友圈
|
||
webpageUrl: shareUrl,
|
||
title: content.title,
|
||
description: content.description,
|
||
type: "1",
|
||
sharetype: "1"
|
||
};
|
||
|
||
console.log('执行分享:', shareParams);
|
||
|
||
WebViewJavascriptBridge.callHandler(
|
||
'friendsSharetypeUrlToptitleDescript',
|
||
JSON.stringify(shareParams),
|
||
(response) => {
|
||
console.log('分享执行完成');
|
||
this.onShareComplete(shareType, targetType, shareData);
|
||
}
|
||
);
|
||
},
|
||
|
||
// 分享完成回调
|
||
onShareComplete(shareType, targetType, shareData) {
|
||
// 记录分享事件
|
||
this.trackShare(shareType, targetType);
|
||
|
||
// 显示分享完成提示
|
||
this.showShareSuccessMessage(targetType);
|
||
|
||
// 触发分享完成事件
|
||
this.triggerShareEvent(shareType, targetType, shareData);
|
||
},
|
||
|
||
// 分享事件跟踪
|
||
trackShare(shareType, targetType) {
|
||
const eventData = {
|
||
event: 'share',
|
||
shareType: shareType,
|
||
targetType: targetType === '1' ? 'friends' : 'moments',
|
||
timestamp: Date.now()
|
||
};
|
||
|
||
console.log('分享事件跟踪:', eventData);
|
||
// 这里可以调用分析SDK记录事件
|
||
},
|
||
|
||
// 显示分享成功消息
|
||
showShareSuccessMessage(targetType) {
|
||
const target = targetType === '1' ? '好友' : '朋友圈';
|
||
showMessage(`分享到${target}成功!`);
|
||
},
|
||
|
||
// 触发分享事件
|
||
triggerShareEvent(shareType, targetType, shareData) {
|
||
const event = new CustomEvent('shareCompleted', {
|
||
detail: {
|
||
shareType: shareType,
|
||
targetType: targetType,
|
||
shareData: shareData,
|
||
timestamp: Date.now()
|
||
}
|
||
});
|
||
window.dispatchEvent(event);
|
||
},
|
||
|
||
// 快捷分享方法
|
||
shareToFriends(shareType, shareData) {
|
||
this.share(shareType, '1', shareData);
|
||
},
|
||
|
||
shareToMoments(shareType, shareData) {
|
||
this.share(shareType, '2', shareData);
|
||
}
|
||
};
|
||
|
||
// 使用示例
|
||
function shareGameAchievement(achievement) {
|
||
const shareData = {
|
||
appName: ShareManager.shareConfig.appName,
|
||
achievementName: achievement.name,
|
||
difficulty: achievement.difficulty,
|
||
achievementId: achievement.id
|
||
};
|
||
|
||
// 分享到朋友圈
|
||
ShareManager.shareToMoments('achievement', shareData);
|
||
}
|
||
|
||
function shareInvitation(inviteCode) {
|
||
const shareData = {
|
||
appName: ShareManager.shareConfig.appName,
|
||
inviteCode: inviteCode
|
||
};
|
||
|
||
// 分享给好友
|
||
ShareManager.shareToFriends('invite', shareData);
|
||
}
|
||
|
||
// 监听分享完成事件
|
||
window.addEventListener('shareCompleted', function(event) {
|
||
console.log('分享完成事件:', event.detail);
|
||
});
|
||
```
|
||
|
||
### HarmonyOS实现要点
|
||
- **接口名称**: `friendsSharetypeUrlToptitleDescript`
|
||
- **调用方向**: WebView → App
|
||
- **参数格式**: JSON字符串,包含分享相关的所有参数
|
||
- **平台支持**: 微信好友、微信朋友圈、可扩展其他平台
|
||
- **SDK集成**: 需要集成微信SDK等第三方分享SDK
|
||
- **用户体验**: 根据分享类型提供不同的交互流程
|
||
- **错误处理**: 处理分享失败、用户取消等情况
|
||
|
||
---
|
||
|
||
## 文档关联
|
||
|
||
本文档是TSGame JSBridge接口规范的第四部分,完整文档包括:
|
||
|
||
1. **用户认证与页面管理** - 登录、页面跳转、语音控制
|
||
2. **系统功能与交互** - 剪贴板、游戏状态、设备检测
|
||
3. **位置与媒体服务** - GPS定位、音频播放
|
||
4. **高级功能与扩展** (本文档) - 录音、震动、分享
|
||
|
||
---
|
||
|
||
**文档维护**: TSGame开发团队
|
||
**最后更新**: 2025年7月13日
|
||
**版本**: v1.9
|
||
**联系方式**: 技术支持组
|