Android笔记(十六):前台服务

news2024/12/26 22:39:12

设置服务为前台服务。前台服务会在状态栏显示一个通知。通知界面与服务进行关联。

一、什么是通知?

Notification通知是在移动应用APP提供给用户的消息提示,是在移动系统的通知栏中显示。当移动应用不在运行时或者在后台状态下,通过发布通知给用户,用户可以浏览通知的提示信息或者对通知进行某些操作。

在这里插入图片描述
图1 通知显示示例
如上图所示:
①小图标:为必要图标,通过setSmallIcon()设置
②应用名称:由系统提供。
③时间戳:由系统提供,可以通过setWhen()进行替换或使用setShowWhen(false)将其隐藏。
④标题:可选内容,通过setContentTitle()设置。
⑤文本:可选内容,通过setContentText()设置。
⑥大图标:可选图标(通常仅用于联系人照片),通过setLargeIcon设置。
⑦样式:通过样式设置大图片

1.在AndroidManifest.xml中配置发布通知的权限

注意从Android13开始发布通知需要配置android.permission.POST_NOTIFICATIONS许可

  <!-- 设置发布通知许可 --> 
 <uses-permission    
   android:name="android.permission.POST_NOTIFICATIONS" />

2.请求发布通知权限

// 请求发布通知权限

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
0)
}

3. 创建通知渠道和创建通知

(1)创建通知渠道

从 Android 8.0(API 级别 26)开始,所有通知都必须分配到相应的渠道。

    //定义通知管理器
    val notificationManager:NotificationManager =
        getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    //定义通知渠道的标识
    val channelId = "com.example.ch07"
    //定义通知渠道的名称
    val channelName = "移动应用开发"
    //定义通知渠道:指定通知渠道的标识、名称和通知渠道的重要级别
    val channel = NotificationChannel(channelId,channelName, NotificationManager.IMPORTANCE_DEFAULT)
    //定义通知渠道的描述信息
    val channelDesc = "移动应用通知渠道描述"
    //创建并配置通知渠道
    notificationManager.createNotificationChannel(channel)

(2)创建通知

    //创建通知
    val notification = Notification.Builder(this,channelId) .apply{
        //设置通知标题
        setContentTitle("通知实例一")
        //设置通知内容
        setContentText("欢迎使用通知")
        //设置通知时间
        setWhen(System.currentTimeMillis())
        //设置通知的小图标
        setSmallIcon(R.mipmap.nature)
        //设置通知的大图标
        setLargeIcon(BitmapFactory.decodeResource(resources,R.mipmap.someone))
        //设置通知样式
        style = Notification.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources,R.mipmap.honggutan))
    }.build()

(3)发布通知

    //创建通知标记
    val notificationID = 1
    //发布通知到通知栏
    notificationManager.notify(notificationID,notification)

4. 通知实例

接下来通过实例来说明发布通知:

(1)定义界面MainScreen

在MainScreen中定义发布通知的按钮,提供交互处理

@Composable
fun MainScreen(postAction:()->Unit){
    Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center){
        TextButton(onClick={
            postAction.invoke()
        }){
            Text("发布通知",fontSize = 24.sp)
        }
    }
}

