HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

关于DCloud周日晚切换服务器引发问题的公告和总结

公告

故障描述

DCloud服务器在做跨云切换,这是DCloud第一次做这类事情,经验不足,轻视了风险,以为可以无缝切换,所以未提前发公告。

但从12月17日周日晚10点半起,还是造成了部分业务中断或缓慢,尤其是登陆鉴权服务的中断,给当时仍在使用的开发者带来了很大麻烦。

  • 开发者无法登陆HBuilder,鉴权失效,进而造成了无法打包等一系列故障。
  • uniCloud控制台无法登陆,无法更新云函数。

本次切换是提前在新云部署好后再切换的,但还是有2个故障点:

故障时间 故障范围 故障现象 故障原因
故障1 22点半到23点半 所有开发者 无法登陆HX和uniCloud控制台 流量较大,切换不及时
故障2 23点半到1点10分 token失效的HX开发者 点击登陆按钮没有反应 HX连接服务器的备份域名未及时切换,HX主备切换相关代码不完善,备份域名切换后需要重启HX才能恢复登陆

往上追一层的原因分析:

  • 故障1属于跨云切换经验不足。
  • 故障2暴露了相关代码不健壮,后续会升级HX和服务器交互代码来彻底解决主备切换的不完善。

再次说明:DCloud服务器故障不影响开发者的线上业务运行。
包括uniCloud虽然无法登陆管理,但云函数和数据库是在阿里云、腾讯云、支付宝小程序云上的,线上云函数连接不经过DCloud服务器,所以这块不会被影响。

后续改进

开发者肯定会追问,如何避免DCloud服务器以后再次异常导致自己的开发工作受影响?

  1. DCloud会努力保证服务器的正常,跨云切换是非常低频的事件,日常维护方面DCloud从域名到服务器均有主备策略,我们会加大对主备切换相关代码逻辑的完善。
  2. DCloud计划后续更新HX,确保DCloud服务器异常时不影响开发者打包Web和Wgt。
    HX发行时会校验开发者账户和AppId的匹配关系,这是防止黑产盗用正常用户的AppID。而AppId对应着DCloud的很多服务,付费插件、uniCloud、安全网络、加固...
    (当然仅凭这个校验无法防护所有黑产,DCloud还有其他措施配套。)
  3. DCloud一直以来都提供离线打包,App有离线打包,导出Wgt也将确保不因DCloud服务器异常而受影响。uni-app的cli也一直都可以离线发行Web和小程序。

我们无法保证DCloud的服务器一直不出问题,但我们可以保证:

  1. 相关人员吸取了教训,变得更有经验
  2. 相关代码会被仔细review,变得更健壮
  3. 相关制度会更加完善和细化,进一步降低问题出现的概率和破坏性

DCloud是一个负责任的公司,有自己的行为准则,无论您后续是否继续使用DCloud的工具和服务,无论您是否为DCloud支付费用,
这些不影响DCloud将严格要求自身,按照更高质量要求的标准提供服务。

更新:
18日上午及中午,随着开发者流量增加,一批与存储相关的业务并发性能受到影响。
该问题是因为存储文件体积较大,部分文件还未迁移到新云,老云的文件通过外网流量访问,而外网流量带宽不足导致。
随着各处的带宽配置增加,该问题已解决。
由于积压了较多打包排队请求,DCloud已经扩容了打包机,目前打包拥堵已恢复正常。

继续阅读 »

故障描述

DCloud服务器在做跨云切换,这是DCloud第一次做这类事情,经验不足,轻视了风险,以为可以无缝切换,所以未提前发公告。

但从12月17日周日晚10点半起,还是造成了部分业务中断或缓慢,尤其是登陆鉴权服务的中断,给当时仍在使用的开发者带来了很大麻烦。

  • 开发者无法登陆HBuilder,鉴权失效,进而造成了无法打包等一系列故障。
  • uniCloud控制台无法登陆,无法更新云函数。

本次切换是提前在新云部署好后再切换的,但还是有2个故障点:

故障时间 故障范围 故障现象 故障原因
故障1 22点半到23点半 所有开发者 无法登陆HX和uniCloud控制台 流量较大,切换不及时
故障2 23点半到1点10分 token失效的HX开发者 点击登陆按钮没有反应 HX连接服务器的备份域名未及时切换,HX主备切换相关代码不完善,备份域名切换后需要重启HX才能恢复登陆

往上追一层的原因分析:

  • 故障1属于跨云切换经验不足。
  • 故障2暴露了相关代码不健壮,后续会升级HX和服务器交互代码来彻底解决主备切换的不完善。

再次说明:DCloud服务器故障不影响开发者的线上业务运行。
包括uniCloud虽然无法登陆管理,但云函数和数据库是在阿里云、腾讯云、支付宝小程序云上的,线上云函数连接不经过DCloud服务器,所以这块不会被影响。

后续改进

开发者肯定会追问,如何避免DCloud服务器以后再次异常导致自己的开发工作受影响?

  1. DCloud会努力保证服务器的正常,跨云切换是非常低频的事件,日常维护方面DCloud从域名到服务器均有主备策略,我们会加大对主备切换相关代码逻辑的完善。
  2. DCloud计划后续更新HX,确保DCloud服务器异常时不影响开发者打包Web和Wgt。
    HX发行时会校验开发者账户和AppId的匹配关系,这是防止黑产盗用正常用户的AppID。而AppId对应着DCloud的很多服务,付费插件、uniCloud、安全网络、加固...
    (当然仅凭这个校验无法防护所有黑产,DCloud还有其他措施配套。)
  3. DCloud一直以来都提供离线打包,App有离线打包,导出Wgt也将确保不因DCloud服务器异常而受影响。uni-app的cli也一直都可以离线发行Web和小程序。

我们无法保证DCloud的服务器一直不出问题,但我们可以保证:

  1. 相关人员吸取了教训,变得更有经验
  2. 相关代码会被仔细review,变得更健壮
  3. 相关制度会更加完善和细化,进一步降低问题出现的概率和破坏性

DCloud是一个负责任的公司,有自己的行为准则,无论您后续是否继续使用DCloud的工具和服务,无论您是否为DCloud支付费用,
这些不影响DCloud将严格要求自身,按照更高质量要求的标准提供服务。

更新:
18日上午及中午,随着开发者流量增加,一批与存储相关的业务并发性能受到影响。
该问题是因为存储文件体积较大,部分文件还未迁移到新云,老云的文件通过外网流量访问,而外网流量带宽不足导致。
随着各处的带宽配置增加,该问题已解决。
由于积压了较多打包排队请求,DCloud已经扩容了打包机,目前打包拥堵已恢复正常。

收起阅读 »

【跳转到App Store】ios更新,跳转到app store更新

Appstore App iOS

你的AppleID:Apple Developer(发布ios app的地方)--->App信息--->综合信息里面

const url = `itms-apps://itunes.apple.com/cn/app/id${你的AppleID}?mt=8`  
plus.runtime.openURL(url);

↓↓↓ 各位大佬点点赞

继续阅读 »

你的AppleID:Apple Developer(发布ios app的地方)--->App信息--->综合信息里面

const url = `itms-apps://itunes.apple.com/cn/app/id${你的AppleID}?mt=8`  
plus.runtime.openURL(url);

↓↓↓ 各位大佬点点赞

收起阅读 »

关于华为应用市场上架,申请权限未告知目的被驳回问题的简单处理方式(修改篇)

权限

该文章是在https://ask.dcloud.net.cn/article/40875上的补充

var isIos    
// #ifdef APP-PLUS    
isIos = (plus.os.name == "iOS")    
// #endif    
var viewShow = true;  
// 判断推送权限是否开启    
function judgeIosPermissionPush() {    
    var result = false;    
    var UIApplication = plus.ios.import("UIApplication");    
    var app = UIApplication.sharedApplication();    
    var enabledTypes = 0;    
    if (app.currentUserNotificationSettings) {    
        var settings = app.currentUserNotificationSettings();    
        enabledTypes = settings.plusGetAttribute("types");    
        console.log("enabledTypes1:" + enabledTypes);    
        if (enabledTypes == 0) {    
            console.log("推送权限没有开启");    
        } else {    
            result = true;    
            console.log("已经开启推送功能!")    
        }    
        plus.ios.deleteObject(settings);    
    } else {    
        enabledTypes = app.enabledRemoteNotificationTypes();    
        if (enabledTypes == 0) {    
            console.log("推送权限没有开启!");    
        } else {    
            result = true;    
            console.log("已经开启推送功能!")    
        }    
        console.log("enabledTypes2:" + enabledTypes);    
    }    
    plus.ios.deleteObject(app);    
    plus.ios.deleteObject(UIApplication);    
    return result;    
}    

// 判断定位权限是否开启    
function judgeIosPermissionLocation() {    
    var result = false;    
    var cllocationManger = plus.ios.import("CLLocationManager");    
    var status = cllocationManger.authorizationStatus();    
    result = (status != 2)    
    console.log("定位权限开启:" + result);    
    // 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation    
    /* var enable = cllocationManger.locationServicesEnabled();    
    var status = cllocationManger.authorizationStatus();    
    console.log("enable:" + enable);    
    console.log("status:" + status);    
    if (enable && status != 2) {    
        result = true;    
        console.log("手机定位服务已开启且已授予定位权限");    
    } else {    
        console.log("手机系统的定位没有打开或未给予定位权限");    
    } */    
    plus.ios.deleteObject(cllocationManger);    
    return result;    
}    

// 判断麦克风权限是否开启    
function judgeIosPermissionRecord() {    
    var result = false;    
    var avaudiosession = plus.ios.import("AVAudioSession");    
    var avaudio = avaudiosession.sharedInstance();    
    var permissionStatus = avaudio.recordPermission();    
    console.log("permissionStatus:" + permissionStatus);    
    if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {    
        console.log("麦克风权限没有开启");    
    } else {    
        result = true;    
        console.log("麦克风权限已经开启");    
    }    
    plus.ios.deleteObject(avaudiosession);    
    return result;    
}    

// 判断相机权限是否开启    
function judgeIosPermissionCamera() {    
    var result = false;    
    var AVCaptureDevice = plus.ios.import("AVCaptureDevice");    
    var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');    
    console.log("authStatus:" + authStatus);    
    if (authStatus == 3) {    
        result = true;    
        console.log("相机权限已经开启");    
    } else {    
        console.log("相机权限没有开启");    
    }    
    plus.ios.deleteObject(AVCaptureDevice);    
    return result;    
}    

// 判断相册权限是否开启    
function judgeIosPermissionPhotoLibrary() {    
    var result = false;    
    var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");    
    var authStatus = PHPhotoLibrary.authorizationStatus();    
    console.log("authStatus:" + authStatus);    
    if (authStatus == 3) {    
        result = true;    
        console.log("相册权限已经开启");    
    } else {    
        console.log("相册权限没有开启");    
    }    
    plus.ios.deleteObject(PHPhotoLibrary);    
    return result;    
}    

// 判断通讯录权限是否开启    
function judgeIosPermissionContact() {    
    var result = false;    
    var CNContactStore = plus.ios.import("CNContactStore");    
    var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);    
    if (cnAuthStatus == 3) {    
        result = true;    
        console.log("通讯录权限已经开启");    
    } else {    
        console.log("通讯录权限没有开启");    
    }    
    plus.ios.deleteObject(CNContactStore);    
    return result;    
}    

// 判断日历权限是否开启    
function judgeIosPermissionCalendar() {    
    var result = false;    
    var EKEventStore = plus.ios.import("EKEventStore");    
    var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);    
    if (ekAuthStatus == 3) {    
        result = true;    
        console.log("日历权限已经开启");    
    } else {    
        console.log("日历权限没有开启");    
    }    
    plus.ios.deleteObject(EKEventStore);    
    return result;    
}    

