UniApp获取安卓系统权限教程

本教程将详细介绍在UniApp中开发安卓APP时,如何正确配置和动态申请系统权限,涵盖权限声明、运行时申请、状态处理等完整流程。

一、权限配置基础

1.1 在manifest.json中声明权限

在项目根目录的manifest.json文件中配置所需权限。有两种配置方式:

​​方式一:可视化配置(推荐)​ ​

打开HBuilderX,在manifest.json编辑界面切换到"App权限配置" -> "Android权限配置",勾选需要的权限项。

​​方式二:代码视图配置​ ​

在manifest.json的代码视图中添加:

复制代码
{
  "app-plus": {
    "distribute": {
      "android": {
        "permissions": [
          "android.permission.CAMERA",
          "android.permission.ACCESS_FINE_LOCATION",
          "android.permission.WRITE_EXTERNAL_STORAGE"
        ]
      }
    }
  }
}

1.2 常用安卓权限列表

权限名称 说明 权限常量
相机权限 访问摄像头拍照 android.permission.CAMERA
存储权限 读写外部存储 android.permission.WRITE_EXTERNAL_STORAGE
定位权限 获取精确位置 android.permission.ACCESS_FINE_LOCATION
麦克风权限 录音 android.permission.RECORD_AUDIO
电话权限 拨打电话 android.permission.CALL_PHONE
联系人权限 读取联系人 android.permission.READ_CONTACTS

二、动态权限申请

Android 6.0+系统要求运行时动态申请敏感权限。UniApp通过plus.android.requestPermissionsAPI实现。

2.1 基本申请方法

复制代码
// 单个权限申请示例
plus.android.requestPermissions(
  ['android.permission.CAMERA'],
  function(resultObj) {
    // 权限申请结果回调
    console.log('权限申请结果:', resultObj);
    
    if (resultObj.granted.length > 0) {
      // 权限已授予
      console.log('相机权限已获取');
    } else if (resultObj.deniedPresent.length > 0) {
      // 本次拒绝
      console.log('用户本次拒绝授权');
    } else if (resultObj.deniedAlways.length > 0) {
      // 永久拒绝
      console.log('用户永久拒绝授权');
    }
  },
  function(error) {
    // 申请出错
    console.error('权限申请出错:', error);
  }
);

2.2 多个权限同时申请

复制代码
// 同时申请多个权限
const permissions = [
  'android.permission.CAMERA',
  'android.permission.WRITE_EXTERNAL_STORAGE'
];

plus.android.requestPermissions(
  permissions,
  function(resultObj) {
    // 处理多个权限结果
    console.log('已授权:', resultObj.granted);
    console.log('本次拒绝:', resultObj.deniedPresent);
    console.log('永久拒绝:', resultObj.deniedAlways);
  }
);

三、权限状态处理

3.1 检查权限状态

在申请权限前,可以先检查当前权限状态:

复制代码
// 检查权限是否已授予(仅适用于部分权限)
uni.getSetting({
  success(res) {
    if (res.authSetting['scope.camera']) {
      console.log('相机权限已开启');
    } else {
      // 需要申请权限
      requestCameraPermission();
    }
  }
});

3.2 处理用户拒绝场景

当用户拒绝权限时,需要提供友好的引导:

复制代码
function handlePermissionResult(resultObj) {
  if (resultObj.deniedAlways.length > 0) {
    // 用户勾选了"不再询问",需要引导到设置页
    uni.showModal({
      title: '权限提示',
      content: '您已永久拒绝该权限,请前往设置手动开启',
      success(res) {
        if (res.confirm) {
          // 跳转到应用设置页
          openAppSettings();
        }
      }
    });
  } else if (resultObj.deniedPresent.length > 0) {
    // 本次拒绝,可以稍后再次尝试
    uni.showToast({
      title: '权限未获取,部分功能无法使用',
      icon: 'none'
    });
  }
}

四、跳转到系统设置页

当用户永久拒绝权限时,需要引导用户到系统设置页手动开启:

复制代码
// 跳转到应用权限设置页
function openAppSettings() {
  if (plus.os.name === 'Android') {
    const Intent = plus.android.importClass('android.content.Intent');
    const Settings = plus.android.importClass('android.provider.Settings');
    const Uri = plus.android.importClass('android.net.Uri');
    
    const mainActivity = plus.android.runtimeMainActivity();
    const intent = new Intent();
    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    const uri = Uri.fromParts('package', mainActivity.getPackageName(), null);
    intent.setData(uri);
    mainActivity.startActivity(intent);
  }
}

五、完整示例代码