(2)定义主活动MainActivity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //请求权限
        requestNotificationPermission()

        setContent {
            Ch07_DemoTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    MainScreen {
                        showNotification()
                    }
                }
            }
        }
    }

    private fun requestNotificationPermission(){
        // 检查通知权限是否已经授予 注意:API 33以上版本需要检查POST_NOTIFICATIONS发布通知权限
        if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.TIRAMISU) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
                0
            )
        }
    }

    private fun showNotification(){
        //定义通知管理器
        val notificationManager:NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        //定义通知渠道的标识
        val channelId = "com.example.ch07"
        //定义通知渠道的名称
        val channelName = "移动应用开发"
        //定义通知渠道:指定通知渠道的标识、名称和通知渠道的重要级别
        val channel = NotificationChannel(channelId,channelName, NotificationManager.IMPORTANCE_DEFAULT)
        //定义通知渠道的描述信息
        val channelDesc = "移动应用开发通知渠道描述"
        //创建并配置通知渠道
        notificationManager.createNotificationChannel(channel)

        //创建通知
        val notification =
            Notification.Builder(this,channelId)
                .apply{
            //设置通知标题
            setContentTitle("通知实例一")
            //设置通知内容
            setContentText("欢迎使用通知")
            //设置通知时间
            setWhen(System.currentTimeMillis())
            //设置通知的小图标
            setSmallIcon(R.mipmap.nature)
            //设置通知的大图标
            setLargeIcon(BitmapFactory.decodeResource(resources,R.mipmap.someone))
            //设置通知样式
            style =
                Notification.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources,R.mipmap.honggutan))
        }.build()

        //创建通知标记
        val notificationID = 1
        //发布通知到通知栏,注意从Android13开始发布通知需要配置android.permission.POST_NOTIFICATIONS许可
        notificationManager.notify(notificationID,notification)
    }
}

运行结果如下所示:

在这里插入图片描述

图2 运行结果
运行结果的图片来自网络,如有侵权,告知,会主动删除。

二、前台服务

设置服务为前台服务。前台服务会在状态栏显示一个通知。通知界面与服务进行关联。从Android 14版本(API Level 34)开始,每个前台服务需要声明合适的服务类型。也就是在启动前台服务时,系统会根据服务类型检查是否满足前提条件。
表2-1 常见服务类型

前台服务类型要声明的权限运行时要求前提条件运行时请求权限请求权限调用的方法说明
相机FOREGROUND_SERVICE_CAMERA请求CAMERA运行时权限在后台访问相机
连接设备FOREGROUND_SERVICE_CONNECTED_DEVICECHANGE_NETWORK_STATE或CHANGE_WIFI_STATE或CHANGE_WIFI_MULTICAST_STATE或NFC或TRANSMIT_IRBLUETOOTH_CONNECT或BLUETOOTH_ADVERTISE或BLUETOOTH_SCAN或UWEB_RANGING调用UsbManager.requestPermission()与需要的蓝牙、NFC、IR、USB或网络的外部设备互动
数据同步FOREGROUND_SERVICE_DATA_SYNC数据传输的操作
健康FOREGROUND_SERVICE_HEALTHHIGH_SAMPLING_RATE_SENSORSBORY_SENSORS或ACTIVITY_RECOGNITION为健身类别的应用提供支持
位置FOREGROUND_SERVICE_LOCATIONACESS__COARSE_LOCATION或ACESS_FINE_LOCATION为位置信息使用权的长时间运行用例
媒体FOREGROUND_SERVICE_MEDIA_PLAYBACK在后台继续播放音频或视频
媒体投影FOREGROUND_SERVICE_MEDIA_PROJECTION调用createScreenCaptureIntent()使用MediaProjection API将内容投影到外部
麦克风FOREGROUND_SERVICE_MICROPHONERECORD_AUDIO在后台继续捕获麦克风内容
致电FOREGROUND_SERVICE_PHONE_CALLMANAGE_OWN_CALLS使用COnnetionService API继续当前通话
远程消息传递FOREGROUND_SERVICE_REMOTE_MESSAGING将短信从一台设备转移另外一台设备
配置前台服务

启动前台服务

Context.startForeground(int,Notification)

例:创建一个前台服务,播放mp3文件,并在状态栏中显示相应的通知。

1.创建服务

在这里插入图片描述
自定义服务,可以控制音频的播放,代码如下:

class MusicService : Service() {
    lateinit var mediaPlayer: MediaPlayer

    override fun onCreate() {
        super.onCreate()
        mediaPlayer = MediaPlayer.create(this,R.raw.song3)

    }
    override fun onBind(intent: Intent): IBinder? {
        postNotification()
        mediaPlayer.setOnPreparedListener {
            mediaPlayer.start()
        }
        mediaPlayer.setOnCompletionListener {
            mediaPlayer.stop()
        }
        return null
    }