// 判断备忘录权限是否开启    
function judgeIosPermissionMemo() {    
    var result = false;    
    var EKEventStore = plus.ios.import("EKEventStore");    
    var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);    
    if (ekAuthStatus == 3) {    
        result = true;    
        console.log("备忘录权限已经开启");    
    } else {    
        console.log("备忘录权限没有开启");    
    }    
    plus.ios.deleteObject(EKEventStore);    
    return result;    
}    

// Android权限查询    
function requestAndroidPermission(permissionID) {    
    return new Promise((resolve, reject) => {    
        plus.android.requestPermissions(    
            permissionID.split(","),    
            // [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装    
            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    
                }    
                resolve(result);    
                // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限    
                // if (result != 1) {    
                // gotoAppPermissionSetting()    
                // }    
            },    
            function(error) {    
                console.log('申请权限错误:' + error.code + " = " + error.message);    
                resolve({    
                    code: error.code,    
                    message: error.message    
                });    
            }    
        );    
    });    
}    

// 使用一个方法,根据参数判断权限    
function judgeIosPermission(permissionID) {    
    if (permissionID == "location") {    
        return judgeIosPermissionLocation()    
    } else if (permissionID == "camera") {    
        return judgeIosPermissionCamera()    
    } else if (permissionID == "photoLibrary") {    
        return judgeIosPermissionPhotoLibrary()    
    } else if (permissionID == "record") {    
        return judgeIosPermissionRecord()    
    } else if (permissionID == "push") {    
        return judgeIosPermissionPush()    
    } else if (permissionID == "contact") {    
        return judgeIosPermissionContact()    
    } else if (permissionID == "calendar") {    
        return judgeIosPermissionCalendar()    
    } else if (permissionID == "memo") {    
        return judgeIosPermissionMemo()    
    }    
    return false;    
}    

// 跳转到**应用**的权限页面    
function gotoAppPermissionSetting() {    
    if (isIos) {    
        var UIApplication = plus.ios.import("UIApplication");    
        var application2 = UIApplication.sharedApplication();    
        var NSURL2 = plus.ios.import("NSURL");    
        // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");         
        var setting2 = NSURL2.URLWithString("app-settings:");    
        application2.openURL(setting2);    

        plus.ios.deleteObject(setting2);    
        plus.ios.deleteObject(NSURL2);    
        plus.ios.deleteObject(application2);    
    } else {    
        // console.log(plus.device.vendor);    
        var Intent = plus.android.importClass("android.content.Intent");    
        var Settings = plus.android.importClass("android.provider.Settings");    
        var Uri = plus.android.importClass("android.net.Uri");    
        var mainActivity = plus.android.runtimeMainActivity();    
        var intent = new Intent();    
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);    
        var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);    
        intent.setData(uri);    
        mainActivity.startActivity(intent);    
    }    
}    

// 检查系统的设备服务是否开启    
// var checkSystemEnableLocation = async function () {    
function checkSystemEnableLocation() {    
    if (isIos) {    
        var result = false;    
        var cllocationManger = plus.ios.import("CLLocationManager");    
        var result = cllocationManger.locationServicesEnabled();    
        console.log("系统定位开启:" + result);    
        plus.ios.deleteObject(cllocationManger);    
        return result;    
    } else {    
        var context = plus.android.importClass("android.content.Context");    
        var locationManager = plus.android.importClass("android.location.LocationManager");    
        var main = plus.android.runtimeMainActivity();    
        var mainSvr = main.getSystemService(context.LOCATION_SERVICE);    
        var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);    
        console.log("系统定位开启:" + result);    
        return result    
    }    
}    

let permissionMap = {    
    "android": {    
        "CAMERA_EXTERNAL_STORAGE": {    
            "name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA",    
            "title": "相机/相册权限说明",    
            "content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"    
        },    
        "CAMERA": {    
            "name": "android.permission.CAMERA",    
            "title": "相机权限说明",    
            "content": "便于您使用该功能拍照更换头像、意见反馈上传图片、与客服沟通等场景中发送拍摄图片"    
        },    
        "EXTERNAL_STORAGE": {    
            "name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE",    
            "title": "相册权限说明",    
            "content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"    
        }    
    },    
    "ios": {}    
}    

let view = null;    

function showViewDesc(permission) {    
    let plat = isIos ? "ios" : "android";    
    view = new plus.nativeObj.View('per-modal', {    
        top: '0px',    
        left: '0px',    
        width: '100%',    
        backgroundColor: 'rgba(0,0,0,0.2)',    
        //opacity: '.9'       
    })    
    view.drawRect({    
        color: '#fff',    
        radius: '5px'    
    }, {    
        top: '30px',    
        left: '5%',    
        width: '90%',    
        height: "100px",    
    })    
    view.drawText(permissionMap[plat][permission]["title"], {    
        top: '40px',    
        left: "8%",    
        height: "30px"    
    }, {    
        align: "left",    
        color: "#000",    
    }, {    
        onClick: function(e) {    
            console.log(e);    
        }    
    })    
    view.drawText(permissionMap[plat][permission]["content"], {    
        top: '65px',    
        height: "60px",    
        left: "8%",    
        width: "84%"    
    }, {    
        whiteSpace: 'normal',    
        size: "14px",    
        align: "left",    
        color: "#656563"    
    })   
        setTimeout(()=>{  
            if(viewShow) view.show()  
        },200)  
}    

function premissionCheck(permission) {    
    return new Promise(async (resolve, reject) => {    
        let plat = isIos ? "ios" : "android";    
        if (isIos) { // ios    
            // const camera = permission.judgeIosPermission("camera");//判断ios是否给予摄像头权限    
            // //ios相册没权限,系统会自动弹出授权框    
            // //let photoLibrary = permission.judgeIosPermission("photoLibrary");//判断ios是否给予相册权限    
            // if(camera){    
            //     resolve();    
            // }else{    
            //     reject('需要开启相机使用权限');    
            // }    
            resolve(1)    
        } else { // android    
            let permission_arr = permissionMap[plat][permission]["name"].split(",");    
            let flag = true;    
            for(let i = 0;i<permission_arr.length;i++) {    
                let status = plus.navigator.checkPermission(permission_arr[i]);    
                if(status == "undetermined") {    
                    flag = false;    
                }    
            }    
            if (flag == false) { // 未完全授权    
                                showViewDesc(permission);  
                requestAndroidPermission(permissionMap[plat][permission]["name"]).then((res) => {    
                                        viewShow = false;  
                                        setTimeout(()=>{  
                                            viewShow = true;  
                                        },120)  
                    view.close();    
                    if (res == -1) {    
                        uni.showModal({    
                            title: '提示',    
                            content: '操作权限已被拒绝,请手动前往设置',    
                            confirmText: "立即设置",    
                            success: (res) => {    
                                if (res.confirm) {    
                                    gotoAppPermissionSetting()    
                                }    
                            }    
                        })    
                    }    
                    resolve(res)    
                })    
            } else {    
                resolve(1)    
            }    
        }    
    })    
}    

module.exports = {    
    judgeIosPermission: judgeIosPermission,    
    requestAndroidPermission: requestAndroidPermission,    
    checkSystemEnableLocation: checkSystemEnableLocation,    
    gotoAppPermissionSetting: gotoAppPermissionSetting,    
    premissionCheck: premissionCheck    
}
继续阅读 »

该文章是在https://ask.dcloud.net.cn/article/40875上的补充

var isIos    
// #ifdef APP-PLUS    
isIos = (plus.os.name == "iOS")    
// #endif    
var viewShow = true;  
// 判断推送权限是否开启    
function judgeIosPermissionPush() {    
    var result = false;    
    var UIApplication = plus.ios.import("UIApplication");    
    var app = UIApplication.sharedApplication();    
    var enabledTypes = 0;    
    if (app.currentUserNotificationSettings) {    
        var settings = app.currentUserNotificationSettings();    
        enabledTypes = settings.plusGetAttribute("types");    
        console.log("enabledTypes1:" + enabledTypes);    
        if (enabledTypes == 0) {    
            console.log("推送权限没有开启");    
        } else {    
            result = true;    
            console.log("已经开启推送功能!")    
        }    
        plus.ios.deleteObject(settings);    
    } else {    
        enabledTypes = app.enabledRemoteNotificationTypes();    
        if (enabledTypes == 0) {    
            console.log("推送权限没有开启!");    
        } else {    
            result = true;    
            console.log("已经开启推送功能!")    
        }    
        console.log("enabledTypes2:" + enabledTypes);    
    }    
    plus.ios.deleteObject(app);    
    plus.ios.deleteObject(UIApplication);    
    return result;    
}    

// 判断定位权限是否开启    
function judgeIosPermissionLocation() {    
    var result = false;    
    var cllocationManger = plus.ios.import("CLLocationManager");    
    var status = cllocationManger.authorizationStatus();    
    result = (status != 2)    
    console.log("定位权限开启:" + result);    
    // 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation    
    /* var enable = cllocationManger.locationServicesEnabled();    
    var status = cllocationManger.authorizationStatus();    
    console.log("enable:" + enable);    
    console.log("status:" + status);    
    if (enable && status != 2) {    
        result = true;    
        console.log("手机定位服务已开启且已授予定位权限");    
    } else {    
        console.log("手机系统的定位没有打开或未给予定位权限");    
    } */    
    plus.ios.deleteObject(cllocationManger);    
    return result;    
}    

// 判断麦克风权限是否开启    
function judgeIosPermissionRecord() {    
    var result = false;    
    var avaudiosession = plus.ios.import("AVAudioSession");    
    var avaudio = avaudiosession.sharedInstance();    
    var permissionStatus = avaudio.recordPermission();    
    console.log("permissionStatus:" + permissionStatus);    
    if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {    
        console.log("麦克风权限没有开启");    
    } else {    
        result = true;    
        console.log("麦克风权限已经开启");    
    }    
    plus.ios.deleteObject(avaudiosession);    
    return result;    
}    

// 判断相机权限是否开启    
function judgeIosPermissionCamera() {    
    var result = false;    
    var AVCaptureDevice = plus.ios.import("AVCaptureDevice");    
    var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');    
    console.log("authStatus:" + authStatus);    
    if (authStatus == 3) {    
        result = true;    
        console.log("相机权限已经开启");    
    } else {    
        console.log("相机权限没有开启");    
    }    
    plus.ios.deleteObject(AVCaptureDevice);    
    return result;    
}    

// 判断相册权限是否开启    
function judgeIosPermissionPhotoLibrary() {    
    var result = false;    
    var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");    
    var authStatus = PHPhotoLibrary.authorizationStatus();    
    console.log("authStatus:" + authStatus);    
    if (authStatus == 3) {    
        result = true;    
        console.log("相册权限已经开启");    
    } else {    
        console.log("相册权限没有开启");    
    }    
    plus.ios.deleteObject(PHPhotoLibrary);    
    return result;    
}    

// 判断通讯录权限是否开启    
function judgeIosPermissionContact() {    
    var result = false;    
    var CNContactStore = plus.ios.import("CNContactStore");    
    var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);    
    if (cnAuthStatus == 3) {    
        result = true;    
        console.log("通讯录权限已经开启");    
    } else {    
        console.log("通讯录权限没有开启");    
    }    
    plus.ios.deleteObject(CNContactStore);    
    return result;    
}    

// 判断日历权限是否开启    
function judgeIosPermissionCalendar() {    
    var result = false;    
    var EKEventStore = plus.ios.import("EKEventStore");    
    var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);    
    if (ekAuthStatus == 3) {    
        result = true;    
        console.log("日历权限已经开启");    
    } else {    
        console.log("日历权限没有开启");    
    }    
    plus.ios.deleteObject(EKEventStore);    
    return result;    
}    

