【Java】Android动态权限相关问题梳理

Unity安卓相机相册权限全版本适配:从运行时权限到作用域存储实战 在移动应用开发中,运行时权限管理是保障用户隐私与功能实现的核心机制。其原理在于系统将敏感权限(如相机、存储)的授予时机从安装时推迟到应用运行时,由用户动态控制。这一机制的技术价值在于平衡了应用功能需求与用户数据安全,是构建可信应用的基础。随着安卓系统迭代,权限模型持续演进,尤其在访问外部存储时,安卓11引入的作用域存储(Scoped Storage)规范,进一步收紧了文件访问范围,要求应用通过系统选择器或MediaStore API访问媒体文件,这直接影响了相机拍照与相册选图等常见场景的实现。对于使用Uni 阅读详情

本篇文章主要讲解

1、申请权限为什么需要额外引入appcomat包(或者权限框架)?可以不引入吗?哪些情况可以不用引入?

2、不引入appcompat包的情况下,如何检查是否授权呢?

3、动态权限处理代码参考示例

4、敏感权限组清单及错误理解

5、shouldShowRequestPermissionRationale方法真正含义

6、选择照片和拍照一定要相机权限吗?

Android 6.0开始,对敏感权限需要动态申请,首先我们需要引入android.support.v4兼容包(或appcompat兼容包),然后使用support包中ActivityCompat这个类来处理权限。其实Activity自身也可以处理动态权限,不需要额外引入ActivityCompat。

使用ActivityCompat处理权限需要用到的方法:

ActivityCompat.checkSelfPermission(...)
ActivityCompat.requestPermissions(...)
ActivityCompat.shouldShowRequestPermissionRationale(...)

第一个是检查某个权限是否授权
第二个是申请权限
第三个是判断是否需要合理显示授权对话框。具体含义和用法文末会详解。

Activity自身也可以处理动态权限,也有这些方法,为什么要使用ActivityCompat来处理动态权限?

这也就是为什么要引入兼容包的原因。

第一,如果应用的minSdkVersion小于23(我们一般会设置成15或16左右),直接使用Activity来处理动态权限,那么IDE会提示你这些方法在6.0以下不存在,编译会不通过。

第二,ActivityCompat做了一些兼容性判断,比如requestPermissions的实现里加了判断api 23,在23以下的机器方法不做处理,不弹出对话框。onRequestPermissionsResult回调在23以下是没有的,除非Activity实现了OnRequestPermissionsResultCallback接口。

看看ActivityCompat.requestPermissions函数的源码就明白了:

  public static void requestPermissions(final @NonNull Activity activity,
            final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) {
        if (sDelegate != null
                && sDelegate.requestPermissions(activity, permissions, requestCode)) {
            // Delegate has handled the permission request.
            return;
        }

        if (Build.VERSION.SDK_INT >= 23) {
            if (activity instanceof RequestPermissionsRequestCodeValidator) {
                ((RequestPermissionsRequestCodeValidator) activity)
                        .validateRequestPermissionsRequestCode(requestCode);
            }
            activity.requestPermissions(permissions, requestCode);
        } else if (activity instanceof OnRequestPermissionsResultCallback) {
            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    final int[] grantResults = new int[permissions.length];

                    PackageManager packageManager = activity.getPackageManager();
                    String packageName = activity.getPackageName();

                    final int permissionCount = permissions.length;
                    for (int i = 0; i < permissionCount; i++) {
                        grantResults[i] = packageManager.checkPermission(
                                permissions[i], packageName);
                    }

                    ((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult(
                            requestCode, permissions, grantResults);
                }
            });
        }
    }

可以看到,如果系统是23以上就调用activity的申请权限方法,如果系统是23以下的,并且activity又没有实现OnRequestPermissionsResultCallback接口,那么这个requestPermissions方法就什么都没做。

所谓兼容包,其实就是帮我们判断了系统版本,针对性地进行处理,防止高版本的api在低版本上不存在而出错。

ActivityCompat.checkSelfPermission函数源码:

  public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }

        return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());
    }

可以看到这个方法其实调用的是Context的方法。需要注意的是,Context的checkPermission方法一直都是存在的,并不是23以后才加入的。

因此如果只是检查权限,不需要使用兼容包,直接调用context的方法即可。

ActivityCompat.shouldShowRequestPermissionRationale函数源码:

  public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity,
            @NonNull String permission) {
        if (Build.VERSION.SDK_INT >= 23) {
            return activity.shouldShowRequestPermissionRationale(permission);
        }
        return false;
    }
    