    override fun onUnbind(intent: Intent?): Boolean {
        if(mediaPlayer.isPlaying) {
            mediaPlayer.stop()
        }

        return super.onUnbind(intent)
    }

    /**
     * Request notification permission
     * 请求通知权限
     */
    private fun requestNotificationPermission(){
        val notificationPermissionGranted =
            NotificationManagerCompat.from(this).areNotificationsEnabled()

        if(!notificationPermissionGranted){
            val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
            intent.putExtra(Settings.EXTRA_APP_PACKAGE,packageName)
            startActivity(intent)
        }
    }

    private fun postNotification(){
        //请求通知权限
        requestNotificationPermission()
        //创建通知管理器
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        //定义通知渠道
        val channel = NotificationChannel("music_service","一剪梅",NotificationManager.IMPORTANCE_DEFAULT)
        //创建通知渠道
        notificationManager.createNotificationChannel(channel)
        //定义启动服务的意图
        val intent1 = Intent(this,NextActivity::class.java)
        //定义悬浮意图
        val pendingIntent = PendingIntent.getActivity(this,0,
            intent1,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)

        //创建通知
        val notification = NotificationCompat.Builder(this,"music_service").apply{
            setOngoing(true)
            setOnlyAlertOnce(true)
            setContentTitle("播放音乐")
            setContentText("正在歌曲播放一剪梅...")
            setSmallIcon(R.mipmap.ic_launcher)
            setColorized(true)
            color = resources.getColor(R.color.teal_200,null)
            setContentIntent(pendingIntent)
        }.build()

        startForeground(1,notification)
    }
}

2.在AndroidManifest.xml配置服务

<service
            android:foregroundServiceType="mediaPlayback"
            android:name=".MusicService"
            android:enabled="true"
            android:exported="true" />

设置前台服务类型为mediaPlayback

3.在自定义应用中创建通知渠道

class MusicApp: Application() {
    override fun onCreate() {
        super.onCreate()
        //从API 26开始使用通知渠道
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
            //定义通知管理器
            val notificationManager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            //定义通知渠道的标识
            val channelId = "com.example.course.ch07"
            //定义通知渠道的名称
            val channelName = "移动应用开发"
            //定义通知渠道:指定通知渠道的标识、名称和通知渠道的重要级别
            val channel = NotificationChannel(
                            channelId,
                            channelName,
                            NotificationManager.IMPORTANCE_DEFAULT)
            //创建并配置通知渠道
            notificationManager.createNotificationChannel(channel)
        }
    }
}

需要在AndroidManifest.xml中指定自定义的应用为当前应用,配置自定义应用

     <application
             android:name=".MusicApp" 
         ...>
         .......
     </application>

4. 在主活动MainActivity中启动服务

要启动前台服务需要在AndroidManifest.xml配置前台服务的权限:

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

在主活动启动前台服务

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val intent1 = Intent(this,MusicService::class.java)
        requestPermissions()
        setContent {
            Ch07_DemoTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Column(modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally){
                        Row{
                            TextButton(onClick = {
                                startService(intent1)
                            }){
                                Text("播放",fontSize = 20.sp)
                            }

                            TextButton(onClick = {
                                stopService(intent1)
                            }){
                                Text("停止",fontSize = 20.sp)
                            }
                        }
                    }
                }
            }
        }
    }

    private fun requestPermissions(){
        //从API 33开始请求发布通知权限
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.TIRAMISU) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
                0
            )
        }
    }
}

在这里插入图片描述
图3

参考文献

  1. 陈轶 《Android移动应用开发(微课版)》清华大学出版社 2022-9 P203-P238

  2. 前台服务启动限制
    https://developer.android.google.cn/about/versions/12/foreground-services?hl=zh-cn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1271605.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python快速实现BMI(身体质量指数)计算器(窗口界面形式)