// 判断备忘录权限是否开启    
function judgeIosPermissionMemo() {    
    var result = false;    
    var EKEventStore = plus.ios.import("EKEventStore");    
    var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);    
    if (ekAuthStatus == 3) {    
        result = true;    
        console.log("备忘录权限已经开启");    
    } else {    
        console.log("备忘录权限没有开启");    
    }    
    plus.ios.deleteObject(EKEventStore);    
    return result;    
}    

// Android权限查询    
function requestAndroidPermission(permissionID) {    
    return new Promise((resolve, reject) => {    
        plus.android.requestPermissions(    
            permissionID.split(","),    
            // [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装    
            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    
                }    
                resolve(result);    
                // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限    
                // if (result != 1) {    
                // gotoAppPermissionSetting()    
                // }    
            },    
            function(error) {    
                console.log('申请权限错误:' + error.code + " = " + error.message);    
                resolve({    
                    code: error.code,    
                    message: error.message    
                });    
            }    
        );    
    });    
}    

// 使用一个方法,根据参数判断权限    
function judgeIosPermission(permissionID) {    
    if (permissionID == "location") {    
        return judgeIosPermissionLocation()    
    } else if (permissionID == "camera") {    
        return judgeIosPermissionCamera()    
    } else if (permissionID == "photoLibrary") {    
        return judgeIosPermissionPhotoLibrary()    
    } else if (permissionID == "record") {    
        return judgeIosPermissionRecord()    
    } else if (permissionID == "push") {    
        return judgeIosPermissionPush()    
    } else if (permissionID == "contact") {    
        return judgeIosPermissionContact()    
    } else if (permissionID == "calendar") {    
        return judgeIosPermissionCalendar()    
    } else if (permissionID == "memo") {    
        return judgeIosPermissionMemo()    
    }    
    return false;    
}    

// 跳转到**应用**的权限页面    
function gotoAppPermissionSetting() {    
    if (isIos) {    
        var UIApplication = plus.ios.import("UIApplication");    
        var application2 = UIApplication.sharedApplication();    
        var NSURL2 = plus.ios.import("NSURL");    
        // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");         
        var setting2 = NSURL2.URLWithString("app-settings:");    
        application2.openURL(setting2);    

        plus.ios.deleteObject(setting2);    
        plus.ios.deleteObject(NSURL2);    
        plus.ios.deleteObject(application2);    
    } else {    
        // console.log(plus.device.vendor);    
        var Intent = plus.android.importClass("android.content.Intent");    
        var Settings = plus.android.importClass("android.provider.Settings");    
        var Uri = plus.android.importClass("android.net.Uri");    
        var mainActivity = plus.android.runtimeMainActivity();    
        var intent = new Intent();    
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);    
        var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);    
        intent.setData(uri);    
        mainActivity.startActivity(intent);    
    }    
}    

// 检查系统的设备服务是否开启    
// var checkSystemEnableLocation = async function () {    
function checkSystemEnableLocation() {    
    if (isIos) {    
        var result = false;    
        var cllocationManger = plus.ios.import("CLLocationManager");    
        var result = cllocationManger.locationServicesEnabled();    
        console.log("系统定位开启:" + result);    
        plus.ios.deleteObject(cllocationManger);    
        return result;    
    } else {    
        var context = plus.android.importClass("android.content.Context");    
        var locationManager = plus.android.importClass("android.location.LocationManager");    
        var main = plus.android.runtimeMainActivity();    
        var mainSvr = main.getSystemService(context.LOCATION_SERVICE);    
        var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);    
        console.log("系统定位开启:" + result);    
        return result    
    }    
}    

let permissionMap = {    
    "android": {    
        "CAMERA_EXTERNAL_STORAGE": {    
            "name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA",    
            "title": "相机/相册权限说明",    
            "content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"    
        },    
        "CAMERA": {    
            "name": "android.permission.CAMERA",    
            "title": "相机权限说明",    
            "content": "便于您使用该功能拍照更换头像、意见反馈上传图片、与客服沟通等场景中发送拍摄图片"    
        },    
        "EXTERNAL_STORAGE": {    
            "name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE",    
            "title": "相册权限说明",    
            "content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"    
        }    
    },    
    "ios": {}    
}    

let view = null;    

function showViewDesc(permission) {    
    let plat = isIos ? "ios" : "android";    
    view = new plus.nativeObj.View('per-modal', {    
        top: '0px',    
        left: '0px',    
        width: '100%',    
        backgroundColor: 'rgba(0,0,0,0.2)',    
        //opacity: '.9'       
    })    
    view.drawRect({    
        color: '#fff',    
        radius: '5px'    
    }, {    
        top: '30px',    
        left: '5%',    
        width: '90%',    
        height: "100px",    
    })    
    view.drawText(permissionMap[plat][permission]["title"], {    
        top: '40px',    
        left: "8%",    
        height: "30px"    
    }, {    
        align: "left",    
        color: "#000",    
    }, {    
        onClick: function(e) {    
            console.log(e);    
        }    
    })    
    view.drawText(permissionMap[plat][permission]["content"], {    
        top: '65px',    
        height: "60px",    
        left: "8%",    
        width: "84%"    
    }, {    
        whiteSpace: 'normal',    
        size: "14px",    
        align: "left",    
        color: "#656563"    
    })   
        setTimeout(()=>{  
            if(viewShow) view.show()  
        },200)  
}    

function premissionCheck(permission) {    
    return new Promise(async (resolve, reject) => {    
        let plat = isIos ? "ios" : "android";    
        if (isIos) { // ios    
            // const camera = permission.judgeIosPermission("camera");//判断ios是否给予摄像头权限    
            // //ios相册没权限,系统会自动弹出授权框    
            // //let photoLibrary = permission.judgeIosPermission("photoLibrary");//判断ios是否给予相册权限    
            // if(camera){    
            //     resolve();    
            // }else{    
            //     reject('需要开启相机使用权限');    
            // }    
            resolve(1)    
        } else { // android    
            let permission_arr = permissionMap[plat][permission]["name"].split(",");    
            let flag = true;    
            for(let i = 0;i<permission_arr.length;i++) {    
                let status = plus.navigator.checkPermission(permission_arr[i]);    
                if(status == "undetermined") {    
                    flag = false;    
                }    
            }    
            if (flag == false) { // 未完全授权    
                                showViewDesc(permission);  
                requestAndroidPermission(permissionMap[plat][permission]["name"]).then((res) => {    
                                        viewShow = false;  
                                        setTimeout(()=>{  
                                            viewShow = true;  
                                        },120)  
                    view.close();    
                    if (res == -1) {    
                        uni.showModal({    
                            title: '提示',    
                            content: '操作权限已被拒绝,请手动前往设置',    
                            confirmText: "立即设置",    
                            success: (res) => {    
                                if (res.confirm) {    
                                    gotoAppPermissionSetting()    
                                }    
                            }    
                        })    
                    }    
                    resolve(res)    
                })    
            } else {    
                resolve(1)    
            }    
        }    
    })    
}    

module.exports = {    
    judgeIosPermission: judgeIosPermission,    
    requestAndroidPermission: requestAndroidPermission,    
    checkSystemEnableLocation: checkSystemEnableLocation,    
    gotoAppPermissionSetting: gotoAppPermissionSetting,    
    premissionCheck: premissionCheck    
}
收起阅读 »

uniapp video H5页面设置srcObject分享

h5 stream video

需要先获取到组件video,直接获取绑定的id在uniapp中获取到的是uni-video标签,真正的标签是uni-video内包裹的video标签,要给内层的标签进行设置
代码如下:

<video id="video-dom"></video>

const vidoDom = document.querySelector('#video-dom video')
vidoDom.srcObject = stream
vidoDom.play();

珍惜成果,热心分享,给个

继续阅读 »

需要先获取到组件video,直接获取绑定的id在uniapp中获取到的是uni-video标签,真正的标签是uni-video内包裹的video标签,要给内层的标签进行设置
代码如下:

<video id="video-dom"></video>

const vidoDom = document.querySelector('#video-dom video')
vidoDom.srcObject = stream
vidoDom.play();

珍惜成果,热心分享,给个

收起阅读 »

全局搜索了个uni.requireNativePlugin,直接吧Hbuilder卡死,重启电脑再次打开依然卡死。

卡慢 HBuilderX

全局搜索了个uni.requireNativePlugin,直接吧Hbuilder卡死,重启电脑再次打开依然卡死。
写代码写上一会就特别卡。

全局搜索了个uni.requireNativePlugin,直接吧Hbuilder卡死,重启电脑再次打开依然卡死。
写代码写上一会就特别卡。

2023年11月阿里云版uniCloud故障说明及赔付方案公告

uniCloud

2023年11月份,阿里云版的uniCloud发生了3次故障,DCloud紧急联系阿里云快速治理恢复。

故障后,阿里云内部也及时做了复盘,现将故障原因及改进措施同步如下:

针对此次故障,依据相关SLA协议,DCloud将执行如下赔付方案:

  • 2023年11月,开发者实际消耗阿里云版uniCloud服务费用总额的10%,DCloud以代金券方式返还给开发者
  • DCloud会在1个月内(2024年1月12日之前),支持在购买包月套餐及按量扣费时,使用代金券

DCloud会继续督促阿里云切实提升服务质量,增强安全防控,确保服务的健壮稳定。

继续阅读 »

2023年11月份,阿里云版的uniCloud发生了3次故障,DCloud紧急联系阿里云快速治理恢复。

故障后,阿里云内部也及时做了复盘,现将故障原因及改进措施同步如下:

针对此次故障,依据相关SLA协议,DCloud将执行如下赔付方案:

  • 2023年11月,开发者实际消耗阿里云版uniCloud服务费用总额的10%,DCloud以代金券方式返还给开发者
  • DCloud会在1个月内(2024年1月12日之前),支持在购买包月套餐及按量扣费时,使用代金券

DCloud会继续督促阿里云切实提升服务质量,增强安全防控,确保服务的健壮稳定。

收起阅读 »

【UniAPP X快速上手】如何使用UniAPPX开发一个原生安卓商城

uniapp 教程 uniapp插件 uniapp模板

什么是UniAPP X

uni-app x,是下一代 uni-app,是一个跨平台应用开发引擎。

uni-app x 没有使用js和webview,它基于 uts 语言。在App端,uts在iOS编译为swift、在Android编译为kotlin,完全达到了原生应用的功能、性能。
更重要的是,UniAPP X未来也会支持鸿蒙,这里引用DCloud社区的官方答复
> DCloud有资源第一时间得到鸿蒙无apk手机的上市计划。我们和华为保持着紧密沟通,会把握好节奏,不用担心。大家可以观察一个信号,等微信的鸿蒙next版敲定了,鸿蒙无apk手机就可以明确上市计划了。鸿蒙的开发语言是arkTS,uni-app x是uts,都是变种ts,uni-app x编译到鸿蒙是靠谱的。
而把uni-app的js编译成arkTS不靠谱。除非编个h5跑在鸿蒙的webview里,但这个体验估计没多少人能接受。

如何学习UniAPP X

1. 学习官方文档

这里的重点和难点应该是UTS语言,因为UTS语言需要编译成Kotlin语言,所以有强类型要求,会TypeScript的同学适应起来会快一些,只是习惯js的同学可能上手会难,可以参考官方组件库easyX的写法,多多学习。

2. 学习UTS语言

UTS语言是TS的变种,建议先学习TS。就连鸿蒙原生开发用的ArkTS也是TS的变种(笔者最近在开发鸿蒙原生应用,会TS上手很快),可见TS的重要性。学习TS可以参考如下教程:
TypeScript 教程

上手TS之后,需要重点关注UTS和TS的区别。

  • UTS为Kotlin和Swift新增了一些专有数据类型;
  • UTS有一些特殊的内置对象和API

其实这些区别主要是为了原生开发的,但是比直接上手安卓和iOS原生开发要简单太多。

3. 关注UniAPP X的Vue规范