shouldShowRequestPermissionRationale其实也是调用了Context的方法。

Android 23以下如何检查权限呢?

上面已经说了,检查权限方法并不是23以后出现的新方法。一种检查方法是使用ActivityCompat,调用checkSelfPermission方法。
另一种方法直接使用context提供的方法:checkPermission(String permission, int pid, int uid),需要传入当前进程id和uid:

context.checkPermission(permission, android.os.Process.myPid(), Process.myUid())
动态权限处理代码示例
package com.devnn.testdemo;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.widget.Toast;

public class MainActivity extends Activity {
    String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{permission}, 100);
        }else{
            Toast.makeText(this, "已有读SDK卡权限", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode==100){
            if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
                Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
            }else if(ActivityCompat.shouldShowRequestPermissionRationale(this,permission)==false){
                Toast.makeText(this, "拒绝并勾选了不再提醒,不会弹了,需要引导用户去设置页", Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(this, "拒绝了授权,下次还会再弹", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

记得先要在AndroidManifest.xml里声明权限。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

在弹出系统的权限对话框前,弹出自已的对话框,用来说明权限用途,会更加友好一点。直接使用Materia风格的Dialog。

    public void showPermissionDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth);
        builder.setMessage("需要读SD卡权限,用来获取照片\n需要获取手机状态权限,用来获取设备号\n需要获取联系人权限,用来...");
        builder.setTitle("权限说明");
        builder.setCancelable(true);
        builder.setPositiveButton("申请", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, 100);
            }
        });
        builder.show();
    }

对话框效果:
在这里插入图片描述

只有危险权限(或叫敏感权限)才需要申请,其它权限不需要申请。

危险权限组:
在这里插入图片描述
要注意的是,“危险(敏感)权限组中的某一个权限授权了,组内其它权限也被同时授权。”这句话是错误的,经过对读写SD卡权限的测试,发现仅申请读SD卡权限后,并没有写权限。当申请了写权限后,读权限自动被授予。

关于Context.shouldShowRequestPermissionRationale(...)方法含义

ActivityCompat.shouldShowRequestPermissionRationale(…)实质也是调用Context的这个方法,参见上文源码。

从字面意思理解,即是否需要合理显示申请权限对话框(注意是系统的不是自定义的)。那么什么时候显示才是合理的呢?经过本人实测发现以下规律:

1、在第一次申请权限前,它返回了false
2、用户选择接受权限后,它返回false
3、用户选择拒绝但是没有勾选不再提醒,它返回true
4、用户选择拒绝并勾选不再提醒(永久拒绝),它返回了false

因此这个方法并不能用来判断是否需要显示自已的权限说明对话框。
它只能在权限回调里用来判断是否要引导用户到设置页打开权限。
此方法正确使用方式参考上文示例代码。

选择照片和拍照一定要相机权限吗?

很多APP有上传照片的需求,比如从用户相册中选择一张照片或者实时拍照上传。其实这种功能我们不需要相机权限,一般我们调用系统相册app即可,大多数相册还自带拍照功能,我们只是打开了别的app,相机权限是别的app自带的。我们的app在不添加任何权限的情况下,可以打开系统相册并且可以选择照片和拍照,但是无法上传,因为你拿不到照片文件。这个时候我们只需要给自己的app添加READ_EXTERNAL_STORAGE的权限即可。

Android权限篇 ContextCompat.checkSelfPermission() 方法【确定您的应用是否已被授予权限】 一、Android上声明和请求运行时权限的工作流程 在应用程序的manifest文件中声明该权限 将你的应用UX设计成不言自明的 等待用户请求一个特定的操作 许可已经授予你的应用程序 (1)Yes : 访问受权限保护的信息 (2)No : 显示原理给用户吗 No:显示原理给用户吗 Yes : 向用户解释为什么你的应用需要这个权限 – > 请求允许显示系统对话框 No : 请求允许显示系统对话框 是否授予您的应用程序权限? Yes : 访问受权限保护的信息 No : 优雅降级你的应用程 阅读详情

相关推荐

Android权限检查API checkSelfPermission失效问题

targetSdkVersion < 23的时候,6.0权限检查API失效了,不过通过上面的分析指导,在设置中权限的操作仍然会被存储内存及持久化到appops.xml文件中,这里就是走的AppOpsService那一套,AppOpsService可以看做6.0为了兼容老APP而保留的一个附加的权限管理模型,在6.0之后的系统中,可以看做runtime权限管理的补充,其实AppOpsService这套在4.3就推出了,不过不太灵活,基本没啥作用,之前只用到了通知管理。懂得多是自己的加分项 而不是必须项。