BMI是身体质量指数&#xff08;Body Mass Index&#xff09;的缩写&#xff0c;是一种衡量人体肥胖程度的指标。它是根据人的身高和体重计算得出的&#xff0c;公式为&#xff1a; BMI 体重&#xff08;kg&#xff09;/ 身高^2&#xff08;m&#xff09; 其中&#xff0c;体…

有它再也不用PS制作企业期刊了!

随着互联网的发展&#xff0c;越来越多的人开始使用在线工具来制作企业期刊。但是&#xff0c;对于一些新手来说&#xff0c;使用PS等专业的图像处理软件可能会感到非常困难。那么&#xff0c;有没有一种简单易用的方法来制作企业期刊呢&#xff1f;答案是肯定的&#xff01; 所…

老师选班干部的方法

我经常被问到这样一个问题&#xff1a;“老师&#xff0c;你怎么选班干部的&#xff1f;”那我就来分享一下我的经验吧&#xff0c;希望能给广大教师朋友提供一些参考。 选班干部之前先要明确一点&#xff0c;班干部是做什么的&#xff1f;有什么职责。班干部是班级的核心力量&…

什么是gRPC

gRPC&#xff08;gRPC Remote Procedure Call&#xff09;是由 Google 开发的开源 RPC 框架&#xff0c;它基于 HTTP/2 标准&#xff0c;使用 Protocol Buffers 作为接口定义语言&#xff08;IDL&#xff09;。gRPC 提供了一种高效、跨语言、跨平台的远程过程调用&#xff08;R…

如何制作一个数字人?流程是怎样的?

​​虚拟人概念从早期动漫领域的初音未来用一首《甩葱歌》让绿色双马尾的“歌姬”形象火出圈&#xff0c;到洛天依登上央视春晚舞台&#xff0c;再到众多虚拟歌手、虚拟主播、KOL、代言人等活跃于各种情境中。 去年以来&#xff0c;元宇宙和虚拟人技术进入全球科技产业的聚光灯…

牛客算法心得——abb(dp)

大家好&#xff0c;我是晴天学长&#xff0c;传智杯的题&#xff0c;我准备写一个题解&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1) .abb leafee 最近爱上了 abb 型语句&#xff0c;比如“叠词词”、…

量化误差的测量

因为转换的精度有限&#xff0c;所以将模拟值数字化时会不可避免地出现量化误差。量化误差由转换器及其误差、噪声和非线性度决定。当输入信号和计数器时基有区别时就会产生量化误差。根据输入信号的相位和计数器时基的匹配程度&#xff0c;计数器有下列三种可能性&#xff1a;…

光伏设计软件操作指南

在能源产业的变革中&#xff0c;光伏将成为未来最大的绿电来源。光伏电站未来25年的发电量、后期的运维等&#xff0c;都需要借助严谨的设计。光伏设计软件可以帮助设计者减少工作量&#xff0c;降低人工计算的错误&#xff0c;使得数据更精确。 1.了解软件构成 光伏设计软件专…

Carbonyl ,一个可以在终端里运行的浏览器

浏览器对于我们的日常来说是使用频率比较高的一个东西。 一般来说&#xff0c;对于桌面的发行版的linux的浏览器&#xff0c;用的比较多的是Firefox浏览器。对于我们日常windows、mac等。常用的有chrome、edge等。 但是&#xff01;在终端里运行一个浏览器&#xff0c;我想大多…

8.0 新特性 - Generated Invisible Primary Key

文章目录 说明1. GIPK 介绍1.1 参数设置2.2 可见性测试2.3 修改元数据可见性2.4 修改查询可见性 2. GIPK 测试2.1 Binlog 分析2.2 主从复制2.3 逻辑备份2.4 其它限制2.4.1 AUTO_INCREMENT 属性2.4.2 my_row_id 关键字 后记 说明 MySQL Innodb 引擎采用的是 IOT&#xff08;索引…