uni-app x的vue规范,按照vue3规范实现,但目前不支持setup组合式写法,仅支持option选项式写法。而且有些Vue3的api也不支持。大家在开发过程中遇到问题,要查看官方文档里重点列出的差异
UniAPP X的Vue实现

原生安卓商城的开发

前面的学习铺垫,是为了大家开发过程更加顺利。实际上,easyX已经封装好了常见的电商业务组件,并且已经上线了一些模板。即使是小白,也可以直接用easyX开发出一个原生商城。先看效果
商城首页模板
这个页面的代码可以查看Gitee示例代码, 大家直接复制粘贴即可。

使用easyX组件库和模板库

使用easyX有两种方式,一种是从Gitee下载源码,另一种是从UniAPP插件市场下载源码

下载源码之后解压,找到components目录,将该目录下的所有内容复制到你的UniAPP X项目下的components目录即可使用。
eaxyX支持按需引用,各个组件的具体使用可以查看相关easyX组件文档

当然,您也可以直接下载安卓easyX的安卓apk体验。

easyX演示包下载安装链接

easyX采用MIT协议开源,组件库和模板库仍在不断扩充。对于开发原生商城应用的同学来说,是个宝藏库。等UniAPPX支持鸿蒙后,easyX用来开发鸿蒙原生商城,想想真是吊炸天的开发利器。

应用打包

安卓打包是需要证书的。如果想省事,直接使用Dcloud的公共云证书,傻瓜式操作,不过因为有人滥用这个证书,现在很多品牌的手机会报毒,所以还是建议自己申请证书。
免费证书申请攻略

应用上线

如果要上架到华为、小米、oppo等应用市场,那就需要软件著作权和应用备案了。软件著作权的申请周期比较长,大概3个月,应用备案就快很多了。网上很多服务商提供这两项服务,大家也可以私信我,公司业务可以按照市场最低价给大家服务,个人业务可以提供一些免费指导然后你自己操作。

我是刘明,十年创业老兵,开源技术爱好者。
有问题欢迎私信。

继续阅读 »

什么是UniAPP X

uni-app x,是下一代 uni-app,是一个跨平台应用开发引擎。

uni-app x 没有使用js和webview,它基于 uts 语言。在App端,uts在iOS编译为swift、在Android编译为kotlin,完全达到了原生应用的功能、性能。
更重要的是,UniAPP X未来也会支持鸿蒙,这里引用DCloud社区的官方答复
> DCloud有资源第一时间得到鸿蒙无apk手机的上市计划。我们和华为保持着紧密沟通,会把握好节奏,不用担心。大家可以观察一个信号,等微信的鸿蒙next版敲定了,鸿蒙无apk手机就可以明确上市计划了。鸿蒙的开发语言是arkTS,uni-app x是uts,都是变种ts,uni-app x编译到鸿蒙是靠谱的。
而把uni-app的js编译成arkTS不靠谱。除非编个h5跑在鸿蒙的webview里,但这个体验估计没多少人能接受。

如何学习UniAPP X

1. 学习官方文档

这里的重点和难点应该是UTS语言,因为UTS语言需要编译成Kotlin语言,所以有强类型要求,会TypeScript的同学适应起来会快一些,只是习惯js的同学可能上手会难,可以参考官方组件库easyX的写法,多多学习。

2. 学习UTS语言

UTS语言是TS的变种,建议先学习TS。就连鸿蒙原生开发用的ArkTS也是TS的变种(笔者最近在开发鸿蒙原生应用,会TS上手很快),可见TS的重要性。学习TS可以参考如下教程:
TypeScript 教程

上手TS之后,需要重点关注UTS和TS的区别。

  • UTS为Kotlin和Swift新增了一些专有数据类型;
  • UTS有一些特殊的内置对象和API

其实这些区别主要是为了原生开发的,但是比直接上手安卓和iOS原生开发要简单太多。

3. 关注UniAPP X的Vue规范

uni-app x的vue规范,按照vue3规范实现,但目前不支持setup组合式写法,仅支持option选项式写法。而且有些Vue3的api也不支持。大家在开发过程中遇到问题,要查看官方文档里重点列出的差异
UniAPP X的Vue实现

原生安卓商城的开发

前面的学习铺垫,是为了大家开发过程更加顺利。实际上,easyX已经封装好了常见的电商业务组件,并且已经上线了一些模板。即使是小白,也可以直接用easyX开发出一个原生商城。先看效果
商城首页模板
这个页面的代码可以查看Gitee示例代码, 大家直接复制粘贴即可。

使用easyX组件库和模板库

使用easyX有两种方式,一种是从Gitee下载源码,另一种是从UniAPP插件市场下载源码

下载源码之后解压,找到components目录,将该目录下的所有内容复制到你的UniAPP X项目下的components目录即可使用。
eaxyX支持按需引用,各个组件的具体使用可以查看相关easyX组件文档

当然,您也可以直接下载安卓easyX的安卓apk体验。

easyX演示包下载安装链接

easyX采用MIT协议开源,组件库和模板库仍在不断扩充。对于开发原生商城应用的同学来说,是个宝藏库。等UniAPPX支持鸿蒙后,easyX用来开发鸿蒙原生商城,想想真是吊炸天的开发利器。

应用打包

安卓打包是需要证书的。如果想省事,直接使用Dcloud的公共云证书,傻瓜式操作,不过因为有人滥用这个证书,现在很多品牌的手机会报毒,所以还是建议自己申请证书。
免费证书申请攻略

应用上线

如果要上架到华为、小米、oppo等应用市场,那就需要软件著作权和应用备案了。软件著作权的申请周期比较长,大概3个月,应用备案就快很多了。网上很多服务商提供这两项服务,大家也可以私信我,公司业务可以按照市场最低价给大家服务,个人业务可以提供一些免费指导然后你自己操作。

我是刘明,十年创业老兵,开源技术爱好者。
有问题欢迎私信。

收起阅读 »

解决安卓弹出虚拟键盘时,顶部fixed消失的问题

fixed 虚拟键盘

思路:关掉输入框的adjust-position,键盘就不会把fixed元素顶上去。然后弹出键盘时页面滚动到输入框光标的位置。

<input :adjust-position="false" @keyboardheightchange="handleKeyboardHeightChange"></input>
handleKeyboardHeightChange(e) {  
    const keyboardHeight = e.detail.height  
    // e.target.offsetTop就是输入框中的光标在整个页面的scrollTop。  
    const inputTop = e.target.offsetTop  
    if (keyboardHeight > 0) {  
        const safeHeight = uni.getWindowInfo().safeArea.height  
        const upperHeight = safeHeight - keyboardHeight  

        this.pagePaddingBottom = keyboardHeight  
        setTimeout(() => {  
            uni.pageScrollTo({  
                scrollTop: inputTop - upperHeight + 50,  
                duration: 50,  
            })  
        })  
    } else {  
        this.pagePaddingBottom = 0  
    }  
}
继续阅读 »

思路:关掉输入框的adjust-position,键盘就不会把fixed元素顶上去。然后弹出键盘时页面滚动到输入框光标的位置。

<input :adjust-position="false" @keyboardheightchange="handleKeyboardHeightChange"></input>
handleKeyboardHeightChange(e) {  
    const keyboardHeight = e.detail.height  
    // e.target.offsetTop就是输入框中的光标在整个页面的scrollTop。  
    const inputTop = e.target.offsetTop  
    if (keyboardHeight > 0) {  
        const safeHeight = uni.getWindowInfo().safeArea.height  
        const upperHeight = safeHeight - keyboardHeight  

        this.pagePaddingBottom = keyboardHeight  
        setTimeout(() => {  
            uni.pageScrollTo({  
                scrollTop: inputTop - upperHeight + 50,  
                duration: 50,  
            })  
        })  
    } else {  
        this.pagePaddingBottom = 0  
    }  
}
收起阅读 »

开发一套小程序和后台。具体so liao qso liao q

开发一套后台和一个小程序功能简单能做的资料具体

开发一套后台和一个小程序功能简单能做的资料具体

CodeGeeX 支持 HBuilderX 啦

OpenAI

我看这个已经出来了,我之前用 vscode 用的多,大家用着怎么样

https://ext.dcloud.net.cn/plugin?id=15497#rating

我看这个已经出来了,我之前用 vscode 用的多,大家用着怎么样

https://ext.dcloud.net.cn/plugin?id=15497#rating

uni-AD原生广告SDK-合规使用说明

uni_ad