5.1 相机权限申请完整示例

复制代码
// 封装相机权限申请函数
export function requestCameraPermission() {
  return new Promise((resolve, reject) => {
    // 先检查是否已授权
    uni.getSetting({
      success(res) {
        if (res.authSetting['scope.camera']) {
          resolve(true);
          return;
        }
        
        // 向用户解释权限用途
        uni.showModal({
          title: '权限申请',
          content: '我们需要访问您的相机以使用拍照功能',
          success(modalRes) {
            if (modalRes.confirm) {
              // 发起权限申请
              plus.android.requestPermissions(
                ['android.permission.CAMERA'],
                function(resultObj) {
                  if (resultObj.granted.length > 0) {
                    resolve(true);
                  } else if (resultObj.deniedAlways.length > 0) {
                    // 永久拒绝,引导到设置页
                    uni.showModal({
                      title: '提示',
                      content: '请前往设置开启相机权限',
                      success(settingRes) {
                        if (settingRes.confirm) {
                          openAppSettings();
                        }
                        resolve(false);
                      }
                    });
                  } else {
                    resolve(false);
                  }
                },
                function(error) {
                  console.error('权限申请错误:', error);
                  reject(error);
                }
              );
            } else {
              resolve(false);
            }
          }
        });
      }
    });
  });
}

// 使用示例
async function takePhoto() {
  const hasPermission = await requestCameraPermission();
  if (hasPermission) {
    // 执行拍照操作
    uni.chooseImage({
      count: 1,
      success(res) {
        console.log('拍照成功:', res.tempFilePaths[0]);
      }
    });
  }
}

5.2 定位权限申请示例

复制代码
// 定位权限申请
function requestLocationPermission() {
  const permissions = [
    'android.permission.ACCESS_FINE_LOCATION',
    'android.permission.ACCESS_COARSE_LOCATION'
  ];
  
  plus.android.requestPermissions(
    permissions,
    function(resultObj) {
      if (resultObj.granted.length > 0) {
        // 获取定位
        uni.getLocation({
          type: 'wgs84',
          success(res) {
            console.log('定位成功:', res);
          }
        });
      } else {
        uni.showToast({
          title: '定位权限未获取',
          icon: 'none'
        });
      }
    }
  );
}

六、常见问题与解决方案

6.1 权限弹窗不显示

  • ​​原因1​​:manifest.json中未正确配置权限

  • ​​解决​​:检查manifest.json权限配置,确保权限名称正确

  • ​​原因2​​:在非主线程调用权限申请

  • ​​解决​​:确保在页面生命周期(如onLoad、onShow)或用户交互事件中调用

6.2 权限申请回调不执行

  • ​原因​:Android系统限制,用户点击"拒绝"后短时间内不会再次弹窗
  • ​解决​:添加合理的重试机制,或引导用户到设置页

6.3 应用市场审核被拒

  • ​原因​:权限使用说明不充分
  • ​解决​:在权限申请前向用户清晰说明权限用途,并在隐私政策中说明数据使用方式

七、最佳实践建议

  1. ​按需申请​:在真正需要使用功能时才申请权限,不要一次性申请所有权限
  2. ​用户引导​:申请权限前向用户解释为什么需要该权限,提升用户体验
  3. ​错误处理​:对权限拒绝、永久拒绝等不同状态做差异化处理
  4. ​测试覆盖​:在不同Android版本、不同厂商ROM上测试权限申请流程
  5. ​隐私合规​:确保符合应用市场审核要求,在隐私政策中说明权限使用目的

八、总结

UniApp开发安卓APP的权限管理涉及manifest配置、运行时申请、状态处理等多个环节。通过plus.android.requestPermissionsAPI可以方便地实现动态权限申请,但需要注意不同Android版本的兼容性、用户引导、错误处理等细节。建议将权限申请逻辑封装成工具函数,提高代码复用性和可维护性。

在实际开发中,建议参考官方文档和最新API,因为不同HBuilderX版本可能会有细微差异。同时,关注各大应用市场的审核要求,确保权限使用符合规范。


​​注意​​:本教程基于UniApp官方文档和常见开发实践编写,具体实现时请根据实际项目需求和HBuilderX版本进行调整。建议在真机上进行充分测试,确保权限申请流程正常工作。

相关推荐
千里马学框架5 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台5 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone5 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc5 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo5 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077005 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼5 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
码兄科技5 天前
24小时自助健身房系统软件开发实战指南:功能设计与部署方案
java·spring boot·uni-app
AFinalStone5 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen5 天前
属性动画原理与高级动画实现
android·kotlin·canvas