更新记录

2.0.0(2023-12-23)

  • 全新通知条

    支持自定义图片、通知标题、通知内容,支持上一首、下一首、播放、暂停按钮事件监听

    支持通知布局界面跟随日间夜间主题模式切换

  • 新增跳转到通知设置页面接口 openNotifySetting

  • 新增通话状态回调监听

  • 新增日渐夜间模式切换回调监听


平台兼容性

Android Android CPU类型 iOS
适用版本区间:8.0 - 14.0 armeabi-v7a:支持,arm64-v8a:支持,x86:支持 ×

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


文字转语音多功能通知版 - 更新日志

2.0.0(2023-12-18)

老版本传送门:https://ext.dcloud.net.cn/plugin?id=899

此版本需设置manifest.json中的 APP常用其他设置 -> minSdkVersion = 26,否则无法正常打包。

  • 全新通知条

支持自定义图片、通知标题、通知内容,支持上一首、下一首、播放、暂停按钮事件监听

支持通知布局界面跟随日间夜间主题模式切换

  • 新增跳转到通知设置页面接口 openNotifySetting
  • 新增通话状态回调监听
  • 新增日渐夜间模式切换回调监听

针对上架各家应用商店所做的调整

  • 修正耳机监听初始化逻辑,将自动监听改为手动监听(应用宝)
  • 将sdk版本调整为min26,target33(小米)
注:不可与老版本同时混用

特别鸣谢:

@胖虎777(TT阅读器:http://tt.oxking.cn)

@**276***@qq.com(安卓通知栏播放器:https://ext.dcloud.net.cn/plugin?id=9018)

介绍

TTS(Text To Speech,文本转语音)是语音合成应用的一种,它将储存于电脑中的文件,如帮助文件或者网页,转换成自然语音输出。

使用说明

需要搭配第三方语音引擎实现中文转语音(一般来说手机都会自带语音引擎,如果没有的话可以自行下载安装,讯飞等TTS语音引擎)

测试机型

华为MATE20 、华为 MATE20PRO、小米MIX2S、PDA安卓10系统、 vivo S9e、小米10 至尊纪念版、红米 9、Vivo X70、OPPO Find X5 Pro、真我 8 5G等

测试安卓版本

安卓9~安卓14

接口说明

  • init(JSCallback jsCallback, JSONObject options) options可不传。 options.savePath 初始化音频文件保存目录
TTSSpeaker.init(
    function(result) {
        // result有两个状态,code = 0 初始化正常 code > 0 初始化失败
        if (result.code > 0) {
            uni.showToast({title: result.msg});
            return false;
        }
        // 此处注意,需要根据实际返回内容进行json格式判断是否需要parse
        // init回调内不可调用任何tts插件方法,如speak、setVoiceSpeed等,因为这些方法全部基于init初始化方法创建的tts对象,此处回调是在init tts对象内,若在此处调用基于tts对象的方法将报错
        let obj = JSON.parse(result.data)
        // 返回设置的语速和音调
        _this.pitch = obj.voice_pitch;
        _this.speed = obj.voice_speed;
        // 返回当前已安装的引擎列表
        _this.engineList = JSON.parse(obj.engines);
        _this.engineList.forEach(v => {
        _this.array.push(v.app_name)
        })
        uni.showToast({
            title: JSON.stringify(result),
            icon: 'none'
        });
    },
    {
        savePath: '',    // 音频保存目录
        engine: engine | 'com.iflytek.speechsuite'    // 自定义语音引擎 使用 getEngines 方法返回的 package_name ,留空默认使用设备默认引擎
    }
);
  • speak(String words, Integer model, String taskId)

    words:待播放的文字 model: 1 丢弃之前的播报任务,立即播报本次内容; 2 播放完之前的语音任务后才播报本次内容; taskid:自定播放任务id,用于监听播放进度回调,id全局唯一,不可重复

  • setVoiceSpeed(Float speed, JSCallback jsCallback) 设置语速,最高为3

  • setVoicePicth(Float speed, JSCallback jsCallback) 设置语调,最高为3(有些手机不支持)

  • stop() 停止播放

  • saveAudioFile(JSONObject options, JSCallback jsCallback) 保存合成音频

  • destorySpeaker() 销毁注册的播放任务

  • getDefaultEngine() 获取当前系统默认语音引擎包名,若为空则说明系统内缺少TTS引擎,需要下载安装(讯飞等)

  • playerSpeak(String words, String savePath, JSCallback jsCallback)音频模式-生成文件并播放,返回文件目录

  • playerPlay(String audioPath); 播放本地音频

  • playerStop() 停止播放

  • playerResume() 恢复播放

  • playerPause() 暂停播放

  • getFolderSize(String path) 递归获取指定目录下总文件大小,留空默认目录为 /storage/emulated/0/Android/data/包名/cache/voices/

  • getCurrentFolderSize(String path) 只获取指定目录下总文件大小,留空默认目录为 /storage/emulated/0/Android/data/包名/cache/voices/

  • deleteFolderFile(String path, Boolean deleteSelf) 递归删除指定目录下的文件夹及文件 deleteSelf:是否同时删除祖目录

  • deleteFile(String path) 删除指定目录下的文件

  • goBatterySetting() 跳转到电池保护设置页面

  • goAutoStartSetting() 跳转到应用自启动设置页面

  • checkNotifyEnabled() 检查是否有允许通知权限

  • checkFilePermission() 检查是否有允许文件读写权限

通知栏

  • startForeground(JSONObject options, UniJSCallback callback) 创建通知
  TTSSpeaker.startForeground({
      notifyType: 'normal',       // normal 普通自定义布局, media 媒体通知布局
      title: '水浒传',             // 书名
      subTitle: '第一章',          // 章节
      image: '',                  // 封面图,支持远程(http|https)或本地(plus.io.convertLocalFileSystemURL(plus.io.PRIVATE_WWW).slice(0, -1))
      keepAlive: 60               // 通知保活周期,单位:秒。最低60秒
  },
  data => {
      console.log(data);
      uni.showToast({
        title: data.type,
        icon: 'none'
      });
      switch (data.type) {
        case 'play':
            // 点击播放按钮
            break;
        case 'pause':
            // 点击暂停按钮
            break;
        case 'next':
            // 点击下一章
            break;
        case 'pre':
            // 点击上一章
            break;
      }
  });
  • setlastOrnext(JSONObject options) 设置上一章、下一章按钮是否可点击
TTSSpeaker.setlastOrnext({
    last: false,        // 上一章
    next: true          // 下一章
});
  • setTitleOrimage(JSONObject options) 更新书名、章节、封面图
TTSSpeaker.setTitleOrimage({
    title: '水浒传',     // 书名
    subTitle: '第二章',  // 章节
    image: ''           // 封面图
});
  • setplayicon(Boolean isPlay) 设置播放状态,注意是布尔型,不是字符串 true 正在播放 false 暂停播放
TTSSpeaker.setplayicon(true);
  • setOptions(JSONObject options) 统一更新通知布局
TTSSpeaker.setOptions({
    title: '水浒传',     // 书名
    subTitle: '第三章',  // 章节
    image: '',          // 封面图
    last: true,         // 上一章按钮是否可用
    next: false,        // 下一章按钮是否可用
    isPlay: false       // 是否在播放
});
  • stopForeground() 停止前台服务

回调监听

const speakListener = weex.requireModule('globalEvent');

// TTS实时模式监听播放状态
speakListener.addEventListener('speakListener', function(e) {
    // {"data":{"taskid":"666234324563543","code":1,"msg":"播放开始"},"code":0,"msg":"实时播放任务监听"}
    //  data.code 1 播放开始 2 播放结束 -1 播放失败
    console.log(e);

    if (e.data.code == 2) {
        TTSSpeaker.speak(this.words, this.playModel + 1);
    }
});

// 文字转音频播放监听播放状态
speakListener.addEventListener('mediaListener', function(e) {
    // {"data":{"status":1,"data":{"position":97,"progress":6792},"msg":"正在播放"},"code":0,"msg":"音频模式播放任务监听"}
    //  data.status 1 正在播放 2 播放结束 -1 播放失败;data.data.position 播放进度百分比 data.data.progress 播放进度
    console.log(e);
});

// 耳机
speakListener.addEventListener('headsetListener', function(e) {
    // {"data":{"code":0,"msg":"有线耳机已拔出"},"code":0,"msg":"实时播放任务监听"}
    // {"data":{"code":11,"msg":"蓝牙耳机已连接"},"code":1,"msg":"耳机状态监听"}
    // e.code 0 耳机已拔出或断开 1 耳机已连接
    console.log(e);
});

// 通话状态
speakListener.addEventListener('phoneCallListener', function(e) {
    // {"data":{"code":0,"msg":"通话结束或未通话"},"code":0,"msg":"通话状态监听"}
    // {"data":{"code":1,"msg":"来电响铃"},"code":1,"msg":"通话状态监听"}
    // {"data":{"code":2,"msg":"接听电话或拨出电话"},"code":1,"msg":"通话状态监听"}
    // e.code 0 通话结束或未通话 1 来电响铃 2 正在接听电话或拨出电话
    console.log(e);
});

// 系统日夜模式切换
speakListener.addEventListener('uimodeListener', function(e) {
    uni.showToast({
        title: e.code,
        icon: 'none'
    });
});

示例代码

<template>
    <view class="uni-padding-wrap">
        <view><textarea maxlength="-1" v-model="words" placeholder="输入要说的内容"></textarea></view>
        <view>
            <text>{{ tips }}</text>
        </view>
        <view class="uni-title">设置语速</view>
        <view>
            <slider v-model="speed" step="0.5" min="0.5" max="3" @change="setVoiceSpeed" show-value />
        </view>

        <view class="uni-title">设置音调</view>
        <view>
            <slider v-model="pitch" step="0.5" min="0.5" max="3" @change="setVoicePicth" show-value />
        </view>

        <view>
            <view class="uni-list">
                <view class="uni-list-cell">
                    <view class="uni-list-cell-left">当前选择</view>
                    <view class="uni-list-cell-db">
                        <picker @change="bindPickerChange" :value="index" :range="array">
                            <view class="uni-input">{{ array[index] }}</view>
                        </picker>
                    </view>
                </view>
            </view>
        </view>

        <view class="padding"></view>

        <view>
            <radio-group @change="modelChange">
                <label class="uni-list-cell uni-list-cell-pd" v-for="(item, index) in items" :key="item.value">
                    <view>
                        <radio :value="item.value" :checked="index === playModel" />
                    </view>
                    <view>{{ item.name }}</view>
                </label>
            </radio-group>
        </view>

        <view class="flex-box">
            <view>
                <p>设置页</p>
            </view>
            <view><button @click="goBatterySetting">跳转到电量保护设置页</button></view>
            <view><button @click="goAutoStartSetting">跳转到应用自启动设置页</button></view>
            <view><button @click="openNotifySetting">跳转到通知设置页面</button></view>
            <view><button @click="checkFilePermission">检查文件读写权限</button></view>
            <view><button @click="checkNotifyEnabled">检查通知权限</button></view>

            <view>
                <p>媒体通知栏</p>
            </view>
            <view><button @click="startForeground('media')">创建媒体通知</button></view>

            <view>
                <p>自定义通知栏</p>
            </view>
            <view><button @click="startForeground('normal')">创建自定义通知</button></view>

            <view>
                <p>更新通知栏</p>
            </view>
            <view><button @click="setlastOrnext">修改按钮状态</button></view>
            <view><button @click="setTitleOrimage">更新通知内容</button></view>
            <view><button @click="setOptions">统一更新通知内容</button></view>
            <view><button @click="setplayicon">修改播放状态</button></view>
            <view><button @click="stopForeground">------停止通知------</button></view>

            <view>
                <p>TTS</p>
            </view>
            <view><button @click="init">初始化</button></view>
            <view><button @click="getEngines">获取设备已安装的引擎列表</button></view>
            <view><button @click="getDefaultEngine">获取当前设备默认引擎</button></view>
            <view><button @click="setEngine">设置引擎</button></view>
            <view><button @click="speak">实时模式播放</button></view>
            <view><button @click="stop">停止播放</button></view>
            <view><button @click="saveAudioFile">生成音频文件</button></view>
            <view><button @click="destorySpeaker">销毁</button></view>
            <view><button @click="openSetting">打开TTS引擎设置页</button></view>
            <view>
                <p>tts音频</p>
            </view>
            <view><button @click="playerSpeak">音频模式-生成文件</button></view>
            <view><button @click="playerPlay">音频模式-播放</button></view>
            <view><button @click="playerPause">音频模式-暂停</button></view>
            <view><button @click="playerResume">音频模式-继续</button></view>
            <view><button @click="playerStop">音频模式-停止播放</button></view>
            <view>
                <p>工具</p>
            </view>
            <view><button @click="getFolderSize">递归获取文件夹大小</button></view>
            <view><button @click="getCurrentFolderSize">获取文件夹大小</button></view>
            <view><button @click="deleteFolderFile">删除指定目录下的文件及文件夹</button></view>
            <view><button @click="deleteFile">删除指定目录下的文件</button></view>
        </view>
    </view>
</template>

<script>
    const TTSSpeaker = uni.requireNativePlugin('Karma617-SuperTTSSpeaker');
    const speakListener = weex.requireModule('globalEvent');
    export default {
        data() {
            return {
                engineList: [],
                array: ['请选择引擎'],
                index: 0,
                words: 'TTS(Text To Speech,文本转语音)是语音合成应用的一种,它将储存于电脑中的文件,如帮助文件或者网页,转换成自然语音输出。',
                speed: 2,
                pitch: 1,
                playModel: 1,
                items: [{
                        value: 0,
                        name: '舍弃模式'
                    },
                    {
                        value: 1,
                        name: '追加模式'
                    }
                ],
                tips: '',
                engine: '',
                isPlay: true,
                notifyType: 'normal',
            };
        },
        onReady() {
            let _this = this;
            _this.init();
            // TTS实时模式监听播放状态
            speakListener.addEventListener('speakListener', function(e) {
                // {"data":{"taskid":"666234324563543","code":1,"msg":"播放开始"},"code":0,"msg":"实时播放任务监听"}
                //  data.code 1 播放开始 2 播放结束 -1 播放失败
                console.log(e);

                if (e.data.code == 2) {
                    TTSSpeaker.speak(this.words, this.playModel + 1);
                }
            });

            // 文字转音频播放监听播放状态
            speakListener.addEventListener('mediaListener', function(e) {
                // {"data":{"status":1,"data":{"position":97,"progress":6792},"msg":"正在播放"},"code":0,"msg":"音频模式播放任务监听"}
                //  data.status 1 正在播放 2 播放结束 -1 播放失败;data.data.position 播放进度百分比 data.data.progress 播放进度
                console.log(e);
            });

            // 耳机
            speakListener.addEventListener('headsetListener', function(e) {
                // {"data":{"code":0,"msg":"有线耳机已拔出"},"code":0,"msg":"实时播放任务监听"}
                // {"data":{"code":11,"msg":"蓝牙耳机已连接"},"code":1,"msg":"耳机状态监听"}
                // e.code 0 耳机已拔出或断开 1 耳机已连接
                console.log(e);
            });

            // 通话状态
            speakListener.addEventListener('phoneCallListener', function(e) {
                // {"data":{"code":0,"msg":"通话结束或未通话"},"code":0,"msg":"通话状态监听"}
                // {"data":{"code":1,"msg":"来电响铃"},"code":1,"msg":"通话状态监听"}
                // {"data":{"code":2,"msg":"接听电话或拨出电话"},"code":1,"msg":"通话状态监听"}
                // e.code 0 通话结束或未通话 1 来电响铃 2 正在接听电话或拨出电话
                console.log(e);
            });

            // 日夜切换
            speakListener.addEventListener('uimodeListener', function(e) {
                uni.showToast({
                    title: e.code,
                    icon: 'none'
                });
            });
        },
        onUnload() {
            // 记得注销通话状态监听事件
            TTSSpeaker.distoryTelePhoneListener();
        },
        methods: {
            openSetting() {
                TTSSpeaker.openSetting();
            },
            checkNotifyEnabled() {
                TTSSpeaker.checkNotifyEnabled();
            },
            checkFilePermission() {
                TTSSpeaker.checkFilePermission();
            },
            setEngine() {
                if (this.engine) {
                    TTSSpeaker.setEngine(this.engine);
                }
            },
            startForeground(type) {
                this.notifyType = type;
                TTSSpeaker.startForeground({
                        notifyType: type || 'normal',
                        title: '银河创新成长混合',
                        subTitle: '诺安小弟',
                        image: 'https://img01-xusong.91q.com/8F11E8B2-14CF-4A23-B4A7-7E45FEDE2791.jpg',
                        keepAlive: 60
                    },
                    data => {
                        console.log(data);
                        uni.showToast({
                            title: data.type,
                            icon: 'none'
                        });
                        switch (data.type) {
                            case 'play':
                                TTSSpeaker.speak(this.words, this.playModel + 1);
                                this.setplayicon();
                                break;
                            case 'pause':
                                TTSSpeaker.stop();
                                this.setplayicon();
                                break
                        }
                    }
                );
            },
            stopForeground() {
                TTSSpeaker.stopForeground();
            },
            setlastOrnext() {
                TTSSpeaker.setlastOrnext({
                    last: false,
                    next: true
                });
            },
            setOptions() {
                TTSSpeaker.setOptions({
                    title: '在Android通知中,小图标(',
                    subTitle: '在如果你想要修改',
                    image: 'https://img01-xusong.91q.com/8F11E8B2-14CF-4A23-B4A7-7E45FEDE2791.jpg',
                    last: true,
                    next: false,
                    isPlay: false
                });
            },
            setTitleOrimage() {
                TTSSpeaker.setTitleOrimage({
                    title: '混合银河创新成长混合银河创新成长',
                    subTitle: '诺安小弟混合银河创新成长混合银河创新成长混合银河创新成长',
                    image: 'https://img01-xusong.91q.com/3F92300D-11A6-4575-8509-7CABAE420464.jpg'
                });
            },
            setplayicon() {
                TTSSpeaker.setplayicon(this.isPlay);
                this.isPlay = !this.isPlay;
            },
            goBatterySetting() {
                TTSSpeaker.goBatterySetting();
            },
            goAutoStartSetting() {
                TTSSpeaker.goAutoStartSetting();
            },
            bindPickerChange(e) {
                this.index = e.detail.value;
                this.engine = this.engineList[this.index - 1].package_name;
                console.log(this.engine);
                if (this.engine) {
                    TTSSpeaker.setEngine(this.engine);
                }
                // this.destorySpeaker();
                // let _this = this;
                // setTimeout(v => {
                //     _this.init(_this.engine);
                // }, 500);
            },
            init(engine) {
                let _this = this;
                _this.array = ['请选择引擎'];
                TTSSpeaker.init(
                    function(result) {
                        let obj = JSON.parse(result.data);
                        // 返回设置的语速和音调
                        _this.pitch = obj.voice_pitch;
                        _this.speed = obj.voice_speed;
                        // 返回当前已安装的引擎列表
                        _this.engineList = JSON.parse(obj.engines);
                        _this.engineList.forEach(v => {
                            _this.array.push(v.app_name);
                        });
                    }, {
                        engine: engine || ''
                    }
                );
            },
            openNotifySetting() {
                TTSSpeaker.openNotifySetting();
            },
            modelChange: function(evt) {
                for (let i = 0; i < this.items.length; i++) {
                    if (this.items[i].value === evt.detail.value) {
                        this.playModel = i;
                        break;
                    }
                }
            },
            speak() {
                // 对应参数: 待播放文本,播放模式(1 丢弃之前的播报任务,立即播报本次内容 2 播放完之前的语音任务后才播报本次内容),任务id(用来获取播放状态)
                TTSSpeaker.speak(this.words, this.playModel + 1);
                this.startForeground(this.notifyType);

            },
            setVoiceSpeed(e) {
                TTSSpeaker.setVoiceSpeed(e.detail.value, function(result) {
                    uni.showToast({
                        title: JSON.stringify(result),
                        icon: 'none'
                    });
                });
            },
            setVoicePicth(e) {
                TTSSpeaker.setVoicePicth(e.detail.value, function(result) {
                    uni.showToast({
                        title: JSON.stringify(result),
                        icon: 'none'
                    });
                });
            },
            stop() {
                TTSSpeaker.stop();
                this.stopForeground();
            },
            destorySpeaker() {
                TTSSpeaker.destorySpeaker();
            },
            getDefaultEngine() {
                TTSSpeaker.getDefaultEngine(v => {
                    uni.showToast({
                        title: JSON.stringify(v),
                        icon: 'none'
                    });
                });
            },
            getEngines() {
                // 该方法必须在init初始化之后才能调用。1.1.4版本以后,初始化成功后将一并返回tts引擎列表
                this.array = ['请选择引擎'];
                TTSSpeaker.getEngines(res => {
                    this.engineList = res.data;
                    res.forEach(v => {
                        this.array.push(v.app_name);
                    });
                    uni.showToast({
                        title: JSON.stringify(v),
                        icon: 'none'
                    });
                });
            },
            saveAudioFile() {
                // 文字过长时,请加延时,测试8000字,需延时最少2500毫秒。
                // 建议将文本分段后再进行合成保存
                TTSSpeaker.saveAudioFile({
                        words: this.words,
                        save_path: '' // 音频文件保存路径,可选,默认保存路径为本应用的cache目录下,例:/xxx/xxx/xxx/audio.wav。
                    },
                    function(result) {
                        // 返回文件目录信息
                        uni.showToast({
                            title: JSON.stringify(result),
                            icon: 'none'
                        });
                    }
                );
            },
            playerSpeak() {
                let _this = this;
                // words待播放文本 , savePath音频文件保存路径,可选,默认保存路径为本应用的cache目录下,例:/xxx/xxx/xxx/audio.wav。
                TTSSpeaker.playerSpeak(_this.words, '', res => {
                    console.log(res);
                    // {"data":"/storage/emulated/0/Android/data/com.qdapi.ttspeaker/cache/voices/a44fb3b2bffdb007de81935476457587.wav","code":0,"msg":"保存成功"}
                    _this.savePath = res.data;
                });
            },
            playerPlay() {
                TTSSpeaker.playerPlay(this.savePath);
            },
            playerStop() {
                TTSSpeaker.playerStop();
            },
            playerResume() {
                TTSSpeaker.playerResume();
            },
            playerPause() {
                TTSSpeaker.playerPause();
            },
            getFolderSize() {
                TTSSpeaker.getFolderSize('', res => {
                    // {"data":"217.38KB","code":0,"msg":"获取成功"}
                    console.log(res);
                });
            },
            getCurrentFolderSize() {
                TTSSpeaker.getCurrentFolderSize('', res => {
                    // {"data":"217.38KB","code":0,"msg":"获取成功"}
                    console.log(res);
                });
            },
            deleteFolderFile() {
                TTSSpeaker.deleteFolderFile('', false, res => {
                    // {"data":"","code":0,"msg":"删除成功"}
                    console.log(res);
                });
            },
            deleteFile() {
                TTSSpeaker.deleteFile('', res => {
                    // {"data":"","code":0,"msg":"删除成功"}
                    console.log(res);
                });
            }
        }
    };
</script>
<style lang="less">
    .padding {
        padding: 20px;
    }

    .flex-box {
        display: flex;
        flex-direction: column;
        flex-wrap: wrap;

        >view {
            text-align: center;
            display: flex;
            flex-direction: row;
            justify-content: center;

            >p {
                font-size: 26px;
                font-weight: bold;
            }

            >button {
                flex: 1;
            }
        }

    }
</style>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

"android.permission.READ_EXTERNAL_STORAGE":这个权限允许应用程序从你的设备的外部存储(例如 SD 卡)中读取数据。 "android.permission.WRITE_EXTERNAL_STORAGE":这个权限允许应用程序写入到你的设备的外部存储中。 "android.permission.MODIFY_AUDIO_SETTINGS":此权限允许应用程序更改你的设备的音频设置。 "android.permission.READ_PHONE_STATE":这项权限允许应用程序访问当前电话的状态,例如有无正在进行的通话。 "android.permission.BLUETOOTH":这个权限允许应用程序连接到配对的蓝牙设备。 "android.permission.BLUETOOTH_ADMIN":这个权限允许应用程序发现和配对蓝牙设备,以及更改蓝牙设置。 "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS":这个权限允许应用请求忽略电池优化设置。 "android.permission.FOREGROUND_SERVICE":继 Android 9.0(API 级别 28)之后,需要此权限才能使应用启动前台服务。 "android.permission.RECEIVE_BOOT_COMPLETED":这个权限允许应用程序在系统完成启动(即开机)后接收一个广播。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问