SDK合规指引

  1. 按照中国国家法律法规、政策及标准的要求,在APP上应对《隐私政策》进行展示。开发者应在APP首次启动和登录注册页面,通过弹窗、超链接等方式,清晰告知用户个人信息处理规则,在用户充分阅读并同意的情况下再读取用户信息设备信息。《隐私政策》可参考国家标准《信息安全技术个人信息安全规范》文件中的隐私政策模板编写。
    </br>
    接入规范及建议

    • 需要在用户明确同意隐私政策\服务条款后,才可以初始化uni-AD原生广告。游客模式下不得初始化广告SDK。
    • 用户未同意隐私政策\服务条款前,禁止获取、传输用户数据;禁止弹出系统权限弹窗向用户申请系统权限。
    • 请勿在App处于未激活状态时(例如App在后台运行)请求优量汇相关服务
  2. 应在APP的隐私政策、信息共享清单中明确披露uni-AD原生广告SDK和其他三方广告SDK(如优量汇、穿山甲、快手等)的名称、功能、信息类型及隐私政策等信息。
    uni-AD原生广告SDK披露信息可参考下段内容

    SDK名称:uni-AD原生广告SDK  
    
    开发者:数字天堂(北京)网络技术有限公司  
    
    主要功能:广告投放、三方广告联盟SDK聚合服务  
    
    个人信息类型:必要信息:设备信息(设备品牌、型号、操作系统版本、分辨率、设备语言、手机系统时间、设备名称、时区、屏幕密度),应用信息(应用名、应用包名、版本号)可选信息:设备信息(网络类型、IP地址、User Agent信息、BSSID、SSID),设备标识符(如IMEI/MEID、IMSI、GAID(仅GMS服务)、AndroidID、OAID),运营商信息,位置信息,传感器,应用安装列表。  
    
    SDK隐私政策:https://dcloud.io/license/uni-ad.html  
  3. SDK可选个人信息的配置说明

    <table style="word-break:break-all">
    <tr>
    <th style="width:30%">可选个人信息类型及字段</th>
    <th style="width:15%">使用目的</th>
    <th style="width:15%">使用场景</th>
    <th style="width:40%">配置方案及示例</th>
    </tr>
    <tr>
    <td><b>标识符</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />IMEI(Device ID)、Android_ID、OAID、MAC地址</td>
    <td>广告投放、广告归因、广告监测、反作弊</td>
    <td>在进行广告投放和广告统计分析时使用</td>
    <td>
    <pre><code class="language-java">
    DCloudAdManager.init(this,config);
    // 初始化之后立即调用setPrivacyConfig方法
    DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
    /**

    • 是否允许SDK主动获取手机设备信息,如:imei,运营商信息
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUsePhoneState() {
      return false;
      }
      /**
    • 是否允许SDK主动获取MAC地址
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetMacAddress() {
      return false;
      }
      /**
    • 是否允许SDK主动获取Android id
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetAndroidId() {
      return false;
      }
      /**
    • 是否允许SDK主动获取OAID
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetOAID() {
      return false;
      }
      /**
    • 是否允许SDK主动获取IP地址
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetIP() {
      return false;
      }
      });
      </code></pre></td>
      </tr>
      <tr>
      <td><b>应用安装列表信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />应用安装列表信息</td>
      <td>广告投放、反作弊</td>
      <td>在进行广告投放和广告统计分析时使用</td>
      <td>
      <pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许SDK主动收集上传应用列表
    • @return true 允许SDK收集,false 不允许
      */
      @Override
      public boolean isCanGetInstallAppList() {
      return super.isCanGetInstallAppList();
      }
      /**
    • 是否允许SDK主动收集上传后台运行的应用列表
    • @return true 允许SDK收集,false 不允许
      */
      @Override
      public boolean isCanGetRunningApps() {
      return super.isCanGetRunningApps();
      }
      });</code></pre>
      </td>
      </tr>
      <tr>
      <td><b>传感器信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />线性加速度传感器、磁场传感器、旋转矢量传感器、加速度传感器、陀螺仪传感器</td>
      <td>广告投放、广告反作弊</td>
      <td>在进行摇一摇、扭一扭等广告投放和广告反作弊分析时使用</td>
      <td>
      <pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许使用传感器
    • @return true 开启, false 关闭,默认值为true
      */
      @Override
      public boolean isCanUseSensor() {
      return super.isCanUseSensor();
      }
      });</code></pre>
      </td>
      </tr>
      <tr>
      <td><b>位置信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />精确位置信息、粗略位置信息</td>
      <td>广告投放、广告反作弊</td>
      <td>在进行广告投放和广告统计分析时使用</td>
      <td>
      <pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许SDK主动获取地理位置信息
    • @return true可以获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUseLocation() {
      return super.isCanUseLocation();
      }
      });</code></pre>
      </td>
      </tr>
      <tr>
      <td><b>运营商信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />运营商信息</td>
      <td>广告投放、广告反作弊</td>
      <td>在进行广告投放和广告统计分析时使用</td>
      <td><pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许SDK主动获取手机设备信息,如:imei
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUseWifiState() {
      return super.isCanUseWifiState();
      }

    /**

    • 是否允许SDK主动获取手机运营商信息
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUseSimOperator() {
      return super.isCanUseSimOperator();
      }
      });</code></pre>
      </td>
      </tr>
      </table>
  4. SDK 权限说明

    权限名称 功能 目的 申请时机
    android.permission.ACCESS_NETWORK_STATE<br/>android.permission.ACCESS_WIFI_STATE 获取网络信息 广告监测、统计分析 开发者在调用需要该权限的SDK功能且用户已授权相应权限时。
    android.permission.ACCESS_COARSE_LOCATION<br/>android.permission.ACCESS_FINE_LOCATION 获取位置信息 广告主归因及投放 开发者在调用需要该权限的SDK功能且用户已授权相应权限时。
    android.permission.READ_PHONE_STATE 获取手机设备标识等信息 广告监测、统计分析、广告主投放 开发者在调用需要该权限的SDK功能且用户已授权相应权限时。
  5. 应在应用设置页面等位置提供“个性化广告”关闭按钮。
    uni-AD原生广告SDK提供设置“个性化广告”开关的API

    是否开启个性化广告 false为关闭个性化推荐,默认为true  
    
    DCloudAdManager.setPersonalAd(Context context, boolean isOpen);  
  6. 应在向用户展示广告时,提供“关闭(X)”或“跳过”按钮,点击之后广告可以关闭。
    注意:展示广告时不得对“跳过”、“关闭”按钮进行遮挡。

APP合规指引

  1. 隐私弹窗
    应用在首次启动时需要弹窗提示,弹窗内容中需要包含隐私政策\服务条款链接。隐私政策弹框需要提供明确的拒绝按钮。

  2. 隐私政策

    • 隐私政策应该单独成文,不得与用户协议等说明文件的一部分存在。
    • 隐私政策中应清晰描述每个SDK的收集使用个人信息的目的、方式、范围及收集的个人信息类型及权限说明
    • 隐私政策应由最终用户自主选择是否同意,不应以默认勾选“同意”的方式取得用户授权。
    • 因业务需要,确需超出上述范围使用个人信息的,应再次征得用户明示同意。
  3. APP合规规范

    • 用户未同意隐私政策或者游客模式下,不得通过任何方式获取、传输用户隐私信息。
    • 隐私政策\服务条款应该有专门的链接公示。
    • 用户进入您的产品主功能界面后,通过4次以内的点击/滑动,能够访问到您的产品隐私政策。
    • 不应通过捆绑产品或服务各项业务功能的方式,要求用户一次性接受并授权同意其未申请或使用的业务功能收集个人信息的请求。
    • 用户明确表示不同意后,不得频繁征求用户同意、干扰用户正常使用。
    • 不得超范围获取用户信息。
    • APP不应收集与业务功能无任何关系的个人信息。
    • APP更新升级后,不应更改原有的系统权限设置。
  4. 最小必要数据收集
    在仅能收集最小必要的个人信息的情形下,仍能保证用户能使用APP的基本功能服务,可参考《常见类型移动互联网应用程序必要个人信息范围规定》

  5. 个性化退出机制。
    如果用户存在定向推送功能(个性化推荐,营销推送等功能),需要提供关闭定向推送功能的选项。

  6. 账号注销
    APP需要提供账户注销的途径,并在用户注销账号后,及时删除其个人信息或进行匿名化处理。

  7. 投诉管理
    APP应建立投诉管理机制和投诉跟踪流程,并在合理的时间内对投诉进行响应。

uni-AD原生广告集成的三方SDK说明

<table style="word-break:break-all">
<tr>
<th style="width:8%">SDK名称</th>
<th style="width:10%">SDK包名/网址</th>
<th style="width:8%">SDK用途</th>
<th style="width:20%">可能获取的个人信息类型</th>
<th style="width:25%">调用的设备权限</th>
<th style="width:20%">信息用途</th>
<th style="width:10%">SDK隐私政策链接/目的</th>
</tr>
<tr>
<td>快手 </td>
<td>com.kwad.sdk </td>
<td>增强广告 </td>
<td>基础信息:设备品牌、设备型号、软件系统版本、存储信息、运营商信息、设备时区、设备语言、网络信息等基础信息</br>
设备标识:IMEIs、MEID、OAID、AndroidID、IMSIs、ICCID</br>
位置信息:IP地址、MAC地址、GPS位置信息、基站信息、WIFI信息</br>
应用信息:应用安装列表</br>
其他信息:传感器信息、sim卡激活信息</td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.INTERNET <br>
android.permission.READ_PHONE_STATE <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.VIBRATE
</td>
<td>广告投放、广告归因、反作弊、安全 </td>
<td><a href="https://www.kuaishou.com/about/policy" target="_blank">快手内容联盟隐私协议</a>和<a href="https://u.kuaishou.com/home/detail/1220" target="_blank">SDK使用规范</a></td>
</tr>
<tr>
<td>快手内容联盟 </td>
<td>com.kwad.sdk </td>
<td>增强广告 </td>
<td>基础信息:设备品牌、设备型号、软件系统版本、存储信息、运营商信息、设备时区、设备语言、网络信息等基础信息</br>
设备标识:IMEIs、MEID、OAID、AndroidID、IMSIs、ICCID</br>
位置信息:IP地址、MAC地址、GPS位置信息、基站信息、WIFI信息</br>
应用信息:应用安装列表</br>
其他信息:传感器信息、sim卡激活信息 </td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.INTERNET <br>
android.permission.READ_PHONE_STATE <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.VIBRATE <br>
android.permission.SET_WALLPAPER<br>
android.permission.READ_EXTERNAL_STORAGE <br>
android.permission.WRITE_EXTERNAL_STORAGE <br>
android.permission.ACCESS_COARSE_LOCATION <br>
android.permission.BLUETOOTH
</td>
<td>广告投放、广告归因、反作弊、安全 </td>
<td><a href="https://www.kuaishou.com/about/policy" target="_blank">快手内容联盟隐私协议</a>和<a href="https://u.kuaishou.com/home/detail/1220" target="_blank">SDK使用规范</a></td>
</tr>
<tr>
<td>优量汇 </td>
<td>com.qq.e<br/>com.android.gdt.qone </td>
<td>增强广告 </td>
<td>基站、附近的WIFI、连接的WIFI、位置信息、设备制造商、设备型号、操作系统版本、屏幕分辨率、屏幕方向、屏幕DPI、IP地址、加速度传感器、磁场传感器、OAID、IMEI/MEID(Device ID)、Android_ID、包名、版本号、进程名称、运行状态、可疑行为、应用安装信息 </td>
<td style="font-size:12px">
android.permission.INTERNET <br>
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.CHANGE_NETWORK_STATE<br>
android.permission.QUERY_ALL_PACKAGES <br>
android.permission.REORDER_TASKS<br>
android.permission.VIBRATE <br>
android.permission.ACCESS_COARSE_LOCATION
</td>
<td style="font-size:12px">广告投放与监测归因、广告主统计投放结果、减少App崩溃、确保服务器正常运行、提升可扩展性和性能</td>
<td><a href="https://e.qq.com/dev/help_detail.html?cid=2005&pid=5983" target="_blank">优量汇隐私协议</a></td>
</tr>
<tr>
<td>穿山甲 </td>
<td>com.bytedance.sdk.openadsdk</td>
<td>增强广告 </td>
<td>设备品牌、型号、软件系统版本、分辨率、网络信号强度、IP地址、设备语言、传感器信息等基础信息、无线网SSID名称、MAC地址、AndroidID、应用名、应用包名、版本号、应用前后台状态、应用列表信息、运营商信息、设备时区 </td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.READ_PHONE_STATE <br>
android.permission.WRITE_EXTERNAL_STORAGE
</td>
<td>广告投放合作、广告归因、反作弊 </td>
<td><a href="https://www.pangle.cn/privacy/partner" target="_blank">穿山甲隐私协议</a></td>
</tr>
<tr>
<td>Sigmob </td>
<td>com.sigmob.windad </td>
<td>增强广告 </td>
<td>设备信息:设备品牌、型号、操作系统版本、OAID、分辨率等基础设备信息
应用信息:应用名称、应用包名、应用版本号等
其他:运营商信息、时区</td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.INTERNET <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.CHANGE_WIFI_STATE <br>
android.permission.READ_PHONE_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.QUERY_ALL_PACKAGES
</td>
<td>广告投放、广告主归因、反作弊 </td>
<td><a href="https://doc.sigmob.com/#/Sigmob%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/%E9%9A%90%E7%A7%81%E6%9D%A1%E6%AC%BE/%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96/">Sigmob隐私协议</a></td>
</tr>
<tr>
<td>百度百青藤</td>
<td>com.baidu.mobads.proxy </td>
<td>增强广告 </td>
<td>设备信息:设备品牌、型号、软件系统版本、分辨率、网络信号强度、传感器信息,磁盘总空间、系统总内存空间、手机重启信息、手机系统更新时间等基础信息、OAID、AndroidID、屏幕宽高,屏幕像素密度,系统版本号,设备厂商,设备型号,手机运营商,手机网络状态,设备剩余存储空间,手机重启时间和更新时间
开发者应用信息:应用包名、应用前后台状态
设备信息:IMEI、IMSI、MEID
位置信息</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.READ_PHONE_STATE<br>
android.permission.ACCESS_COARSE_LOCATION<br>
android.permissio.WRITE_EXTERNAL_STORAGE<br>
</td>
<td>为最终用户提供安全保障、改善我们的产品和服务,开展内部审计、数据分析和研究 </td>
<td><a href="https://union.baidu.com/bqt/#/legal/policies">百度百青藤隐私协议</a></td>
</tr>

<tr>
<td>HUAWEI Ads</td>
<td>com.huawei.hms.ads.lite</td>
<td>增强广告 </td>
<td>设备及使用信息:设备标识符(OAID)、设备信息(设备型号、设备硬件信息、操作系统、系统设置、设备使用信息)、应用基本信息、应用设置信息、应用使用信息、传感器信息(陀螺仪、加速度计、旋转矢量传感器、磁力计、气压计)、网络信息、运营商信息、IP地址、WLAN信息(WiFi状态、WiFi参数、WiFi列表、BSSID与SSID)。广告互动信息:
您与本服务投放的广告之间的交互行为,如曝光、点击、内容交互等信息。。广告主服务互动信息:
基于广告投放优化、广告归因和效果分析等目的,广告主可能会向我们提供其与用户交互时获得的转化记录。</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.ACCESS_COARSE_LOCATION<br>
android.permission.ACCESS_FINE_LOCATION<br>
</td>
<td>单次请求的广告定向投放、程序化广告投放、广告监测归因与反作弊。</td>
<td><a href="https://developer.huawei.com/consumer/cn/doc/HMSCore-Guides/whale-hong-kinetic-energy-sdk-privacy-statement-0000001658283582">HUAWEI Ads 隐私声明</a><br><br>和<br><br><a href="https://legal.cloud.huawei.com/terms/scope/huawei/ads/privacy-statement.htm?&code=CN&language=zh-CN&branchid=0&contenttag=default">HUAWEI Ads SDK隐私安全说明</a></td>
</tr>
<tr>
<td>章鱼广告(Octopus SDK)</td>
<td>com.octopus.ad</td>
<td>增强广告 </td>
<td>设备信息:必选信息:设备品牌、型号、软件系统版本、屏幕密度、屏幕分辨率、设备语言、设备时区、CPU信息、可用存储空间大小等基础信息、AndroidID、OAID;可选信息:设备标识符(如OAID、GAID(仅GMS服务)。网络信息(必选):运营商信息、Wi-Fi状态、网络信号强度、IP地址。应用信息(必选):应用包名、运行中的进程信息、版本号。传感器信息(可选):线性加速度传感器、磁场传感器、旋转矢量传感器、加速度传感器、陀螺仪传感器。广告信息(必选):对广告的展示、点击及转化等交互数据。性能数据(必选):崩溃数据、性能数据</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.WRITE_EXTERNAL_STORAGE<br>
android.permission.READ_EXTERNAL_STORAGE<br>
</td>
<td>基于用户设备信息调整广告投放、统计分析、反作弊、实现广告正常显示与交互功能,通过崩溃信息,以此来优化代码缺陷,最大程度减少App崩溃。通过收集SDK运行过程中性能数据,以优化SDK的性能。统计广告数据,以用于广告主统计投放结果。</td>
<td><a href="https://doc.adintl.cn/#/zh-cn/guide/UsePrivacy">章鱼广告SDK隐私政策</a></td>
</tr>

<tr>
<td>倍孜广告(AdScope SDK)</td>
<td>com.beizi.ad<br/>ms.bz.bd.c</td>
<td>增强广告 </td>
<td>设备信息(必选):设备品牌、设备型号、设备时区、设备语言、系统版本、UserAgent信息、屏幕高宽、屏幕方向、屏幕DPI信息、系统更新时间、磁盘空间、物理内存、sim卡状态、cpu。网络信息(必选):网络类型、运营商。应用信息(必选):开发者应用名、应用版本号、应用包名、运行状态。标识符(必选):OAID。位置信息(可选):精确位置信息、粗略位置信息。传感器信息(可选):重力传感器、加速度传感器、方向传感器、陀螺仪、压力传感器、线性加速度传感器。广告信息(必选):产品交互数据、广告数据(展示、点击、转化)。诊断数据(必选):崩溃数据、性能数据</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.WRITE_EXTERNAL_STORAGE<br>
android.permission.READ_EXTERNAL_STORAGE<br>
</td>
<td>广告投放策略、统计分析服务、反作弊分析、广告正常显示与交互功能的实现、广告归因、最大程度减少App崩溃、确保服务器正常运行、提升可扩展性和性能</td>
<td><a href="https://sdkdoc.beizi.biz/#/zh-cn/guide/UsePrivacy">BeiZi SDK隐私保护声明</a></td>
</tr>

<tr>
<td>泛连</td>
<td>com.fl.saas.s2s<br/>com.fl.saas</td>
<td>增强广告 </td>
<td>设备信息:必选信息:设备品牌、设备型号、设备名称、软件系统版本、屏幕密度、屏幕分辨率、设备语言、设备时区、手机系统重启时间;可选信息:IMEI、IMSI、设备的MAC地址、User Agent、AndroidID。标识符:可选信息:设备ID(国内用户OAID、海外用户GAID)。网络信息:必选信息:IP地址、运营商信息、Wi-Fi状态、网络信号强度。应用信息:必选信息:应用版本、应用包名、应用名称、应用前后台状态。可选信息:应用列表信息。传感器信息:可选信息:重力传感器、加速度传感器、方向传感器、陀螺仪、压力传感器、重力传感器、线性加速度传感器。广告信息:必选信息:当用户与我们在您应用上推广的广告发生了交互行为,我们会手机广告的展示、点击及转化等交互数据。位置信息::粗略位置信息(WI-FI列表、WALAN接入点(如SSID、BSSID))、基站。其他信息:必选信息:系统崩溃数据、性能数据
</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.VIBRATE<br>
android.permission.REQUEST_INSTALL_PACKAGES<br>
android.permission.READ_PHONE_STATE<br/>
</td>
<td>广告投放及广告监测归因、反作弊、摇一摇广告投放、广告投放统计分析、提升SDK的稳定性,减少APP的崩溃</td>
<td><a href="https://www.adfunlink.com/doc/privacy.html">Funlink隐私保护声明</a></td>
</tr>
<tr>
<td>华夏乐游(优推广告)</td>
<td>com.alliance.ssp.ad</td>
<td>增强广告</td>
<td>设备信息:
必选信息:设备品牌、型号、软件系统版本、屏幕密度、屏幕分辨率、设备语言、设备时区等基础信息 【仅iOS】磁盘总空间、系统总内存空间;
可选信息:设备MAC地址、设备标识符(如IMEI、MEID,具体字段因软硬件版本不同而存在差异)如AndroidID、OAID、IMSI、IMEI、MEID 等。网络信息:
必选信息:运营商信息、网络状态(包括BSSID、SSID 等)、IP地址。应用信息 :必选信息:应用包名、版本号;可选信息:应用安装列表信息。传感器信息:必选信息:加速度传感器。广告信息:
必选信息:对广告的填充、展示、点击及转化等交互数据。位置信息:
可选信息:精确位置信息。性能数据:
必选信息:如崩溃数据、性能数据</td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.INTERNET<br>
android.permission.READ_PHONE_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.REQUEST_INSTALL_PACKAGES<br>
android.permission.ACCESS_FINE_LOCATION<br>
android.permission.ACCESS_COARSE_LOCATION<br>
android.permission.READ_EXTERNAL_STORAGE<br>
android.permission.WRITE_EXTERNAL_STORAGE<br>
android.permission.QUERY_ALL_PACKAGES<br>
</td>
<td>广告投放及广告反作弊。广告监测归因。保证网络服务有效性及稳定性。摇一摇、扭一扭功能。减少App崩溃、提供稳定可靠的服务</td>
<td><a href="https://lemon.gameley.com/flowdocs/%E4%BC%98%E6%8E%A8%E5%B9%BF%E5%91%8A%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE/%E4%BC%98%E6%8E%A8%E5%B9%BF%E5%91%8A%E5%B9%B3%E5%8F%B0SDK%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96.html">优推广告平台 SDK 隐私政策</a></td>
</tr>
<tr>
<td>微信开放平台</td>
<td>com.tencent.mm</td>
<td>快捷广告</td>
<td>网络信息、设备信息</td>
<td style="font-size:12px">
</td>
<td>打开小程序</td>
<td><a href="https://support.weixin.qq.com/cgi-bin/mmsupportacctnodeweb-bin/pages/RYiYJkLOrQwu0nb8">https://support.weixin.qq.com/cgi-bin/mmsupportacctnodeweb-bin/pages/RYiYJkLOrQwu0nb8</a></td>
</tr>
<tr>
<td>图灵盾风险识别SDK</td>
<td></td>
<td>腾讯优量汇必需功能</td>
<td>硬件序列号、网络状态、系统设置、系统属性、设备型号、操作系统、IP地址、运营商信息、标识符如OAID、IDFA、IDFV等
由第三方开发者根据实际情况决定是否采集并传输给SDK,SDK采取去标识、加密等方式进行处理</td>
<td style="font-size:12px">
</td>
<td>广告推荐、归因及反作弊场景统计,如虚假流量识别等。</td>
<td><a href="https://privacy.qq.com/document/preview/5331f064a91a47eb93993fdacb91c8f7">https://privacy.qq.com/document/preview/5331f064a91a47eb93993fdacb91c8f7</a></td>
</tr>

<tr>
<td>Qone SDK</td>
<td></td>
<td>腾讯优量汇必需功能</td>
<td>IP地址、设备型号、设备标识信息(OAID、Android ID、IDFA、IDFV等)</td>
<td style="font-size:12px">
</td>
<td>广告归因,识别黑产和虚假设备</td>
<td><a href="https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157">https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157</a></td>
</tr>
<tr>
<td>MSA移动安全联盟</td>
<td></td>
<td>获取OAID(可选)</td>
<td>品牌信息:设备制造商、设备型号、设备品牌。网络信息:设备网络运营商名称。应用软件信息:App包名及签名信息,或在对应应用商店的APPID。</td>
<td style="font-size:12px">
</td>
<td>判断终端品牌,调用接口。判断是否为虚拟机环境。生成VAID时判断是否为同一开发者。</td>
<td><a href="https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157">https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157</a></td>
</tr>
</table>

继续阅读 »

SDK合规指引

  1. 按照中国国家法律法规、政策及标准的要求,在APP上应对《隐私政策》进行展示。开发者应在APP首次启动和登录注册页面,通过弹窗、超链接等方式,清晰告知用户个人信息处理规则,在用户充分阅读并同意的情况下再读取用户信息设备信息。《隐私政策》可参考国家标准《信息安全技术个人信息安全规范》文件中的隐私政策模板编写。
    </br>
    接入规范及建议

    • 需要在用户明确同意隐私政策\服务条款后,才可以初始化uni-AD原生广告。游客模式下不得初始化广告SDK。
    • 用户未同意隐私政策\服务条款前,禁止获取、传输用户数据;禁止弹出系统权限弹窗向用户申请系统权限。
    • 请勿在App处于未激活状态时(例如App在后台运行)请求优量汇相关服务
  2. 应在APP的隐私政策、信息共享清单中明确披露uni-AD原生广告SDK和其他三方广告SDK(如优量汇、穿山甲、快手等)的名称、功能、信息类型及隐私政策等信息。
    uni-AD原生广告SDK披露信息可参考下段内容

    SDK名称:uni-AD原生广告SDK  
    
    开发者:数字天堂(北京)网络技术有限公司  
    
    主要功能:广告投放、三方广告联盟SDK聚合服务  
    
    个人信息类型:必要信息:设备信息(设备品牌、型号、操作系统版本、分辨率、设备语言、手机系统时间、设备名称、时区、屏幕密度),应用信息(应用名、应用包名、版本号)可选信息:设备信息(网络类型、IP地址、User Agent信息、BSSID、SSID),设备标识符(如IMEI/MEID、IMSI、GAID(仅GMS服务)、AndroidID、OAID),运营商信息,位置信息,传感器,应用安装列表。  
    
    SDK隐私政策:https://dcloud.io/license/uni-ad.html  
  3. SDK可选个人信息的配置说明

    <table style="word-break:break-all">
    <tr>
    <th style="width:30%">可选个人信息类型及字段</th>
    <th style="width:15%">使用目的</th>
    <th style="width:15%">使用场景</th>
    <th style="width:40%">配置方案及示例</th>
    </tr>
    <tr>
    <td><b>标识符</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />IMEI(Device ID)、Android_ID、OAID、MAC地址</td>
    <td>广告投放、广告归因、广告监测、反作弊</td>
    <td>在进行广告投放和广告统计分析时使用</td>
    <td>
    <pre><code class="language-java">
    DCloudAdManager.init(this,config);
    // 初始化之后立即调用setPrivacyConfig方法
    DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
    /**

    • 是否允许SDK主动获取手机设备信息,如:imei,运营商信息
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUsePhoneState() {
      return false;
      }
      /**
    • 是否允许SDK主动获取MAC地址
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetMacAddress() {
      return false;
      }
      /**
    • 是否允许SDK主动获取Android id
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetAndroidId() {
      return false;
      }
      /**
    • 是否允许SDK主动获取OAID
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetOAID() {
      return false;
      }
      /**
    • 是否允许SDK主动获取IP地址
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanGetIP() {
      return false;
      }
      });
      </code></pre></td>
      </tr>
      <tr>
      <td><b>应用安装列表信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />应用安装列表信息</td>
      <td>广告投放、反作弊</td>
      <td>在进行广告投放和广告统计分析时使用</td>
      <td>
      <pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许SDK主动收集上传应用列表
    • @return true 允许SDK收集,false 不允许
      */
      @Override
      public boolean isCanGetInstallAppList() {
      return super.isCanGetInstallAppList();
      }
      /**
    • 是否允许SDK主动收集上传后台运行的应用列表
    • @return true 允许SDK收集,false 不允许
      */
      @Override
      public boolean isCanGetRunningApps() {
      return super.isCanGetRunningApps();
      }
      });</code></pre>
      </td>
      </tr>
      <tr>
      <td><b>传感器信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />线性加速度传感器、磁场传感器、旋转矢量传感器、加速度传感器、陀螺仪传感器</td>
      <td>广告投放、广告反作弊</td>
      <td>在进行摇一摇、扭一扭等广告投放和广告反作弊分析时使用</td>
      <td>
      <pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许使用传感器
    • @return true 开启, false 关闭,默认值为true
      */
      @Override
      public boolean isCanUseSensor() {
      return super.isCanUseSensor();
      }
      });</code></pre>
      </td>
      </tr>
      <tr>
      <td><b>位置信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />精确位置信息、粗略位置信息</td>
      <td>广告投放、广告反作弊</td>
      <td>在进行广告投放和广告统计分析时使用</td>
      <td>
      <pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许SDK主动获取地理位置信息
    • @return true可以获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUseLocation() {
      return super.isCanUseLocation();
      }
      });</code></pre>
      </td>
      </tr>
      <tr>
      <td><b>运营商信息</b><br />第三方开发者可以选择是否授权本SDK收集如下信息:<br />运营商信息</td>
      <td>广告投放、广告反作弊</td>
      <td>在进行广告投放和广告统计分析时使用</td>
      <td><pre><code class="language-java">DCloudAdManager.init(this,config);
      // 初始化之后立即调用setPrivacyConfig方法
      DCloudAdManager.setPrivacyConfig(new DCloudAdManager.PrivacyConfig() {
      /**
    • 是否允许SDK主动获取手机设备信息,如:imei
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUseWifiState() {
      return super.isCanUseWifiState();
      }

    /**

    • 是否允许SDK主动获取手机运营商信息
    • @return true允许获取,false禁止获取。默认为true
      */
      @Override
      public boolean isCanUseSimOperator() {
      return super.isCanUseSimOperator();
      }
      });</code></pre>
      </td>
      </tr>
      </table>
  4. SDK 权限说明

    权限名称 功能 目的 申请时机
    android.permission.ACCESS_NETWORK_STATE<br/>android.permission.ACCESS_WIFI_STATE 获取网络信息 广告监测、统计分析 开发者在调用需要该权限的SDK功能且用户已授权相应权限时。
    android.permission.ACCESS_COARSE_LOCATION<br/>android.permission.ACCESS_FINE_LOCATION 获取位置信息 广告主归因及投放 开发者在调用需要该权限的SDK功能且用户已授权相应权限时。
    android.permission.READ_PHONE_STATE 获取手机设备标识等信息 广告监测、统计分析、广告主投放 开发者在调用需要该权限的SDK功能且用户已授权相应权限时。
  5. 应在应用设置页面等位置提供“个性化广告”关闭按钮。
    uni-AD原生广告SDK提供设置“个性化广告”开关的API

    是否开启个性化广告 false为关闭个性化推荐,默认为true  
    
    DCloudAdManager.setPersonalAd(Context context, boolean isOpen);  
  6. 应在向用户展示广告时,提供“关闭(X)”或“跳过”按钮,点击之后广告可以关闭。
    注意:展示广告时不得对“跳过”、“关闭”按钮进行遮挡。

