更新记录

1.4.0(2023-05-24)

本次主要更新: 1.andorid 增加 完全自定义拨号来电界面,来电秀

1.3.0(2023-05-17)

本次主要更新: 1.新增设置为默认电话应用 2.增加完全关闭app,也可以接听和挂断电话 3.增加相关监听

1.2.0(2023-05-11)

本次主要更新: 1.iOS增加 注销监听 方法

查看更多

平台兼容性

Android Android CPU类型 iOS
适用版本区间:6.0 - 12.0 armeabi-v7a:支持,arm64-v8a:支持,x86:支持 适用版本区间:11 - 16

原生插件通用使用流程:

  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原生插件配置”->”云端插件“列表中删除该插件重新选择


KJ-CallV2

电话状态监听、接听电话、挂断电话、回调手机号码、默认电话拨号应用、来去电黑白名单、支持不设置默认应用实现接听和挂断、完全关闭app也可以接听挂断电话(ios、android)

注意

1.ios版本:只有 电话状态监听 和 注销监听

2.andorid版本:不保证所有手机都有效,请试用合适再购买

3.如果设置为 默认电话应用,也可以实现完全关闭app,也可以接听和挂断电话

使用

<template>
    <view class="content" style="margin-top: 100px;">
        <button type="primary" @click="CallState">监听电话状态(双端)</button>
        <view class="json">{{json}}</view>
        <button type="primary" @click="unregisterReceiver">注销监听电话状态(双端)</button>

        <button type="primary" @click="CallState_Andoird">监听电话状态(andorid)</button>
        <view class="json">{{json_andorid}}</view>
        <button type="primary" @click="unregisterReceiver_Andoird">注销监听电话状态(andorid)</button>

        <button type="primary" @click="ringingCall">接听电话(andorid8.0以上不需要设置默认电话应用)</button>
        <button type="primary" @click="endCall">挂断电话(andorid9.0以上不需要设置默认电话应用)</button>

        <button type="primary" @click="isDefaultCall">判断本app是不是默认电话应用(andorid)</button>
        <button type="primary" @click="setDefaultCall">设置默认电话应用,完全关闭app也可以接听挂断(andorid)</button>
        <button type="primary" @click="setInCallServiceCallBack">监听电话状态2(andorid)</button>
        <view class="json">{{json2}}</view>
        <button type="primary" @click="cancelInCallServiceCallBack">取消监听电话状态2(andorid)</button>
        <button type="primary" @click="ringingCallV2">接听电话(设置为默认电话应用才有效)</button>
        <button type="primary" @click="endCallV2">挂断电话(设置为默认电话应用才有效)</button>
        <button type="primary" @click="getInCallInfo">获取当前电话通信信息</button>
        <view class="json">{{inCallInfo}}</view>
        <button type="primary" @click="isSystemAlertWindowPermission">是否有“显示在其他应用的上层”权限</button>
        <button type="primary" @click="requestSystemAlertWindowPermission">跳转“显示在其他应用的上层”权限设置页面</button>
        <button type="primary" @click="saveCallUICacheData">保存自定义拨号界面的缓存数据,向网页传值</button>
        <button type="primary" @click="saveCallUICacheData2">清除自定义拨号界面的缓存数据</button>
    </view>
</template>

