安卓杂记2
前言
收录了我学习郭霖大神的《第一行代码》遇到的问题以及处理方法,从内容提供器到服务的这个区间吧。
这个是上一篇安卓杂记1的链接。
找不到内容提供器的URL?
报错大概是这样式的:
Unknown URL content://com.example.databasetest.provider/book
原因大概就是:因为别的应用可以随便访问内容提供器,于是Android 11后就加了点东西。首先就是不能直接找到内容提供器了,需要事先我们在AndroidManifest.xml(注册表,或者叫清单文件)
里面添加查询声明:
举例:A是内容提供器,B去访问A,要在B的注册表里写:
<!--下面两个访问方式随意选一个就行了,也可以一起写-->
<queries>
<package android:name="com.example.databasetest" />
<!--这个是访问内容提供器的包名-->
<provider android:authorities="com.example.databasetest.provider" />
<!--这个是直接访问那个提供器authoritis部分-->
</queries>
这样就能愉快的访问内容提供器了
然后就是A(内容提供器)里面也可以自己设定权限了,如果设定了后,别人要访问它还得有对应的权限才行,这就大大提高了内容提供器的灵活性:
<provider
android:name=".contentProvider.DatabaseProvider"
android:authorities="com.example.databasetest.provider"
android:enabled="true"
android:exported="true"
android:permission="android.permission.contentProvider.DatabaseProvider">
<!--设置使用提供器的权限,权限名可以自己设定-->
</provider>
同时:如果设定如下权限名就表示:只允许系统访问了
<provider
android:permission="android.permission.MANAGE_DOCUMENTS"
当然,还有临时权限什么的,这就不多提了,具体参考如下文档:
参考文档:
创建 content provider | Android 开发者 | Android Developers (google.cn)
创建自定义文档提供程序 | Android 开发者 | Android Developers (google.cn)
参考网址:
通知发送了却显示不了?
由于Android13之后,添加了通知权限:"android.permission.POST_NOTIFICATIONS"
于是:要在AndroidManifest.xml(注册表,或者叫清单文件)
中添加权限声明:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
然后再动态申请这个权限就好了
notifyPer.launch("android.permission.POST_NOTIFICATIONS")
//这个是Activity Result API写法,也可以用书上的申请方法
参考文档:创建通知 | Views | Android Developers (google.cn)
然后就是:我在创建通知的时候偷了一下懒,没有为它设置图片,然后就报错了…我以为有文字就够了的,谁知道文字图片都要啊。。
服务的前台(景)创建不了?
为了更好的管理服务,除了需要在AndroidManifest.xml
声明前台权限FOREGROUND_SERVICE
外,还需要声明对应的类型Type
。
现在我们以书中的下载前台(数据同步类型)为例:
先在AndroidManifest.xml
中声明对应类型:
<!--具体有什么类型不用记的,编译器会帮我们的记住的-->
<service
android:name=".service.MyService"
android:foregroundServiceType="dataSync"
android:enabled="true"
android:exported="true">
</service>
然后你就会发现爆红了:
foregroundServiceType:dataSync requires permission:[android.permission.FOREGROUND_SERVICE_DATA_SYNC]
但是呢,不要慌张。为了安全和好用,前景服务会为我们自动检查我们所需要的对应权限。所以,这是编译器给我们的提示:它说dataSync
类型需要具备如下权限:android.permission.FOREGROUND_SERVICE_DATA_SYNC
,于是:就给它声明这个权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
然后有一个小的细节:
android:exported="false"
这里表示服务不被其他应用程序使用。想想也是,我的服务,凭啥给别的app使用恁?他给我钱啊,这也不是不能考虑。
最后,在我的服务中添加如下代码:
class MyService : Service() {
override fun onCreate() {
......
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(2, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
//最后这个是类型申明,不用记,编译器会帮我们记住的。
} else {
startForeground(2, notification)
}
}
}
这样就可以启动前台服务啦,不过呢,有时候这个前台的显示会慢一点才来,不会像通知那样,一下子就来了,我们要给他一点耐心。(默认下它来了还会伴有一段铃声)
当然,前台服务也是可以单独停止的,只需要调用:stopForeground(Service.STOP_FOREGROUND_REMOVE)
方法就可以了。
然后呢,如下是参考文档,要启动其他类型的前台服务的话可以进行参考,但本质就是改一改对应位置的数据就可以了:
前台服务 | Background work | Android Developers (google.cn)
前台服务类型 | Background work | Android Developers (google.cn)
最后是一个小拓展啦:我们在使用QQ音乐的时候,发现那个前台服务上面有按钮(图标)可以点击,这样就能决定下一曲啊什么的了,其实就是在创建通知的时候调用了这个:
.addAction(R.drawable.ic_action, "Stop Service", pendingIntent); // 添加一个按钮
注意最后一个pendingIntent
,它不单单可以启动活动还可以发送广播
也就是说:我可以在这个服务里面建立一个广播接收器来接受这个广播,然后在对应的广播接受器里面执行对应的逻辑,比如stopForeground(Service.STOP_FOREGROUND_REMOVE)
什么的,这样就解锁了QQ前台服务为啥有许多功能了。