APP合规指引

  1. 隐私弹窗
    应用在首次启动时需要弹窗提示,弹窗内容中需要包含隐私政策\服务条款链接。隐私政策弹框需要提供明确的拒绝按钮。

  2. 隐私政策

    • 隐私政策应该单独成文,不得与用户协议等说明文件的一部分存在。
    • 隐私政策中应清晰描述每个SDK的收集使用个人信息的目的、方式、范围及收集的个人信息类型及权限说明
    • 隐私政策应由最终用户自主选择是否同意,不应以默认勾选“同意”的方式取得用户授权。
    • 因业务需要,确需超出上述范围使用个人信息的,应再次征得用户明示同意。
  3. APP合规规范

    • 用户未同意隐私政策或者游客模式下,不得通过任何方式获取、传输用户隐私信息。
    • 隐私政策\服务条款应该有专门的链接公示。
    • 用户进入您的产品主功能界面后,通过4次以内的点击/滑动,能够访问到您的产品隐私政策。
    • 不应通过捆绑产品或服务各项业务功能的方式,要求用户一次性接受并授权同意其未申请或使用的业务功能收集个人信息的请求。
    • 用户明确表示不同意后,不得频繁征求用户同意、干扰用户正常使用。
    • 不得超范围获取用户信息。
    • APP不应收集与业务功能无任何关系的个人信息。
    • APP更新升级后,不应更改原有的系统权限设置。
  4. 最小必要数据收集
    在仅能收集最小必要的个人信息的情形下,仍能保证用户能使用APP的基本功能服务,可参考《常见类型移动互联网应用程序必要个人信息范围规定》

  5. 个性化退出机制。
    如果用户存在定向推送功能(个性化推荐,营销推送等功能),需要提供关闭定向推送功能的选项。

  6. 账号注销
    APP需要提供账户注销的途径,并在用户注销账号后,及时删除其个人信息或进行匿名化处理。

  7. 投诉管理
    APP应建立投诉管理机制和投诉跟踪流程,并在合理的时间内对投诉进行响应。