<script>
    var KJCallV2 = uni.requireNativePlugin("KJ-CallV2");
    export default {
        data() {
            return {
                json: null,
                json_andorid: null,
                json2: null,
                inCallInfo: null,
                isOpenApp: false
            }
        },
        onLoad() {
            console.log(plus.io.convertLocalFileSystemURL("hybrid/html/index.html"));
            if (plus.os.name == 'Android') {
                plus.android.requestPermissions(
                    ['android.permission.ANSWER_PHONE_CALLS', //手动 挂断和接听 需要这个权限
                        "android.permission.MODIFY_AUDIO_SETTINGS", //手动 挂断和接听 需要这个权限
                        "android.permission.CALL_PHONE", //手动 挂断和接听 需要这个权限
                        "android.permission.READ_PHONE_STATE", //>监听电话状态 需要这个权限
                        "android.permission.READ_CALL_LOG", //获取号码需要这个权限
                        "android.permission.PROCESS_OUTGOING_CALLS"
                    ],
                    function(resultObj) {
                        var result = 0;
                        for (var i = 0; i < resultObj.granted.length; i++) {
                            var grantedPermission = resultObj.granted[i];
                            console.log('已获取的权限:' + grantedPermission);
                            result = 1
                        }
                        for (var i = 0; i < resultObj.deniedPresent.length; i++) {
                            var deniedPresentPermission = resultObj.deniedPresent[i];
                            console.log('拒绝本次申请的权限:' + deniedPresentPermission);
                            result = 0
                        }
                        for (var i = 0; i < resultObj.deniedAlways.length; i++) {
                            var deniedAlwaysPermission = resultObj.deniedAlways[i];
                            console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
                            result = -1
                        }
                    },
                    function(error) {
                        console.log('申请权限错误:' + error.code + " = " + error.message);
                    }
                );
            }
            //this.getInCallInfo();
            this.setInCallServiceCallBack();
        },
        methods: {
            CallState() {
                //电话状态监听
                KJCallV2.CallState((res) => {
                    this.json = JSON.stringify(res);
                    console.log("CallState: " + JSON.stringify(res));
                    if (plus.os.name == 'Android') {
                        console.log("电话号码:" + res.incomingNumber); //号码不一定能获取到
                        if (res.callState == "ringing") {
                            console.log("来电");
                            //this.endCall(); //来电自动挂断
                            //this.ringingCall(); //来电自动接听
                        } else if (res.callState == "offhook") { //拨打 和 接听都会回调这个
                            console.log("待机");
                        } else if (res.callState == "idle") { //挂断 和 没有任何操作 都会回调这个
                            console.log("没有状态");
                        }
                    } else {
                        console.log("电话唯一ID:" + res.callID);
                        if (res.callState == "Dialing") {
                            console.log("拨打");
                        } else if (res.callState == "Connected") {
                            console.log("电话接通");
                        } else if (res.callState == "Disconnected") {
                            console.log("电话挂断");
                        } else if (res.callState == "Incoming") {
                            console.log("来电");
                        } else if (res.callState == "Other") {
                            console.log("电话其他状态");
                        }
                    }
                })
            },
            unregisterReceiver() {
                KJCallV2.unregisterReceiver((res) => {
                    console.log("unregisterReceiver: " + JSON.stringify(res));
                });
            },
            CallState_Andoird() {
                //电话状态监听
                KJCallV2.CallState_Andoird((res) => {
                    this.json_andorid = JSON.stringify(res);
                    console.log("CallState_Andoird: " + JSON.stringify(res));
                    if (plus.os.name == 'Android') {
                        console.log("手机号码:" + res.phoneNumber); //号码不一定能获取到
                        console.log("来电号码:" + res.incomingNumber); //号码不一定能获取到
                        console.log("去电号码:" + res.outNumber); //号码不一定能获取到
                        if (res.callState == "ringing") {
                            console.log("来电");
                            //this.endCall(); //来电自动挂断
                            //this.ringingCall(); //来电自动接听
                        } else if (res.callState == "offhook") { //拨打 和 接听都会回调这个
                            console.log("待机");
                        } else if (res.callState == "idle") { //挂断 和 没有任何操作 都会回调这个
                            console.log("没有状态");
                        }
                    }
                })
            },
            unregisterReceiver_Andoird() {
                KJCallV2.unregisterReceiver_Andoird((res) => {
                    console.log("unregisterReceiver_Andoird: " + JSON.stringify(res));
                });
            },
            ringingCall() {
                //注意事项:andorid 8.0以上 不需要设置为默认电话应用,也可以接听
                KJCallV2.ringingCall((res) => {
                    console.log("ringingCall: " + JSON.stringify(res));
                });
            },
            endCall() {
                //注意事项:andorid 9.0以上 不需要设置为默认电话应用,也可以挂断
                KJCallV2.endCall((res) => {
                    console.log("endCall: " + JSON.stringify(res));
                });
            },
            isDefaultCall() {
                KJCallV2.isDefaultCall((res) => {
                    console.log("isDefaultCall: " + JSON.stringify(res));
                });
            },
            setDefaultCall() {
                /**
                 * 自动接听和挂断是同步执行
                 * 来电,如果想先接后挂, ringing->ringingCall->delay设置为0  ringing->endCall->delay设置为2
                 * 如果设置为 默认电话应用,也可以实现完全关闭app,也可以接听和挂断电话
                 * 黑白名单执行顺序,先执行whiteList,再执行blackList
                 * 
                 * 
                 * 自定义拨号和来电界面有三种方式:
                 * 1.设置isOpenApp为true,然后在 App.vue里onLaunch 和 setInCallServiceCallBack回调 写相关代码,具体看示例
                 * 2.callUI->isUserFloatWindow为true,配置url参数, 提供saveCallUICacheData方法向网页传值,需要“显示在其他应用的上层”权限
                 * 3.callUI->isUserActivity为true,配置url参数, 提供saveCallUICacheData方法向网页传值
                 * */
                var dic = {
                    "isOpenApp": this.isOpenApp, //来电或去电,是否打开app,可用以自定义拨号界面
                    "callUI": {
                        "isUserFloatWindow": true, //来电和拨号是否使用悬浮窗
                        //"isUserActivity": true, //来电和拨号是否使用跳转页面
                        "url": plus.io.convertLocalFileSystemURL("hybrid/html/index.html"),
                    },
                    "ringing": { //来电
                        "ringingCall": { //接听
                            "isAuto": true, //是否自动接听电话
                            "delay": 0, //延迟执行时间,单位秒
                            /**whiteList和blackList都设置为null,所有号码都执行**/
                            "whiteList": ["xxx"], //接听白名单,list里的号码,自动接听,反之不接听
                            //"blackList": ["xxx"], //接听黑名单,list里的号码,不接听,反之自动接听
                        },
                        "endCall": { //挂断
                            "isAuto": false, //是否自动挂断电话
                            "delay": 0, //延迟执行时间,单位秒
                            /**whiteList和blackList都设置为null,所有号码都执行**/
                            //"whiteList": ["xxx"], //挂断白名单,list里的号码,自动挂断,反之不挂断
                            "blackList": ["xxx"], //挂断黑名单,list里的号码,不挂断,反之自动挂断
                        }
                    },
                    "connecting": { //去电
                        "endCall": { //挂断
                            "isAuto": false, //是否自动挂断电话
                            "delay": 0, //延迟执行时间,单位秒
                            /**whiteList和blackList都设置为null,所有号码都执行**/
                            //"whiteList": ["xxx"], //挂断白名单,list里的号码,自动挂断,反之不挂断
                            "blackList": ["xxx"], //挂断黑名单,list里的号码,不挂断,反之自动挂断
                        }
                    }
                }
                KJCallV2.setDefaultCall(dic, (res) => {
                    console.log("setDefaultCall: " + JSON.stringify(res));
                    var code = res.code;
                    if (code == 0) {
                        var resultCode = res.resultCode;
                        if (resultCode == -1) {
                            console.log("已设为默认电话应用");
                        } else {
                            console.log("设为默认电话应用失败");
                        }
                    } else if (code == 1) {
                        console.log("跳到电话设置界面去设置");
                    } else if (code == 2) {
                        console.log("Android 6.0以上才支持修改默认电话应用!");
                    }
                });
            },
            setInCallServiceCallBack() {
                KJCallV2.setInCallServiceCallBack((res) => {
                    console.log("setInCallServiceCallBack: " + JSON.stringify(res));
                    /**
                     * 返回json字段说明:{"method":"onCallAdded","call":{"state":2,"details":{"phoneNumber":"xxx"}}}
                     * state - 状态  0(是一个新的连接,但是还没连接上) 1(一个处于外拨的连接,此时对方还没有应答,可以听到嘟嘟的声音) 2(来电) 
                     * 3(一个连接存于hold状态) 4(一个连接处于活动状态,双方可以正常主动通信) 7(当前的call释放了所有资源处于断开连接状态)
                     * 9(外拨的初始状态) 10(正处于断开连接状态) 11(表示一个连接正处于从远端连接拉到本地连接的一个状态(比如有两个设备但是共用一个号码))
                     * */
                    this.json2 = JSON.stringify(res)
                    var method = res.method;
                    var state = res.call.state;
                    var phoneNumber = res.call.details.phoneNumber; //号码不一定能获取到
                    if (method == "onCallAdded") {
                        if (state == 2) {
                            console.log("来电:" + phoneNumber);
                        } else if (state == 9) {
                            console.log("去电:" + phoneNumber);
                        }
                        if (this.isOpenApp == true) {
                            uni.reLaunch({
                                url: "/pages/index/callUI"
                            })
                        }
                    } else if (method == "onStateChanged") {
                        if (state == 4) {
                            console.log("通话中:" + phoneNumber);
                        } else if (state == 7) {
                            console.log("通话结束:" + phoneNumber);
                        }
                    }
                });
            },
            cancelInCallServiceCallBack() {
                KJCallV2.cancelInCallServiceCallBack();
            },
            ringingCallV2() {
                //注意事项:需要设置为默认电话应用
                KJCallV2.ringingCallV2();
            },
            endCallV2() {
                //注意事项:需要设置为默认电话应用
                KJCallV2.endCallV2();
            },
            getInCallInfo() {
                KJCallV2.getInCallInfo((res) => {
                    this.inCallInfo = JSON.stringify(res);
                    if (res.result.state == 1 || res.result.state == 2) {
                        console.log("getInCallInfo:" + JSON.stringify(res));
                        uni.reLaunch({
                            url: "/pages/index/callUI"
                        })
                    }
                });
            },
            isSystemAlertWindowPermission() {
                KJCallV2.isSystemAlertWindowPermission((res) => {
                    console.log("isSystemAlertWindowPermission:" + JSON.stringify(res));
                });
            },
            requestSystemAlertWindowPermission() {
                //注意:需要在manifest.json配置android.permission.SYSTEM_ALERT_WINDOW权限
                KJCallV2.requestSystemAlertWindowPermission((res) => {
                    console.log("requestSystemAlertWindowPermission:" + JSON.stringify(res));
                });
            },
            saveCallUICacheData() {
                //例如:实现更换壁纸的功能
                var json = {
                    "wallpaperUrl": plus.io.convertLocalFileSystemURL("static/wallpaper2.jpeg")
                }
                var jsonStr = JSON.stringify(json);
                KJCallV2.saveCallUICacheData(jsonStr);
            },
            saveCallUICacheData2() {
                KJCallV2.saveCallUICacheData("");
            }
        }
    }
