电子商务网站建设与管理 教案,客户关系管理系统的功能,网站下方一般放什么,wordpress编辑器换了目录四大组件适配Activity启动方式适配Service启动方式适配前台服务需要添加权限限制静态广播的接收限制ContentResolver数据更新操作权限与安全相关主要适配点运行时动态权限申请默认不支持 http 请求SharedPreferences 适配四大组件适配
Android 应用的开发离不开 Android 四…
目录四大组件适配Activity启动方式适配Service启动方式适配前台服务需要添加权限限制静态广播的接收限制ContentResolver数据更新操作权限与安全相关主要适配点运行时动态权限申请默认不支持 http 请求SharedPreferences 适配四大组件适配
Android 应用的开发离不开 Android 四大组件的使用Android 四大组件分别是Activity用于展示前台页面Service用于执行后台任务BroadCast用于组件之间的通信ContentProvider用于应用间数据的分享。
Activity启动方式适配
Activity 组件用于和用户进行交互在 Android 9 版本中系统对于应用进程的任务栈做了调整Activity 组件是运行在任务栈task stack中而其它三大组件 Broadcast、Service、ContentProvider不需要运行在任务栈中由这些组件打开 Activity 时需要为这个 Activity 的运行指定一个新的任务栈否则会导致应用崩溃并抛出异常信息 android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? 适配方法在 Broadcast、Service、ContentProvider 这些组件中拉起 Activity需要添加FLAG_ACTIVITY_NEW_TASK标志这样便会在拉起 Activity 的同时创建出一个新的任务栈
Intent intent new Intent(context, xxxxx);//xxxxx 表示 Activity 的类名
intent.addFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActiviy(intent);Service启动方式适配
Service 是 Activity 外最常用的组件之一它承接着用户处理后台任务的需求是一种长生命周期的没有可视化界面运行于后台的一种服务程序。在 Android 5.0 之后 google 出于安全的角度禁止了隐式声明 Intent 来启动 Service隐式声明即是不通过指定 Service 包名和类名而是通过Intent 过滤机制设置 intent 的 action、dataType 等方式根据 intent 匹配规则来查找并调用 Service
Intent intent new Intent();
intent.setAction(xxxx);//xxxx 为Service 在 IntentFilter 中配置的 action
context.startService(intent);隐式启动 Service 会产生一个问题就是传入的 action、dataType 可能会匹配到别的应用的后台服务上去Service 是在后台运行的不被用户所感知因此通过隐式方式启动 Service 可能拉起的不是实际想要启动的服务从而会产生错误。
为了防止隐式启动 Service 带来的问题从 Android5.0 开始系统就禁止隐式启动 Service 的方式上述代码在 Android9 系统上运行时会导致应用崩溃并抛出异常 Service Intent must be explicit… 适配方法
解决方式一 将隐式启动转换为显式启动通过指定包名、类名的方式拉起服务
ComponentName cn new ComponentName(包名,类名);
Intent intent new Intent(cn);//显示启动 Service
context.startService(intent);解决方式二调用 intent 的 setPackage 方法指定包名
Intent intent new Intent();
intent.setAction(xxxx);//xxxx 为Service 在 IntentFilter 中配置的 action
intent.setPackage(应用包名);
context.startService(intent);前台服务需要添加权限
在 Android 9.0 中为了防止前台服务被滥用比如各种通知信息系统规定应用在使用前台服务之前必须先申请 FOREGROUND_SERVICE 权限否则就会抛出 SecurityException 异常。 java.lang.SecurityException: Permission Denial: startForeground from pidxxxx, uidxxxx requires android.permission.FOREGROUND_SERVICE 适配方法在 AndroidManifest 中添加权限声明 uses-permission android:nameandroid.permission.FOREGROUND_SERVICE / 通过这样方式便可以申请前台服务的运行权限前台服务的创建才会正常执行。
限制静态广播的接收
应用监听广播可以通过动态注册和静态注册两种方式动态注册就是在程序运行起来后调用注册方法进行注册静态注册则是把广播注册放在 Manifest 配置文件中。
在一些场景中比如监听开机启动广播来拉起应用是需要通过静态注册方式来实现。但对于需要应用正常启动后才能对广播进行正确处理的场景则应用使用动态注册的方式这时如果采用静态注册的方式在应用没有启动时收到广播可能不会得到正确的处理同时都采用静态注册的方式也会影响广播传递的效率因为很多未启动的应用也会被广播唤醒。
也是出于这样的考虑Android 9.0 之后隐式广播将会被全面限制用户的自定义广播和大部分系统广播通过隐式注册的方式即在 AndroidManifest 中注册的 Receiver 的方式将不能够生效。
适配方法使用动态注册的方式注册广播监听如下代码
IntentFilter intentFilter new IntentFilter();
intentFilter.addAction(xxxx);//xxxx 标识广播 action
context.registerReceiver(broadcastReceiver, intentFilter);采用代码中动态注册广播的方式不仅是 Android9 系统的要求也是一种比较好的开发习惯这有利于对广播的使用进行控制在应用功能已经初始化完成的时候添加广播的监听确保广播到来时的功能执行能正常进行。
限制ContentResolver数据更新操作
Android 提供 ContentProvider/ContentResolver 组件来让用户开放自己应用中的数据或者访问别的应用的数据为了防止用户数据监听被滥用从 Android8.0 系统起通过 ContentResolver的registerContentObserver 方法监听应用数据变化的操作被加以限制直接操作会报出如下错误并导致应用崩溃 Failed to find provider xxx for user xxx; expected to find a valid ContentProvider for this authority 适配方法在 AndroidManifest.xml 文件中定义一个 Provider使用监听数据更新的目标 ContentProvider的 authorities 作为这个 provider 的 authorities
providerandroid:namecom.xx.content.ContentProviderandroid:authoritiescom.xxx.androidclient android:enabledtrue android:exportedfalse
/provider权限与安全相关主要适配点
运行时动态权限申请
Google 在 Android 6.0 开始引入了权限申请机制将所有权限分成了正常权限和危险权限。应用的相关功能每次在使用危险权限时需要动态的申请并得到用户的授权才能使用。
系统权限分为两类正常权限和危险权限。
正常权限不会直接给用户隐私权带来风险。如果您的应用在其清单中列出了正常权限系统将自动授予该权限。
危险权限会授予应用访问用户机密数据的权限。如果应用在其清单中列出了危险权限则用户必须明确批准应用使用这些权限。
危险权限主要是和获取用户数据有关应用会用到的危险权限包括
android.permission.READ_EXTERNAL_STORAGE 读取外部存储数据
android.permission.WRITE_EXTERNAL_STORAGE 向外部存储写入数据常用的正常权限包括
BLUETOOTH 使用蓝牙权限
BROADCAST_STICKY 粘性广播
CHANGE_NETWORK_STATE 改变网络状态
CHANGE_WIFI_STATE 控制 WiFi 开关改变 WiFi 状态
GET_PACKAGE_SIZE 获取应用安装包大小
INTERNET 网络权限
RECEIVE_BOOT_COMPLETED 监听启动广播
REQUEST_INSTALL_PACKAGES 安装应用程序
WRITE_SYNC_SETTINGS 修改系统设置适配方法应用运行过程中动态申请需要的危险权限如下代码
requestPermissions(final NonNull Activity activity,final NonNullString[] permissions, final int requestCode)//permissions 即为需要申请权限列表默认不支持 http 请求
出于网络安全的考虑Android9 系统上应用将被禁止使用 http 协议进行网络数据传输而必须使用 https 安全网络协议如果应用中使用了 http 协议传输数据将会抛出下面的错误 java.net.UnknownServiceException: CLEARTEXT communication to xxxx not permitted by network security policy 最好的适配方式是修改所有的网络接口改为 https 协议除了服务端接口改动Google 也提供了两个方案来让客户端支持 http 协议。 方案 1 在 AndroidManifest.xml 中的 application 节点添加以下配置, 允许所有明文请求。
application
... android:usersCleartextTraffic“true”方案 2 添加自定义的网络安全配置在 res 目录下新建 xml 文件夹添加 network_security_config.xml文件
?xml version1.0 encodingutf-8?
network-security-config
base-config cleartextTrafficPermittedtrue /
/network-security-configAndroidManifest.xml 中的 application 添加
manifest ... applicationandroid:networkSecurityConfigxml/network_security_config... /application
/manifestSharedPreferences 适配
SharedPreferences 是 Android 中的数据存储组件原先针对数据访问没有严格的限制 Android9.0 以后给 SharedPreferences 引入数据文件访问权限控制去除了被外部应用读取数据的权限设置 MODE_WORLD_READABLE 或 MODE_WORLD_WRITEABLE会触发安全异常。
适配方法 方案 1 将MODE_WORLD_READABLE模 式 换 成MODE_PRIVATE 通 过 这 种 方 式 将 应 用 的SharedPreference 数据访问权限设置为私有以防止别的应用对 SharedPreference 数据进行任意的读写操作保证了应用自身的安全性对于可以向别的应用暴露的数据,也可以通过ContentProvider组件实现数据共享。
方案 2 对于需要全局读写的功能可使用其他方式替换 SharedPreferences例如DataStore、MMKV等。