uni-AD原生广告集成的三方SDK说明

<table style="word-break:break-all">
<tr>
<th style="width:8%">SDK名称</th>
<th style="width:10%">SDK包名/网址</th>
<th style="width:8%">SDK用途</th>
<th style="width:20%">可能获取的个人信息类型</th>
<th style="width:25%">调用的设备权限</th>
<th style="width:20%">信息用途</th>
<th style="width:10%">SDK隐私政策链接/目的</th>
</tr>
<tr>
<td>快手 </td>
<td>com.kwad.sdk </td>
<td>增强广告 </td>
<td>基础信息:设备品牌、设备型号、软件系统版本、存储信息、运营商信息、设备时区、设备语言、网络信息等基础信息</br>
设备标识:IMEIs、MEID、OAID、AndroidID、IMSIs、ICCID</br>
位置信息:IP地址、MAC地址、GPS位置信息、基站信息、WIFI信息</br>
应用信息:应用安装列表</br>
其他信息:传感器信息、sim卡激活信息</td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.INTERNET <br>
android.permission.READ_PHONE_STATE <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.VIBRATE
</td>
<td>广告投放、广告归因、反作弊、安全 </td>
<td><a href="https://www.kuaishou.com/about/policy" target="_blank">快手内容联盟隐私协议</a>和<a href="https://u.kuaishou.com/home/detail/1220" target="_blank">SDK使用规范</a></td>
</tr>
<tr>
<td>快手内容联盟 </td>
<td>com.kwad.sdk </td>
<td>增强广告 </td>
<td>基础信息:设备品牌、设备型号、软件系统版本、存储信息、运营商信息、设备时区、设备语言、网络信息等基础信息</br>
设备标识:IMEIs、MEID、OAID、AndroidID、IMSIs、ICCID</br>
位置信息:IP地址、MAC地址、GPS位置信息、基站信息、WIFI信息</br>
应用信息:应用安装列表</br>
其他信息:传感器信息、sim卡激活信息 </td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.INTERNET <br>
android.permission.READ_PHONE_STATE <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.VIBRATE <br>
android.permission.SET_WALLPAPER<br>
android.permission.READ_EXTERNAL_STORAGE <br>
android.permission.WRITE_EXTERNAL_STORAGE <br>
android.permission.ACCESS_COARSE_LOCATION <br>
android.permission.BLUETOOTH
</td>
<td>广告投放、广告归因、反作弊、安全 </td>
<td><a href="https://www.kuaishou.com/about/policy" target="_blank">快手内容联盟隐私协议</a>和<a href="https://u.kuaishou.com/home/detail/1220" target="_blank">SDK使用规范</a></td>
</tr>
<tr>
<td>优量汇 </td>
<td>com.qq.e<br/>com.android.gdt.qone </td>
<td>增强广告 </td>
<td>基站、附近的WIFI、连接的WIFI、位置信息、设备制造商、设备型号、操作系统版本、屏幕分辨率、屏幕方向、屏幕DPI、IP地址、加速度传感器、磁场传感器、OAID、IMEI/MEID(Device ID)、Android_ID、包名、版本号、进程名称、运行状态、可疑行为、应用安装信息 </td>
<td style="font-size:12px">
android.permission.INTERNET <br>
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.CHANGE_NETWORK_STATE<br>
android.permission.QUERY_ALL_PACKAGES <br>
android.permission.REORDER_TASKS<br>
android.permission.VIBRATE <br>
android.permission.ACCESS_COARSE_LOCATION
</td>
<td style="font-size:12px">广告投放与监测归因、广告主统计投放结果、减少App崩溃、确保服务器正常运行、提升可扩展性和性能</td>
<td><a href="https://e.qq.com/dev/help_detail.html?cid=2005&pid=5983" target="_blank">优量汇隐私协议</a></td>
</tr>
<tr>
<td>穿山甲 </td>
<td>com.bytedance.sdk.openadsdk</td>
<td>增强广告 </td>
<td>设备品牌、型号、软件系统版本、分辨率、网络信号强度、IP地址、设备语言、传感器信息等基础信息、无线网SSID名称、MAC地址、AndroidID、应用名、应用包名、版本号、应用前后台状态、应用列表信息、运营商信息、设备时区 </td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE <br>
android.permission.READ_PHONE_STATE <br>
android.permission.WRITE_EXTERNAL_STORAGE
</td>
<td>广告投放合作、广告归因、反作弊 </td>
<td><a href="https://www.pangle.cn/privacy/partner" target="_blank">穿山甲隐私协议</a></td>
</tr>
<tr>
<td>Sigmob </td>
<td>com.sigmob.windad </td>
<td>增强广告 </td>
<td>设备信息:设备品牌、型号、操作系统版本、OAID、分辨率等基础设备信息
应用信息:应用名称、应用包名、应用版本号等
其他:运营商信息、时区</td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.INTERNET <br>
android.permission.ACCESS_WIFI_STATE <br>
android.permission.CHANGE_WIFI_STATE <br>
android.permission.READ_PHONE_STATE <br>
android.permission.REQUEST_INSTALL_PACKAGES <br>
android.permission.QUERY_ALL_PACKAGES
</td>
<td>广告投放、广告主归因、反作弊 </td>
<td><a href="https://doc.sigmob.com/#/Sigmob%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/%E9%9A%90%E7%A7%81%E6%9D%A1%E6%AC%BE/%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96/">Sigmob隐私协议</a></td>
</tr>
<tr>
<td>百度百青藤</td>
<td>com.baidu.mobads.proxy </td>
<td>增强广告 </td>
<td>设备信息:设备品牌、型号、软件系统版本、分辨率、网络信号强度、传感器信息,磁盘总空间、系统总内存空间、手机重启信息、手机系统更新时间等基础信息、OAID、AndroidID、屏幕宽高,屏幕像素密度,系统版本号,设备厂商,设备型号,手机运营商,手机网络状态,设备剩余存储空间,手机重启时间和更新时间
开发者应用信息:应用包名、应用前后台状态
设备信息:IMEI、IMSI、MEID
位置信息</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.READ_PHONE_STATE<br>
android.permission.ACCESS_COARSE_LOCATION<br>
android.permissio.WRITE_EXTERNAL_STORAGE<br>
</td>
<td>为最终用户提供安全保障、改善我们的产品和服务,开展内部审计、数据分析和研究 </td>
<td><a href="https://union.baidu.com/bqt/#/legal/policies">百度百青藤隐私协议</a></td>
</tr>