</script>
<style>
    .json {
        word-wrap: break-word;
    }

    button {
        font-size: 15px;
    }
</style>

自定义拨号来电vue页面

<template>
    <view class="content">
        <view class="top">
            <view class="phoneNumber">{{phoneNumber}}</view>
            <view class="time">{{time}}</view>
        </view>
        <view class="bottom">
            <view class="call-btn" @click="endCallV2" v-if="state == 1 || state == 2 || state == 9 || state == 4">
                <image src="../../static/endCall.png" />
                </image>
                <view>挂断</view>
            </view>
            <view class="call-btn" @click="ringingCallV2" v-if="state == 2">
                <image src="../../static/ringingCall.png" />
                </image>
                <view>接听</view>
            </view>
        </view>
    </view>
</template>

<script>
    var KJCallV2 = uni.requireNativePlugin("KJ-CallV2");
    export default {
        data() {
            return {
                state: 1,
                phoneNumber: "xxx",
                time: "正在呼叫中...",
                callingTime: 0
            }
        },
        onLoad() {
            this.getInCallInfo();
            this.setInCallServiceCallBack();

            KJCallV2.openSpeaker();
        },
        methods: {
            setInCallServiceCallBack() {
                KJCallV2.setInCallServiceCallBack((res) => {
                    console.log("setInCallServiceCallBack: " + JSON.stringify(res));
                    /**
                     * 返回json字段说明:{"method":"onCallAdded","call":{"state":2,"details":{"phoneNumber":"xxx"}}}
                     * state - 状态  0(是一个新的连接,但是还没连接上) 1(一个处于外拨的连接,此时对方还没有应答,可以听到嘟嘟的声音) 2(来电) 
                     * 3(一个连接存于hold状态) 4(一个连接处于活动状态,双方可以正常主动通信) 7(当前的call释放了所有资源处于断开连接状态)
                     * 9(外拨的初始状态) 10(正处于断开连接状态) 11(表示一个连接正处于从远端连接拉到本地连接的一个状态(比如有两个设备但是共用一个号码))
                     * */
                    this.json2 = JSON.stringify(res)
                    var method = res.method;
                    var state = res.call.state;
                    var phoneNumber = res.call.details.phoneNumber; //号码不一定能获取到
                    if (method == "onCallAdded") {
                        this.callingTime = 0;
                        if (state == 2) {
                            console.log("来电:" + phoneNumber);
                        } else if (state == 9) {
                            console.log("去电:" + phoneNumber);
                        }
                    } else if (method == "onStateChanged") {
                        if (state == 4) {
                            console.log("通话中:" + phoneNumber);
                            setInterval((res) => {
                                this.callingTime++;
                                this.time = this.getTime(this.callingTime);
                            }, 1000)
                        } else if (state == 7) {
                            console.log("通话结束:" + phoneNumber);
                            this.callingTime = 0;
                            uni.reLaunch({
                                url: "/pages/index/index"
                            })
                        }
                    }
                });
            },
            cancelInCallServiceCallBack() {
                KJCallV2.cancelInCallServiceCallBack();
            },
            ringingCallV2() {
                //注意事项:需要设置为默认电话应用
                KJCallV2.ringingCallV2();
            },
            endCallV2() {
                //注意事项:需要设置为默认电话应用
                KJCallV2.endCallV2();
            },
            getInCallInfo() {
                KJCallV2.getInCallInfo((res) => {
                    console.log("getInCallInfo:" + JSON.stringify(res));
                    this.state = res.result.state;
                    this.inCallInfo = JSON.stringify(res);
                    this.phoneNumber = res.result.phoneNumber
                    if (this.state == 2) {
                        this.time = "来电";
                    } else {
                        this.time = "正在呼叫中...";
                    }
                });
            },
            getTime(time) {
                let h = parseInt(time / 60 / 60 % 24)
                h = h < 10 ? '0' + h : h
                let m = parseInt(time / 60 % 60)
                m = m < 10 ? '0' + m : m
                let s = parseInt(time % 60)
                s = s < 10 ? '0' + s : s
                return h + ":" + m + ":" + s
            }
        }
    }
