关于android:使用APICloud开发app的动态权限及Android平台targetSdkVersion设置教程

24次阅读

共计 7138 个字符,预计需要花费 18 分钟才能阅读完成。

先介绍一下对于 Android 动静权限和 targetSdkVersion 背景:

targetSdkVersion:自 2018 年 11 月开始,GooglePlay 以及国内大部分利用市场要求 app 编译指标 SDK 必须为 26 及以上,否则不予提交审核;有许多已有 app 转到 APICloud 开发后,因 targetSdkVersion 降级而导致无奈笼罩装置;2020 年以来,国家网信办等监管机构也增强了对 app 权限合规的监管。

动静权限:Android 自零碎 6.0 开始,提供动静权限机制,对于敏感权限(存储,定位,录音,拍照,录像等),须要在 app 运行过程中动静向用户申请,这就和 iOS 零碎的权限应用体验保持一致了(iOS 始终以来就是动静权限)。

应用 APICloud 开发平台开发 app 时,如果须要获取权限,须要动静申请。因而 APICloud 开发平台对立了 Android 和 iOS 两个平台的动静权限操作,提供两个 API:hasPermission 和 requestPermission。文档地址为:https://docs.apicloud.com/Cli…

在 Android 上应用动静权限,要求 app 编译的指标 SDK(即 targetSdkVersion)为 23 及以上(对应为 android6.0 及以上零碎),22 及以下零碎会执行缺省解决(手机厂商也可能定制解决),APICloud 为满足更广泛的开发需要,默认配置 targetSdkVersion 为 22,即权限走零碎缺省解决。

开启动静权限,须要依照以下阐明操作:

1、新建 manifest.xml 文件,增加如下代码:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
    <application name="targetSdkVersion" value="28"/>
</manifest>

将其中的 targetSdkVersion 更新为目标值,例如 30;
2、将 manifest.xml 置于你的 / 我的项目代码 /res/ 目录下(widget/res/manifest.xml);
3、将你的 app 代码中所有波及到须要动静权限的操作,参照示例中的代码,革新一遍(例如进行拍照录制视频等须要应用摄像头,以前的缺省解决中不须要申请摄像头权限,而开启动静权限后,必须在进行拍照之前,判断是否有摄像头权限,没有则进行申请,只有用户批准了摄像头权限能力进行接下来拍照的操作);
4、提交代码;
5、云编译界面勾选 app 所需的权限;
6、云编译 app 或自定义 loader 即可。

在这里须要留神的是,当你设置的 targetSdkVersion 大于等于 23 时,即意味着开启了动静权限,如果你的 app 带有获取 IMEI、定位、录音、拍照、录像等敏感性能时,必须应用动静权限机制,先判断是否具备该性能操作权限,再进行操作,如果不具备相应的权限,对应的性能是生效的,也可能导致 app 解体。

为保障动静权限尽可能适配更多厂商的手机以及顺利上线 Google Play,targetSdkVersion 目前举荐设置为 30。

以下为代码示例:

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="maximum-scale=1.0, minimum-scale=1.0, user-scalable=0, initial-scale=1.0, width=device-width" />
    <meta name="format-detection" content="telephone=no, email=no, date=no, address=no">
    <title> 权限治理 </title>
    <link rel="stylesheet" type="text/css" href="./css/api.css" />
    <link rel="stylesheet" type="text/css" href="./css/box.css" />
    <script type="text/javascript" src="./script/public.js"></script>
    <style>
        .marg {
            margin: 3px 15px;
            font-size: 18px;
        }
    </style>
    <script type="text/javascript">

        apiready = function () {}

        function hasPermission(one_per) {var perms = new Array();
            if (one_per) {perms.push(one_per);
            } else {var prs = document.getElementsByName("p_list");
                for (var i = 0; i < prs.length; i++) {if (prs[i].checked) {perms.push(prs[i].value);
                    }
                }
            }
            var rets = api.hasPermission({list: perms});
            if (!one_per) {apialert('判断后果:' + JSON.stringify(rets));
                return;
            }
            return rets;
        }

        function reqPermission(one_per, callback) {var perms = new Array();
            if (one_per) {perms.push(one_per);
            } else {var prs = document.getElementsByName("p_list_r");
                for (var i = 0; i < prs.length; i++) {if (prs[i].checked) {perms.push(prs[i].value);
                    }
                }
            }
            api.requestPermission({
                list: perms,
                code: 100001
            }, function (ret, err) {if (callback) {callback(ret);
                    return;
                }
                var str = '申请后果:\n';
                str += '申请码:' + ret.code + '\n';
                str += "是否勾选 \" 不再询问 \"按钮:" + (ret.never ? '是' : '否') + '\n';
                str += '申请后果: \n';
                var list = ret.list;
                for (var i in list) {str += list[i].name + '=' + list[i].granted + '\n';
                }
                apialert(str);
                console.log(JSON.stringify(ret));
            });
        }

        function opWithPermission(perm) {if (!confirmPer(perm)) {return;}
            if ('calendar' == perm) {// 操作日历} else if ('camera' == perm) {
                api.getPicture({
                    sourceType: 'camera',
                    mediaValue: 'pic',
                    destinationType: 'url',
                }, function (ret, err) {if (ret) {apialert(JSON.stringify(ret));
                    } else {apialert(JSON.stringify(err));
                    }
                });
            } else if ('contacts' == perm) {
                api.openContacts({test: true}, function (ret, err) {if (ret && ret.status) {apialert(JSON.stringify(ret));
                    } else {apialert(JSON.stringify(err));
                    }
                });
            } else if ('location' == perm) {api.getLocation(function (ret, err) {if (ret && ret.status) {apialert(JSON.stringify(ret));
                    } else {apialert(JSON.stringify(err));
                    }
                });
            } else if ('microphone' == perm) {
                api.startRecord({path: 'fs://perm-test.amr'});
            } else if ('phone' == perm) {
                api.call({
                    type: 'tel',
                    number: '10086'
                });
            } else if ('sensor' == perm) {// 操作身材传感器} else if ('sms' == perm) {
                api.sms({numbers: ['10086'],
                    text: '余额',
                    silent: true
                });
            } else if ('storage' == perm) {
                api.readFile({path: 'fs://test.txt'}, function (ret, err) {if (ret.status) {console.log('readFile:' + ret.data);
                    } else {apialert(err.msg + ": \n" + api.fsDir);
                    }
                });
            }
        }

        function confirmPer(perm) {var has = hasPermission(perm);
            if (!has || !has[0] || !has[0].granted) {
                api.confirm({
                    title: '揭示',
                    msg: '没有取得' + perm + "权限 \n 是否返回设置?",
                    buttons: ['去设置', '勾销']
                }, function (ret, err) {if (1 == ret.buttonIndex) {reqPermission(perm);
                    }
                });
                return false;
            }
            return true;
        }

    </script>