<tr>
<td>HUAWEI Ads</td>
<td>com.huawei.hms.ads.lite</td>
<td>增强广告 </td>
<td>设备及使用信息:设备标识符(OAID)、设备信息(设备型号、设备硬件信息、操作系统、系统设置、设备使用信息)、应用基本信息、应用设置信息、应用使用信息、传感器信息(陀螺仪、加速度计、旋转矢量传感器、磁力计、气压计)、网络信息、运营商信息、IP地址、WLAN信息(WiFi状态、WiFi参数、WiFi列表、BSSID与SSID)。广告互动信息:
您与本服务投放的广告之间的交互行为,如曝光、点击、内容交互等信息。。广告主服务互动信息:
基于广告投放优化、广告归因和效果分析等目的,广告主可能会向我们提供其与用户交互时获得的转化记录。</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.ACCESS_COARSE_LOCATION<br>
android.permission.ACCESS_FINE_LOCATION<br>
</td>
<td>单次请求的广告定向投放、程序化广告投放、广告监测归因与反作弊。</td>
<td><a href="https://developer.huawei.com/consumer/cn/doc/HMSCore-Guides/whale-hong-kinetic-energy-sdk-privacy-statement-0000001658283582">HUAWEI Ads 隐私声明</a><br><br>和<br><br><a href="https://legal.cloud.huawei.com/terms/scope/huawei/ads/privacy-statement.htm?&code=CN&language=zh-CN&branchid=0&contenttag=default">HUAWEI Ads SDK隐私安全说明</a></td>
</tr>
<tr>
<td>章鱼广告(Octopus SDK)</td>
<td>com.octopus.ad</td>
<td>增强广告 </td>
<td>设备信息:必选信息:设备品牌、型号、软件系统版本、屏幕密度、屏幕分辨率、设备语言、设备时区、CPU信息、可用存储空间大小等基础信息、AndroidID、OAID;可选信息:设备标识符(如OAID、GAID(仅GMS服务)。网络信息(必选):运营商信息、Wi-Fi状态、网络信号强度、IP地址。应用信息(必选):应用包名、运行中的进程信息、版本号。传感器信息(可选):线性加速度传感器、磁场传感器、旋转矢量传感器、加速度传感器、陀螺仪传感器。广告信息(必选):对广告的展示、点击及转化等交互数据。性能数据(必选):崩溃数据、性能数据</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.WRITE_EXTERNAL_STORAGE<br>
android.permission.READ_EXTERNAL_STORAGE<br>
</td>
<td>基于用户设备信息调整广告投放、统计分析、反作弊、实现广告正常显示与交互功能,通过崩溃信息,以此来优化代码缺陷,最大程度减少App崩溃。通过收集SDK运行过程中性能数据,以优化SDK的性能。统计广告数据,以用于广告主统计投放结果。</td>
<td><a href="https://doc.adintl.cn/#/zh-cn/guide/UsePrivacy">章鱼广告SDK隐私政策</a></td>
</tr>

<tr>
<td>倍孜广告(AdScope SDK)</td>
<td>com.beizi.ad<br/>ms.bz.bd.c</td>
<td>增强广告 </td>
<td>设备信息(必选):设备品牌、设备型号、设备时区、设备语言、系统版本、UserAgent信息、屏幕高宽、屏幕方向、屏幕DPI信息、系统更新时间、磁盘空间、物理内存、sim卡状态、cpu。网络信息(必选):网络类型、运营商。应用信息(必选):开发者应用名、应用版本号、应用包名、运行状态。标识符(必选):OAID。位置信息(可选):精确位置信息、粗略位置信息。传感器信息(可选):重力传感器、加速度传感器、方向传感器、陀螺仪、压力传感器、线性加速度传感器。广告信息(必选):产品交互数据、广告数据(展示、点击、转化)。诊断数据(必选):崩溃数据、性能数据</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.WRITE_EXTERNAL_STORAGE<br>
android.permission.READ_EXTERNAL_STORAGE<br>
</td>
<td>广告投放策略、统计分析服务、反作弊分析、广告正常显示与交互功能的实现、广告归因、最大程度减少App崩溃、确保服务器正常运行、提升可扩展性和性能</td>
<td><a href="https://sdkdoc.beizi.biz/#/zh-cn/guide/UsePrivacy">BeiZi SDK隐私保护声明</a></td>
</tr>

<tr>
<td>泛连</td>
<td>com.fl.saas.s2s<br/>com.fl.saas</td>
<td>增强广告 </td>
<td>设备信息:必选信息:设备品牌、设备型号、设备名称、软件系统版本、屏幕密度、屏幕分辨率、设备语言、设备时区、手机系统重启时间;可选信息:IMEI、IMSI、设备的MAC地址、User Agent、AndroidID。标识符:可选信息:设备ID(国内用户OAID、海外用户GAID)。网络信息:必选信息:IP地址、运营商信息、Wi-Fi状态、网络信号强度。应用信息:必选信息:应用版本、应用包名、应用名称、应用前后台状态。可选信息:应用列表信息。传感器信息:可选信息:重力传感器、加速度传感器、方向传感器、陀螺仪、压力传感器、重力传感器、线性加速度传感器。广告信息:必选信息:当用户与我们在您应用上推广的广告发生了交互行为,我们会手机广告的展示、点击及转化等交互数据。位置信息::粗略位置信息(WI-FI列表、WALAN接入点(如SSID、BSSID))、基站。其他信息:必选信息:系统崩溃数据、性能数据
</td>
<td style="font-size:12px">
android.permission.INTERNET<br>
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.VIBRATE<br>
android.permission.REQUEST_INSTALL_PACKAGES<br>
android.permission.READ_PHONE_STATE<br/>
</td>
<td>广告投放及广告监测归因、反作弊、摇一摇广告投放、广告投放统计分析、提升SDK的稳定性,减少APP的崩溃</td>
<td><a href="https://www.adfunlink.com/doc/privacy.html">Funlink隐私保护声明</a></td>
</tr>
<tr>
<td>华夏乐游(优推广告)</td>
<td>com.alliance.ssp.ad</td>
<td>增强广告</td>
<td>设备信息:
必选信息:设备品牌、型号、软件系统版本、屏幕密度、屏幕分辨率、设备语言、设备时区等基础信息 【仅iOS】磁盘总空间、系统总内存空间;
可选信息:设备MAC地址、设备标识符(如IMEI、MEID,具体字段因软硬件版本不同而存在差异)如AndroidID、OAID、IMSI、IMEI、MEID 等。网络信息:
必选信息:运营商信息、网络状态(包括BSSID、SSID 等)、IP地址。应用信息 :必选信息:应用包名、版本号;可选信息:应用安装列表信息。传感器信息:必选信息:加速度传感器。广告信息:
必选信息:对广告的填充、展示、点击及转化等交互数据。位置信息:
可选信息:精确位置信息。性能数据:
必选信息:如崩溃数据、性能数据</td>
<td style="font-size:12px">
android.permission.ACCESS_NETWORK_STATE<br>
android.permission.INTERNET<br>
android.permission.READ_PHONE_STATE<br>
android.permission.ACCESS_WIFI_STATE<br>
android.permission.REQUEST_INSTALL_PACKAGES<br>
android.permission.ACCESS_FINE_LOCATION<br>
android.permission.ACCESS_COARSE_LOCATION<br>
android.permission.READ_EXTERNAL_STORAGE<br>
android.permission.WRITE_EXTERNAL_STORAGE<br>
android.permission.QUERY_ALL_PACKAGES<br>
</td>
<td>广告投放及广告反作弊。广告监测归因。保证网络服务有效性及稳定性。摇一摇、扭一扭功能。减少App崩溃、提供稳定可靠的服务</td>
<td><a href="https://lemon.gameley.com/flowdocs/%E4%BC%98%E6%8E%A8%E5%B9%BF%E5%91%8A%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE/%E4%BC%98%E6%8E%A8%E5%B9%BF%E5%91%8A%E5%B9%B3%E5%8F%B0SDK%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96.html">优推广告平台 SDK 隐私政策</a></td>
</tr>
<tr>
<td>微信开放平台</td>
<td>com.tencent.mm</td>
<td>快捷广告</td>
<td>网络信息、设备信息</td>
<td style="font-size:12px">
</td>
<td>打开小程序</td>
<td><a href="https://support.weixin.qq.com/cgi-bin/mmsupportacctnodeweb-bin/pages/RYiYJkLOrQwu0nb8">https://support.weixin.qq.com/cgi-bin/mmsupportacctnodeweb-bin/pages/RYiYJkLOrQwu0nb8</a></td>
</tr>
<tr>
<td>图灵盾风险识别SDK</td>
<td></td>
<td>腾讯优量汇必需功能</td>
<td>硬件序列号、网络状态、系统设置、系统属性、设备型号、操作系统、IP地址、运营商信息、标识符如OAID、IDFA、IDFV等
由第三方开发者根据实际情况决定是否采集并传输给SDK,SDK采取去标识、加密等方式进行处理</td>
<td style="font-size:12px">
</td>
<td>广告推荐、归因及反作弊场景统计,如虚假流量识别等。</td>
<td><a href="https://privacy.qq.com/document/preview/5331f064a91a47eb93993fdacb91c8f7">https://privacy.qq.com/document/preview/5331f064a91a47eb93993fdacb91c8f7</a></td>
</tr>

<tr>
<td>Qone SDK</td>
<td></td>
<td>腾讯优量汇必需功能</td>
<td>IP地址、设备型号、设备标识信息(OAID、Android ID、IDFA、IDFV等)</td>
<td style="font-size:12px">
</td>
<td>广告归因,识别黑产和虚假设备</td>
<td><a href="https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157">https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157</a></td>
</tr>
<tr>
<td>MSA移动安全联盟</td>
<td></td>
<td>获取OAID(可选)</td>
<td>品牌信息:设备制造商、设备型号、设备品牌。网络信息:设备网络运营商名称。应用软件信息:App包名及签名信息,或在对应应用商店的APPID。</td>
<td style="font-size:12px">
</td>
<td>判断终端品牌,调用接口。判断是否为虚拟机环境。生成VAID时判断是否为同一开发者。</td>
<td><a href="https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157">https://privacy.qq.com/document/preview/1a3015ecc0f240ebad548012fc64b157</a></td>
</tr>
</table>

收起阅读 »

H5 路由切换没有动画效果

h5

H5 路由切换没有动画效果这个问题怎么办啊,为什么app就支持H5就不支持嘞。。。。。。。不理解,官方什么时候解决一下,插件市场那些不好用有bug

H5 路由切换没有动画效果这个问题怎么办啊,为什么app就支持H5就不支持嘞。。。。。。。不理解,官方什么时候解决一下,插件市场那些不好用有bug