记录:Unity脚本的编写9.0

目录 射线一些准备工作编写代码 突然发现好像没有写过关于射线的内容&#xff0c;我就说怎么总感觉好像少了什么东西&#xff08;心虚 那就在这里写一下关于射线的内容吧&#xff0c;将在这里实现射线检测鼠标点击的功能 射线 射线是一种在Unity中检测碰撞器或触发器的方法&am…

作为搜索引擎,TikTok超过了谷歌

Rise at Seven通过分析不同行业的数千个关键词进行了研究&#xff0c;突出了用户在TikTok上搜索的100个单词和短语&#xff0c;比在谷歌上搜索的更多。 虽然承认“near me”和“what’s on”的搜索查询仍然是谷歌上最突出的搜索查询&#xff0c;但Rise at Seven得出的结论是&a…

11-28 SpringBoot1

约定大于配置 简化Spring开发, spring boot致力于简洁&#xff0c;让开发者写更少的配置&#xff0c;程序能够更快的运行和启动。它是下一代javaweb框架&#xff0c;并且它是spring cloud(微服务)的基础。dev-ops:开发者,运维者。 springboot特点:优点面试重点 1)为基于Spring…

一键上传,无限容量!打造高效图床工具,利用Electron和Gitee搭建自己的私人云存储空间

说在前面 平时写文章或写代码的时候&#xff0c;都少不了需要将本地图片转成在线图片链接&#xff0c;大家都是使用什么工具进行转换的呢&#xff1f;相信很多人都有自己的图床工具&#xff0c;今天来给大家介绍一下&#xff0c;怎么基于Gitee和Electron来开发一个便捷的图床工…

消除笔怎么用?手把手教你一键智能消除杂物

消除笔怎么用&#xff1f;消除笔是一种非常实用的工具&#xff0c;可以帮助我们快速修复图片中的小问题。无论是想要消除照片中的路人还是进行一些修改&#xff0c;消除笔都可以轻松地帮助我们实现。 以下是使用消除笔的步骤&#xff1a; 1、打开水印云软件&#xff0c;并在工具…

ArkTS-时间滑动选择器弹窗

时间滑动选择器弹窗 以24小时的时间区间创建时间滑动选择器&#xff0c;展示在弹窗上。 示例 useMilitaryTime: 展示时间是否为24小时制&#xff0c;默认为12小时制。默认值&#xff1a;false Entry Component struct TimePickerDialogExample {private selectTime: Date new …

基于SSM乡镇自来水收费系统的设计与实现

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对乡镇自来水收费信息管理混乱&#xff0c;出错率高&#xff0c;信息安…

i己学助力构建幼教智能时代家园共育新模式

近日,为探索智能时代幼儿教育的智慧化解决方案,智能时代赢之道——2023幼教智能时代精英论坛在北京成功举办。在会议现场,来自全国各地的幼儿教育专家、园长、教师汇聚一堂,针对智能时代幼儿园所应该如何变革展开分享和讨论,“i己学智慧课堂”同期发布。 “在1-6年级阶段,平均…

专业级音频处理 Logic Pro X 中文 for Mac

Logic Pro X是一款专业音频制作和音乐创作软件。它是Mac电脑上最受欢迎和广泛使用的音频工作站&#xff08;DAW&#xff09;。Logic Pro X提供了丰富的功能和工具&#xff0c;适用于音乐制作、录音、编辑、混音和音频处理等方面。以下是Logic Pro X软件的一些主要特点和功能&am…

05-React路由(Router 5版本)

React路由背景介绍 背景介绍 多页面应用与SPA单页面应用 多页面应用 先说传统的多页面&#xff0c;需要写多个子页面 点击导航栏&#xff0c;整个页面都会刷新&#xff0c;但是实际上我只想刷新一小块的内容&#xff0c;其他东西变化不大 而且这个单页面&#xff0c;每次切…