</head>

<body>
    <div>
        <div id="wrap">
            <div id='header'>
                <div class="back" tapmode="back-aconclick="api.closeWin()"> 返回 </div>
                <h1> 权限治理测试 </h1>
                <div class="adpt"></div>
            </div>
            <div class='itemtitle'> 一、判断权限 </div>
            <div class='marg'> 请抉择一个或者多个权限进行判断:</div>
            <div class='marg'> 日历 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list" value="calendar" /></div>
            <div class='marg'> 相机 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list" value="camera" /></div>
            <div class='marg'> 通讯录 &emsp;&emsp;<input type="checkbox" name="p_list" value="contacts" /></div>
            <div class='marg'> 地位信息 &emsp;<input type="checkbox" name="p_list" value="location" /></div>
            <div class='marg'> 麦克风 &emsp;&emsp;<input type="checkbox" name="p_list" value="microphone" /></div>
            <div class='marg'> 电话 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list" value="phone" /></div>
            <div class='marg'> 身材传感器 <input type="checkbox" name="p_list" value="sensor" /></div>
            <div class='marg'> 短信 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list" value="sms" /></div>
            <div class='marg'> 存储空间 &emsp;<input type="checkbox" name="p_list" value="storage" /></div>
            <div class="clickbtn" tapmode="active" onclick="hasPermission()"> 点击开始判断 </div>
            <div class='itemtitle'> 二、申请权限 </div>
            <div class='marg'> 请抉择一个或者多个权限进行申请:</div>
            <div class='marg'> 日历 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list_r" value="calendar" /></div>
            <div class='marg'> 相机 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list_r" value="camera" /></div>
            <div class='marg'> 通讯录 &emsp;&emsp;<input type="checkbox" name="p_list_r" value="contacts" /></div>
            <div class='marg'> 地位信息 &emsp;<input type="checkbox" name="p_list_r" value="location" /></div>
            <div class='marg'> 麦克风 &emsp;&emsp;<input type="checkbox" name="p_list_r" value="microphone" /></div>
            <div class='marg'> 电话 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list_r" value="phone" /></div>
            <div class='marg'> 身材传感器 <input type="checkbox" name="p_list_r" value="sensor" /></div>
            <div class='marg'> 短信 &emsp;&emsp;&emsp;<input type="checkbox" name="p_list_r" value="sms" /></div>
            <div class='marg'> 存储空间 &emsp;<input type="checkbox" name="p_list_r" value="storage" /></div>
            <div class="clickbtn" tapmode="active" onclick="reqPermission()"> 点击开始申请 </div>
            <div class='itemtitle'> 三、须要权限的 API 操作 </div>
            <div class='marg'>1、日历 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('calendar')"> 点击操作日历 </div>
            <div class='marg'>2、相机 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('camera')"> 点击操作照相机 </div>
            <div class='marg'>3、通讯录 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('contacts')"> 点击操作通讯录 </div>
            <div class='marg'>4、地位信息 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('location')"> 点击操作地位信息 </div>
            <div class='marg'>5、麦克风 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('microphone')"> 点击操作麦克风 </div>
            <div class='marg'>6、电话 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('phone')"> 点击操作电话 </div>
            <div class='marg'>7、身材传感器 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('sensor')"> 点击操作身材传感器 </div>
            <div class='marg'>8、短信 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('sms')"> 点击操作短信 </div>
            <div class='marg'>9、存储空间 </div>
            <div class="clickbtn" tapmode="active" onclick="opWithPermission('storage')"> 点击操作存储空间 </div>
            <br>
        </div>
    </div>
</body>

</html>

正文完
 0