</script>
<style>
    .content {
        text-align: center;
    }

    .top {
        font-size: 40px;
        height: 40vh;
        background-color: #118801;
        color: white;
        display: flex;
        flex-wrap: wrap;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .phoneNumber {
        margin-top: 16px;
    }

    .time {
        font-size: 18px;
    }

    .bottom {
        height: 60vh;
        display: flex;
        flex-wrap: wrap;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }

    .call-btn {
        width: 50%;
        display: flex;
        flex-wrap: wrap;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        font-size: 18px;
    }

    .call-btn image {
        width: 80px;
        height: 80px;
    }
</style>

自定义拨号来电 本地html页面

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <meta name="viewport"
            content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <title></title>
        <script src="js/mui.min.js"></script>
        <link href="css/mui.min.css" rel="stylesheet" />
        <script>
            mui.init();
        </script>
        <style type="text/css">
            html,
            body {
                width: 100%;
                height: 100%;
            }

            .content {
                width: 100%;
                height: 100%;
                text-align: center;
                z-index: 999;
                background-image: url("img/wallpaper.jpeg");
                background-repeat: no-repeat;
                background-size: 100% 100%;
            }

            .top {
                font-size: 40px;
                height: 40%;
                /* background-color: #118801; */
                color: white;
                display: flex;
                flex-wrap: wrap;
                flex-direction: column;
                align-items: center;
                justify-content: center;
            }

            .phoneNumber {
                margin-top: 16px;
            }

            .time {
                margin-top: 16px;
                font-size: 18px;
            }

            .bottom {
                height: 60%;
                color: black;
                display: flex;
                flex-wrap: wrap;
                flex-direction: row;
                align-items: center;
                justify-content: center;
            }

            .call-btn {
                width: 50%;
                display: flex;
                flex-wrap: wrap;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                color: white;
                font-size: 18px;
            }

            .call-btn img {
                width: 80px;
            }
        </style>
    </head>

    <body>
        <div class="content" id="content">
            <div class="top">
                <div class="phoneNumber" id="phoneNumber"></div>
                <div class="time" id="time">正在呼叫中...</div>
            </div>
            <div class="bottom">
                <div class="call-btn" id="endCall">
                    <img src="img/endCall.png" />
                    <div>挂断</div>
                </div>
                <div class="call-btn" id="ringingCall">
                    <img src="img/ringingCall.png" />
                    <div>接听</div>
                </div>
            </div>
        </div>
        <script>
            var callingTime = 0;

            function getTime(time) {
                let h = parseInt(time / 60 / 60 % 24)
                h = h < 10 ? '0' + h : h
                let m = parseInt(time / 60 % 60)
                m = m < 10 ? '0' + m : m
                let s = parseInt(time % 60)
                s = s < 10 ? '0' + s : s
                return h + ":" + m + ":" + s
            }
            var content = document.getElementById("content");
            var phoneNumber = document.getElementById("phoneNumber");
            var time = document.getElementById("time");
            var json = document.getElementById("json");

            var endCallBtn = document.getElementById("endCall");
            var ringingCallBtn = document.getElementById("ringingCall");

            //页面加载完成和通信状态变化都会回调
            function getInCallInfo(jsonStr) {
                var dic = JSON.parse(jsonStr);
                phoneNumber = dic.phoneNumber;
                var state = dic.state;
                if (state == 2) {
                    time = "来电";
                }
                if (state == 4) {
                    setInterval((res) => {
                        callingTime++;
                        time = getTime(callingTime);
                    }, 1000)
                }
                if (state == 1 || state == 2 || state == 9 || state == 4) {
                    endCallBtn.style.display = "block";
                } else {
                    endCallBtn.style.display = "none";
                }
                if (state == 2) {
                    ringingCallBtn.style.display = "block";
                } else {
                    ringingCallBtn.style.display = "none";
                }
            }

            //页面加载完成会回调一次,回调KJCallV2.saveCallUICacheData保存的数据
            function getCallUICacheData(jsonStr) {
                try {
                    var dic = JSON.parse(jsonStr);
                    var wallpaperUrl = dic.wallpaperUrl;
                    content.style.backgroundImage = "url('" +
                        wallpaperUrl + "')"
                } catch (e) {}
            }

            endCallBtn.addEventListener("click", function(res) {
                var dic = {
                    "type": "endCall"
                }
                var jsonStr = JSON.stringify(dic)
                try {
                    window.Android.sendData(jsonStr);
                } catch (e) {}
            })
            ringingCallBtn.addEventListener("click", function(res) {
                var dic = {
                    "type": "ringingCall"
                }
                var jsonStr = JSON.stringify(dic)
                try {
                    window.Android.sendData(jsonStr);
                } catch (e) {}
            })
        </script>
    </body>
</html>

隐私、权限声明

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

andorid: android.permission.ANSWER_PHONE_CALLS、android.permission.MODIFY_AUDIO_SETTINGS、android.permission.CALL_PHONE、android.permission.READ_PHONE_STATE、android.permission.READ_CALL_LOG、android.permission.SYSTEM_ALERT_WINDOW

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

插件不采集任何数据

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

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