2401_84009679的博客 1201

ActivityCompat使用

今天在查看资料的时候看到了ActivityCompat这个类来启动Activity,ActivityCompat是v4包里新加的一个类,打开了看了看代码:&lt;span style="font-family:SimSun;font-size:14px;"&gt;public static void startActivity(Activity activity, Intent intent, @...

专栏 2万+

Windows平台安卓逆向工程:从APK拆解到动态调试的完整工具链指南

安卓逆向工程是深入理解移动应用内部机制的关键技术,它通过静态与动态分析相结合的方法,揭示应用的代码逻辑、数据流和通信协议。其核心原理在于对APK文件进行解包、反编译和运行时监控,从而还原应用的设计思路与实现细节。这项技术的价值不仅在于安全评估和漏洞挖掘,也为开发者学习优秀架构、进行兼容性调试提供了独特视角。在应用场景上,它广泛用于移动安全研究、协议分析、恶意软件检测以及合法合规的第三方功能扩展。本文聚焦于Windows环境下的实战流程,详细解析了以Apktool、JADX和Frida为核心的工具链搭建与使用

890

Android: 动态运行时权限(危险权限)源码分析、封装、及9.0权限改动

简介: 动态运行时权限的检测流程分析:(Android 6.0开始就有了危险权限) ActivityCompat.requestPermissions() ActivityCompat.shouldShowRequestPermissionRationale() ActivityCompat.checkSelfPermission(value) Android 9.0 对于权限处理和6.0...

手写我对你的温柔 4553

安卓逆向的核心流程

检测要么基于原理,比如lldb正在进行动态调试,status会有TracerPid的信息,APK只要检查TracerPid字段,就能知道是不是被动态调试。如果知道安卓逆向的核心流程有哪些,对安卓逆向有一个整体的认知,就能比较清晰地知道自己缺什么和学什么。要么是基于特征进行检测,比如frida的默认端口是27042,APK只要检查端口27042是不是存在,就能知道是不是被frida工具入侵了。5、代码虚拟化:原本的一句代码,变成了一套虚拟代码和虚拟机器,虽然运行的结果一样,但分析难度特别高。

2503_90751938的博客 1691

安卓逆向工程实战:从静态分析到动态调试的完整技术路径

逆向工程是理解软件内部工作机制的关键技术,其核心原理是通过分析程序的二进制代码或运行时行为,还原其设计逻辑与算法实现。这项技术在软件安全评估、漏洞挖掘、协议分析和兼容性开发等领域具有重要价值。在移动安全领域,安卓应用逆向分析尤为常见,涉及对APK文件的解包、反编译、代码审计及动态行为监控。通过静态分析工具(如JADX、Apktool)可初步探查代码结构,而动态调试技术(如基于smalidea的调试或Frida框架)则能实时捕获运行时数据与算法细节。本文以一次典型的安卓应用逆向分析实战为例,系统演示了从环境搭

weixin_34176694的博客 439

安卓开发中遇到最难的问题!最全Android面试知识点梳理,真香

前言: 本文收集整理了各大厂常见面试题N道,你想要的这里都有内容涵盖:Java 相关、Android 基础、Android Framework、三方源码、算法与数据结构、等技术栈,希望大家都能找到适合自己的公司,开开心心的撸代码。 初级 初级研发工程师的定义是掌握基础的Android知识,能够独立完成一个功能,工作年限大概在1-2年,这个层级大部分人通过看一些资料书籍再经过项目练习很快可以达到。这个级别的人往往需要掌握如下一些技能: 掌握Android 四大组件知识,深入了解相关生命周期,对于Applic

m0_57079376的博客 715

【Android 教程系列第 18 篇】关于安卓项目中 import android.support.v4(v7).app.ActivityCompat 报错问题的解决方案

关于安卓项目中 import android.support.v4(v7).app.ActivityCompat 报错问题的解决方案

“Allen Su”的博客 7125

解决90%开发者踩坑的webrtc_android权限处理指南:相机/麦克风/悬浮窗权限最佳实践

在Android平台开发WebRTC视频通话应用时,权限处理往往是新手开发者的第一个拦路虎。本文将系统梳理webrtc_android项目中相机、麦克风和悬浮窗权限的最佳实践,帮助你避开90%的常见权限问题,让视频通话功能稳定运行。 ## 📱 为什么WebRTC权限处理如此重要? WebRTC技术依赖实时音视频流传输,而Android系统对敏感权限(如相机、麦克风)采取了严格的保护机制。权限

gitblog_00998的博客 819

告别TwinCAT:手把手教你用IgH EtherCAT Master在LinuxCNC上搭建实时运动控制平台

本文详细介绍了如何利用IgH EtherCAT Master和LinuxCNC搭建开源实时运动控制平台,替代商业软件TwinCAT。通过分步指南,包括实时Linux环境配置、EtherCAT主站安装、LinuxCNC集成及多轴同步控制实现,帮助开发者构建高性能、低成本的工业自动化解决方案。

weixin_42641741的博客 401

从DDH到FastANI:原核生物分类黄金标准的进化史与技术对比

本文系统梳理了原核生物分类标准从DDH到FastANI的四次技术革命,详细解析了95%相似度阈值的科学依据及应用场景。通过对比DDH、16S rRNA、ANI和FastANI的技术特点与性能指标,为微生物研究者提供基因组分类的实战指南,并展望第三代测序时代的分类新挑战。

weixin_29275257的博客 413

Android权限框架深度解析:从开发痛点到大厂实战

你是否曾经在开发Android应用时,被复杂的权限申请流程搞得焦头烂额?不同Android版本的权限差异、特殊权限的申请方式、用户拒绝后的处理逻辑...这些问题困扰着无数开发者。今天,让我们一起来深入解析XXPermissions权限请求框架,看看它是如何优雅地解决这些痛点的。 ## 开发者的权限之痛 在Android开发中,权限管理一直是令人头疼的问题。你可能遇到过这些场景: - 在And

gitblog_00695的博客 841

Keystone变换(4)MATLAB仿真

关于Keystone变换三种方法(DFT-IFFT法、Sinc插值法和Chirp-Z法)的仿真

qq_45846079的博客 1570

Android面试知识梳理(面试官及面试者)

如何准备Android的面试,结合我之前面试和面试官的经验,目前我梳理了一些基本的知识和准备。 首先,自己要对整个面试要考察的内容要有比较清晰的结构。 下面是整个思维导图: 我们主要分为2大块 1.基础知识 基础知识主要包括 1.Java,Kotlin的基本语言, 面向对象的基本思想 内部类:内部类的分类、应用场景、内部类编译成class后是怎么样的。 抽象类 & 接口:区别、应用场景。 注解:注解的基本概念、分类、编译时注解 & 运行时注解。 内存模型。 垃圾回收

老皮的博客 820

深入解析机器人软件开发中的核心:状态机管理(FSM)—— 理论、实践与优化

状态机(FSM)是机器人软件开发中管理复杂行为逻辑的核心工具,广泛应用于导航、任务执行、故障处理等场景。本文系统探讨状态机的基础理论(定义、要素)、主流设计模式(经典FSM、分层状态机HSM、行为树BT),以及工业级实现方法(代码架构、线程安全、调试技巧)。通过移动机器人导航和机械臂任务执行的案例,分析分层状态机的实际应用,并总结常见陷阱(如状态爆炸、阻塞操作)与优化策略(异步化、事件过滤)。

郑伟强dev的专栏 292

AMBA-CHI协议详解(一)

CHI体系结构是一种可扩展、一致性的集线器接口和片上互联,可由多个组件使用。CHI体系结构允许根据性能、功耗和面积系统要求灵活地进行组件连接拓扑。硬件一致性使系统组件能够共享内存,而无需维护软件缓存以保持一致性。如果两个组件对同一存储器位置的写入可被所有组件以相同的顺序观察到,则存储器区域是一致的。

Crazzy_M的博客 1万+

android 6.0 动态权限申请帮助类

android 6.0 动态权限申请帮助类我们都知道,在android 6.0 及以上版本中,google为了增强安全性,推出了动态权限申请,即某些权限需要用户在使用时手动的授权,如果不授权则应用无法获得相关权限,那么相关权限申请,具体步骤是什么呢?下边进行简单的步骤梳理:通过checkSelfPermission()检测是否已经开启了相关权限,如果已经开启,则不需要权限申请 如果未开启,则判断是否

想你时你在天边 526

15、电科院FTU检测标准学习笔记-基本性能

作者简介:本人从事电力系统多年,岗位包含研发,测试,工程等,具有丰富的经验在配电自动化验收测试以及电科院测试中,本人全程参与,积累了不少现场的经验。

sixtome 1865

悬浮窗权限从Android 6适配到14:VirtualApp避坑实战与一劳永逸方案

VirtualApp 是一个开源的 Android 沙盒引擎,主打应用多开与双开。做多开,几乎绕不开悬浮窗权限适配——从 Android 6 一路升到 14,这套权限规则改了好几轮,稍不留神,悬浮窗就罢工。本文从一个真实故障说起,带你把权限检查、窗口类型、前台服务这些适配要点一次理清,文末附可直接抄的代码。 ## 一个真实事故:手机升完级,悬浮窗不见了 🕵️ 先讲个我同事的遭遇。他把测试机从

gitblog_00062的博客 887

MATLAB和S7-1200PLC水箱液位高度PID控制联合仿真(KEPserverOPC通信应用)

SMART PLC 向导PID的详细介绍请查看下面文章链接:S7-200 SMART PLC PID向导详细介绍(如何实现P、PD、PID控制器)-优快云博客文章浏览阅读1k次。这篇博客主要介绍SMART PLC PID向导的使用,PID控制相关的其它内容请查看专栏系列文章,常用链接如下:SMART PLC PID负压控制(过程量为负数)_负压控制pid控制程序_RXXW_Dor的博客-优快云博客1、如何实现PID反作用调节?S7-1200PLC和KEPserver OPC通信-优快云博客。

RXXW_Dor的博客 1781

HyperLynx(十三)Hyperlynx前放置之对网络的EMC分析

在“Spectrum Analyzer”对话框的“Stimulus”(激励)栏中,设置激励源频率为100MHz,选择“IC modeling”为“Fast-Strong”,并按图所示设置其他选项。显然,在仿真的基频上,它的幅值最大,将鼠标光标置于柱状图上,可以读取其值为64.28mA,这个数值是由选定的驱动芯片决定的。按上图所示的原理图,在接收端增加一个并联的RC负载,再次运行仿真,结果如图所示。在对话框左侧的“Pins”列表中,显示出了已添加电流探针的引脚,可以在此列表中选择所要仿真的目标。...

小幽余生不加糖 4680

Android存储权限演进与文件读写适配:从运行时权限到分区存储的完整解决方案

在Android应用开发中,文件存储与访问是基础且关键的技术环节。其核心原理涉及操作系统对应用数据隔离与用户隐私保护机制的演进,从早期的粗放式文件系统访问,逐步发展为基于权限沙盒的精细化管控。这一演进的技术价值在于平衡了应用功能需求与系统安全性,防止恶意应用随意访问用户敏感数据。在实际应用场景中,开发者常需处理用户日志保存、媒体文件导出等需求,但不同Android版本间的权限差异常导致兼容性问题。本文聚焦于Android存储权限的完整演进路径,特别是针对Scoped Storage(分区存储)和MANAGE

weixin_30730053的博客 303

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Android权限管理:从基础到高阶实践指南

移动应用权限管理是保障用户隐私安全的核心机制,其本质是操作系统对敏感资源的访问控制。Android系统通过安装时权限和运行时权限的分级设计,实现了功能开放与安全防护的平衡。开发者需要掌握权限声明、动态申请、回调处理的标准流程,并针对不同Android版本进行适配。在工程实践中,权限管理涉及权限组处理、后台权限专项申请、存储权限版本适配等关键技术要点。通过合理使用权限缓存、延迟申请等优化策略,可以提升应用性能与用户体验。随着Android 14的到来,开发者还需关注照片选择器、健康数据权限等新特性的适配工作。

weixin_30673611的博客 303

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

告别手动复盘:VibeAlpha Terminal 如何自动生成基金盘前策略与盘后分析报告

VibeAlpha Terminal 是一个专注于中国 A 股市场的智能金融分析平台,主打「盘前策略 + 盘后复盘」的自动化生成。它会在开盘前自动抓取隔夜宏观、北向资金、板块资金流向与持仓消息,用 AI 大语言模型为你撰写**基金盘前策略**简报;收盘后自动核对净值、个股表现与盘中新闻,生成**盘后分析报告**。从此每天不用再手动翻十几个网页做复盘。 ## 为什么要把盘前盘后复盘自动化? 手动

gitblog_00870的博客 342

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

上一篇: 【linux】30分钟学会Shell脚本
下一篇: 【Android】Android不能进行http请求,https抓包后请求失效的解决
devnn
博客等级 码龄12年 2005粉丝 90原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值