更新记录
1.0.0(2026-08-10)
首发
平台兼容性
uni-app
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | - | - | - | - | - | 5.0 | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | 5.0 | - | - | - |
call-auto-record
Android 原生 UTS 插件,提供通话记录查询、通话录音文件扫描、录音文件复制上传、通话录音设置检测等功能。
基本信息
| 项目 | 说明 |
|---|---|
| 插件 ID | call-auto-record |
| 版本 | 1.0.0 |
| 平台 | Android(arm64-v8a、armeabi-v7a) |
| 最低版本 | Android 5.0(API 21) |
| 最高兼容 | Android 15(API 35) |
| 框架支持 | uni-app(Vue2/Vue3)、uni-app-x |
| HBuilderX | ^3.7.0 |
功能列表
| 序号 | 功能 | API |
|---|---|---|
| 1 | 批量申请权限 | requestPermissions(options) |
| 2 | 获取所有通话记录 | getAllCallLogs(options) |
| 3 | 条件查询通话记录 | queryCallLogs(options) |
| 4 | 检测通话自动录音是否开启 | checkCallRecording(options) |
| 5 | 跳转到通话录音设置页 | gotoCallRecordingSettings(options) |
| 6 | 获取所有录音文件 | getAllRecordFiles(options) |
| 7 | 条件搜索录音文件 | searchRecordFiles(options) |
| 8 | 复制录音文件到应用目录 | copyFileToAppDir(options) |
| 9 | 开启通话监听 | startCallMonitor(options) |
| 10 | 停止通话监听 | stopCallMonitor(options) |
快速开始
导入插件
import {
requestPermissions,
getAllCallLogs,
queryCallLogs,
checkCallRecording,
gotoCallRecordingSettings,
getAllRecordFiles,
searchRecordFiles,
copyFileToAppDir,
startCallMonitor,
stopCallMonitor
} from '@/uni_modules/call-auto-record'
申请权限
使用其他功能前,请先申请必要权限:
requestPermissions({
permissions: 'android.permission.READ_PHONE_STATE,android.permission.READ_CALL_LOG,android.permission.READ_EXTERNAL_STORAGE,android.permission.READ_MEDIA_AUDIO',
success: (raw) => {
const result = JSON.parse(raw);
console.log('全部授予:', result.allGranted);
console.log('已授予数量:', result.grantedList.length);
if (result.deniedList.length > 0) {
console.log('未授予:', JSON.stringify(result.deniedList));
}
},
fail: (err) => {
console.error('权限请求失败:', err);
}
});
API 详细说明
1. requestPermissions - 批量申请权限
参数 RequestPermissionsOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| permissions | string | 是 | 逗号分隔的权限字符串 |
| success | (res: string) => void | 否 | 成功回调,返回 JSON 字符串 |
| fail | (err: any) => void | 否 | 失败回调 |
| complete | (res: any) => void | 否 | 完成回调 |
success 回调返回 JSON 结构:
{
"allGranted": true,
"grantedList": ["android.permission.READ_PHONE_STATE", "..."],
"deniedList": []
}
2. getAllCallLogs - 获取所有通话记录
参数 GetAllCallLogsOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | (res: string) => void | 否 | 成功回调,返回 JSON 数组字符串 |
| fail | (err: any) => void | 否 | 失败回调 |
| complete | (res: any) => void | 否 | 完成回调 |
success 回调返回 JSON 数组,每个元素结构:
{
"number": "***",
"name": "张三",
"type": 1,
"duration": 120,
"date": 1718500000
}
| 字段 | 类型 | 说明 |
|---|---|---|
| number | string | 电话号码 |
| name | string | 联系人名称(无则为空) |
| type | number | 通话类型:1=来电,2=去电,3=未接 |
| duration | number | 通话时长(秒) |
| date | number | 通话时间戳(毫秒) |
使用示例:
getAllCallLogs({
success: (raw) => {
const list = JSON.parse(raw);
console.log('通话记录数量:', list.length);
list.forEach(item => {
const typeMap = { 1: '来电', 2: '去电', 3: '未接' };
console.log(`${item.number} - ${typeMap[item.type]} - ${item.duration}秒`);
});
},
fail: (err) => {
console.error('查询失败:', err);
}
});
3. queryCallLogs - 条件查询通话记录
参数 QueryCallLogsOptions:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| number | string | 否 | "" | 按号码精确查询 |
| type | number | 否 | 0 | 通话类型:0=全部,1=来电,2=去电,3=未接 |
| startTime | number | 否 | 0 | 起始时间戳(毫秒),0=不限 |
| endTime | number | 否 | 0 | 截止时间戳(毫秒),0=不限 |
| limit | number | 否 | 500 | 返回最大条数 |
| success | (res: string) => void | 否 | - | 成功回调 |
| fail | (err: any) => void | 否 | - | 失败回调 |
| complete | (res: any) => void | 否 | - | 完成回调 |
使用示例:
// 查询最近7天的来电记录
const now = Date.now();
queryCallLogs({
type: 1,
startTime: now - 7 * 24 * 60 * 60 * 1000,
limit: 100,
success: (raw) => {
const list = JSON.parse(raw);
console.log('查询到', list.length, '条来电记录');
}
});
4. checkCallRecording - 检测通话自动录音状态
参数 CheckCallRecordingOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | (res: boolean) => void | 否 | 成功回调,true=已开启 |
| fail | (err: any) => void | 否 | 失败回调 |
| complete | (res: any) => void | 否 | 完成回调,返回详细 JSON |
complete 回调返回 JSON 结构:
{
"enabled": true,
"detectable": true,
"foundKey": "button_auto_record_call"
}
| 字段 | 说明 |
|---|---|
| enabled | 录音功能是否开启 |
| detectable | 是否能检测到该设置(false 表示设备不支持自动检测) |
| foundKey | 检测到的 Settings 键名 |
兼容性说明: 支持小米、华为、OPPO、vivo 等主流品牌,通过遍历
Settings.System、Settings.Global、Settings.Secure三级存储和 12 个品牌专属键名检测。华为部分机型可能无法自动检测。
使用示例:
checkCallRecording({
success: (enabled) => {
console.log('通话自动录音:', enabled ? '已开启' : '未开启');
},
complete: (raw) => {
if (raw) {
const info = JSON.parse(raw);
if (!info.detectable) {
console.log('当前设备无法自动检测,请手动检查');
}
}
}
});
5. gotoCallRecordingSettings - 跳转通话录音设置
参数 GotoCallRecordingSettingsOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | (res: boolean) => void | 否 | 成功回调,true=跳转成功 |
| fail | (err: any) => void | 否 | 失败回调 |
| complete | (res: any) => void | 否 | 完成回调 |
兼容性说明: 内置 MIUI、华为等品牌的录音设置 Activity 路径,若均不匹配则 fallback 到应用设置页或系统设置页。
使用示例:
gotoCallRecordingSettings({
success: (ok) => {
console.log('跳转录音设置:', ok ? '成功' : '失败');
}
});
6. getAllRecordFiles - 获取所有录音文件
参数 GetAllRecordFilesOptions:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| allAudio | boolean | 否 | false | true=返回所有音频文件,false=只返回录音目录文件 |
| success | (res: string) => void | 否 | - | 成功回调,返回 JSON 数组字符串 |
| fail | (err: any) => void | 否 | - | 失败回调 |
| complete | (res: any) => void | 否 | - | 完成回调 |
success 回调返回 JSON 数组,每个元素结构:
{
"fileName": "CallRecording_20240601_incoming_13800138000.mp3",
"filePath": "/storage/emulated/0/CallRecordings/CallRecording_20240601_incoming_13800138000.mp3",
"fileSize": 1234567,
"dateModified": 1717200000,
"duration": 120,
"number": "***",
"callType": "incoming"
}
| 字段 | 类型 | 说明 |
|---|---|---|
| fileName | string | 文件名 |
| filePath | string | 文件绝对路径 |
| fileSize | number | 文件大小(字节) |
| dateModified | number | 最后修改时间戳(秒) |
| duration | number | 音频时长(秒),获取失败为 -1 |
| number | string | 从文件名解析的号码(可能为空) |
| callType | string | 通话类型:incoming/outgoing/unknown |
机型适配: 默认模式自动过滤 40+ 种品牌录音目录关键字(小米、华为、三星、OPPO、vivo 等)。若设备录音路径不在已知列表中,可传
allAudio: true返回所有音频文件。
使用示例:
getAllRecordFiles({
success: (raw) => {
const list = JSON.parse(raw);
console.log('录音文件数量:', list.length);
list.forEach(item => {
console.log(`${item.fileName} (${item.fileSize / 1024}KB) - ${item.duration}秒`);
});
},
fail: (err) => {
console.error('查询失败:', err);
}
});
7. searchRecordFiles - 条件搜索录音文件
参数 SearchRecordFilesOptions:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| keyword | string | 否 | "" | 文件名关键字(模糊匹配) |
| number | string | 否 | "" | 号码过滤(包含匹配) |
| startTime | number | 否 | 0 | 修改时间起始(秒级时间戳),0=不限 |
| endTime | number | 否 | 0 | 修改时间截止(秒级时间戳),0=不限 |
| minSize | number | 否 | 0 | 最小文件大小(字节),0=不限 |
| maxSize | number | 否 | 0 | 最大文件大小(字节),0=不限 |
| limit | number | 否 | 200 | 返回数量上限 |
| allAudio | boolean | 否 | false | true=搜索所有音频文件 |
| success | (res: string) => void | 否 | - | 成功回调 |
| fail | (err: any) => void | 否 | - | 失败回调 |
| complete | (res: any) => void | 否 | - | 完成回调 |
使用示例:
// 搜索号码包含"10086"且大于100KB的录音
searchRecordFiles({
number: '10086',
minSize: 102400,
limit: 50,
success: (raw) => {
const list = JSON.parse(raw || '[]');
console.log('匹配到', list.length, '个录音文件');
list.forEach(item => {
console.log(`${item.fileName} - ${item.number} - ${item.duration}秒`);
});
}
});
8. copyFileToAppDir - 复制录音文件到应用目录
将录音文件复制到应用外部私有目录,复制后的文件路径可在文件管理器中查看,也可用于上传。
参数 CopyFileToAppDirOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| filePath | string | 是 | 源文件的绝对路径 |
| success | (res: string) => void | 否 | 成功回调,返回复制后的新路径 |
| fail | (err: any) => void | 否 | 失败回调 |
| complete | (res: any) => void | 否 | 完成回调 |
目标路径:
/storage/emulated/0/Android/data/包名/files/call_records/时间戳_原文件名
使用示例:
copyFileToAppDir({
filePath: '/storage/emulated/0/CallRecordings/recording.mp3',
success: (newPath) => {
console.log('复制成功,新路径:', newPath);
// 用新路径上传
uni.uploadFile({
url: 'https://your-server.com/upload',
filePath: newPath,
name: 'file',
success: (res) => {
console.log('上传成功:', res.statusCode);
}
});
},
fail: (err) => {
console.error('复制失败:', err);
}
});
9. startCallMonitor - 开启通话监听
通过 ContentObserver 监听通话记录变化,当有新的通话事件(来电、去电、挂断等)时,通过 onEvent 持续回调返回数据。
参数 StartCallMonitorOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| onEvent | (res: string) => void | 否 | 通话事件持续回调,每次通话记录变化时触发 |
| success | (res: string) => void | 否 | 成功回调,返回“通话监听已开启” |
| fail | (err: any) => void | 否 | 失败回调 |
| complete | (res: any) => void | 否 | 完成回调 |
onEvent 回调返回 JSON 结构:
{
"number": "***",
"name": "张三",
"type": 1,
"duration": 120,
"date": 1718500000
}
| 字段 | 类型 | 说明 |
|---|---|---|
| number | string | 电话号码 |
| name | string | 联系人名称(无则为空) |
| type | number | 通话类型:1=来电,2=去电,3=未接 |
| duration | number | 通话时长(秒) |
| date | number | 通话时间戳(毫秒) |
实现原理: 使用
ContentObserver监听CallLog.Calls.CONTENT_URI,当通话记录数据库发生变化时自动触发回调,查询最新一条通话记录并返回。兼容 Android 5.0~15,不使用已废弃的PhoneStateListener。
使用示例:
startCallMonitor({
onEvent: (raw) => {
const item = JSON.parse(raw);
const typeMap = { 1: '来电', 2: '去电', 3: '未接' };
const date = new Date(item.date).toLocaleString();
console.log(`通话事件: ${item.name || item.number}`);
console.log(` 类型: ${typeMap[item.type]} | 时长: ${item.duration}s | 时间: ${date}`);
},
success: (msg) => {
console.log(msg);
},
fail: (err) => {
console.error('开启通话监听失败:', err);
}
});
10. stopCallMonitor - 停止通话监听
取消已注册的通话监听器。
参数 StopCallMonitorOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| success | (res: string) => void | 否 | 成功回调,返回“通话监听已停止” |
| fail | (err: any) => void | 否 | 失败回调 |
| complete | (res: any) => void | 否 | 完成回调 |
使用示例:
stopCallMonitor({
success: (msg) => {
console.log(msg);
},
fail: (err) => {
console.error('停止通话监听失败:', err);
}
});
权限说明
插件自动声明以下权限,使用前请通过 requestPermissions 动态申请:
| 权限 | 用途 | 备注 |
|---|---|---|
READ_PHONE_STATE |
读取电话状态 | 基础权限 |
READ_CALL_LOG |
读取通话记录 | 通话记录查询必需 |
READ_EXTERNAL_STORAGE |
读取外部存储 | Android 12 及以下 |
READ_MEDIA_AUDIO |
读取音频文件 | Android 13+ 必需 |
机型适配
录音文件扫描
插件通过 MediaStore 查询设备上所有音频文件,并根据路径关键字过滤录音文件。已覆盖以下品牌:
| 品牌 | 录音路径示例 |
|---|---|
| 小米/MIUI | MIUI/sound_recorder/、MIUI/soundrecorder/ |
| 华为/荣耀 | Huawei/CallRecord/、Honor/CallRecord/ |
| 三星 | Sounds/call/、Music/Voice Recorder/ |
| OPPO/realme | OPPO/CallRecord/、Recordings/CallRecord/ |
| vivo/iQOO | Record/CallRecord/、vivo/CallRecord/ |
| 一加 | OnePlus/CallRecordings/ |
| 联想/摩托罗拉 | Lenovo/CallRecord/、Motorola/CallRecord/ |
| 中兴/红魔 | ZTE/CallRecord/、Nubia/CallRecord/ |
若录音文件路径不在以上列表中,可使用 allAudio: true 返回所有音频文件,或使用 searchRecordFiles 按关键字搜索。
通话录音检测
支持检测 12 个品牌专属 Settings 键名,兼容小米、华为、OPPO、vivo 等品牌。华为部分机型可能无法自动检测(detectable 返回 false)。
注意事项
- 回调返回 JSON 字符串: 由于 UTS 插件 JS 桥的限制,所有含数组的回调结果以 JSON 字符串形式返回,需使用
JSON.parse()解析。 - MediaStore 缓存: MediaStore 数据库可能包含已删除文件的缓存记录,插件已自动过滤不存在的文件。
- 权限动态申请: Android 6.0+ 需要动态申请敏感权限,请先调用
requestPermissions。 - 文件复制路径: 复制后的文件位于
/storage/emulated/0/Android/data/包名/files/call_records/,卸载应用时会自动清理。

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 0
赞赏 0
下载 12495974
赞赏 1939
赞赏
京公网安备:11010802035340号