运用手机多媒体之使用通知

news2024/11/19 21:20:27

文章目录

  • 使用通知
    • 将程序运行到手机上
    • 使用通知
      • 创建通知渠道
      • 通知的基本用法
      • 通知的进阶技巧
        • setStyle()方法
        • 不同重要等级的通知渠道

使用通知

将程序运行到手机上

  • 在AS当中除了使用模拟器来运行我们的程序,还可以使用真机来运行我们写的程序
  • 想要将程序运行到手机上,首先需要将手机通过数据线连接到我们的电脑上
  • 打开自己手机的开发人员设置,打开USB调试即可,然后Android Studio就可以自动识别到你的手机

使用通知

  • 通知是Android系统当中比较有特色的一个功能,当某个应用程序希望用户发出一些提示信息,而该程序又不在前台运行的时候,就饿可以借助通知来进行实现
  • 发出一条通知之后,手机最上方的状态栏就会显示一个通知图标,下拉状态栏之后就可以看到通知的详细内容
  • Android的通知自退出之后就大获成功,IOS系统也在5.0版本之后加入了类似的功能

创建通知渠道

  • 通知这个功能最初的初衷是好的,但是在后来却被开发者玩坏了
  • 每发出一条通知,都可能意味着自己的应用程序会拥有更高的打开率,因此有太多太多应用想尽办法地给用户发送通知,以博取更多的展示机会.
  • 虽然Android系统允许我们将某个应用程序的通知完全屏蔽掉,以防止他一直给我们发送垃圾信息,但是在这些信息当中,也有可能存在我们想要关心的内容
  • 比如说我们想要接收微博我们关注的某个人发送来的信息,但是又不想接收微博推送的花边信息,这在之前,用户是没有办法对这些信息做区分的,要么同意接收所有信息,要么屏蔽所有信息,这也是Android通知的功能痛点
  • 于是Android8.0系统引入了通知渠道这个概念
  • 顾名思义就是每一条通知都要有一个属于自己的渠道,每个应用程序都可以自由的创建当前应用拥有那些通知渠道,但是这些通知渠道的控制权是掌握在用户手中的,用户可以自由的选择这些通知渠道的重要程度,是否响铃,是否震动或者是否需要关闭.
  • 拥有了渠道控制权之后,用户就可以对一个应用的通知进行选择性的关闭了
  • 而对于每个应用来说,通知渠道的划分是十分考究的,因为通知渠道一旦创建之后就不能进行修改了,因此开发者需要仔细分析自己的应用程序一共有哪几类通知的类型,然后再去创建相应的通知渠道
  • 参考一下推特的通知渠道划分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jEb0teXs-1671627257231)(C:/Users/zhengbo/%E6%88%91%E7%9A%84%E5%AD%A6%E4%B9%A0/Typora%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E5%AE%89%E5%8D%93/image-20221220234205458.png)].

  • 可以看到推特根据自己的通知类型,对通知渠道进行了非常详细的划分,这样用户的自主选择权力就比较高了.
  • 要创建通知渠道,我们先要创建一个NotificationManager对通知进行管理,并且调用NotificationManager的createNotificationChannel()方法完成创建.
  • 由于NotificationManager类和createNotificationChannel()方法都是Android8.0系统中新增的API,因此我们在使用的时候还需要进行版本判断才可以,写法如下:
if(Build.VERSION.SDK_INT >= Build.VERSON_CODES.O) {
    val channel = NotificationChannel(channelId, channlName, importance)
    manager.createNotificationChannel(channel)
}
  • 创建一个通知渠道至少需要渠道ID,渠道名称以及重要等级这三个参数
  • 其中渠道ID可以随便定义,只要保证全局唯一就可以了,渠道名称是给用户看的.需要清楚表达这个渠道的用途
  • 通知的重要等级有:IMPORTANCE_HIGH,IMPORTANCE_DEFAULT,IMPORTANCE_LOW,IMPORTANCE_MIN这几种.
  • 对应的重要程度依次由高到低,不同的重要等级会决定通知的不同行为,并且用户是随时可以更改某个通知渠道的重要等级的,这是开发者无法干预的.

通知的基本用法

  • 通知的用法还是比较灵活的,既可以在Activity里面创建,也可以在BroadcastReceiver里面创建,也可以在Service里面进行创建

  • 相比于在BroadcastReceiver和Service,在Activity里面创建通知的场景比较少,因为一般就是当程序进入后台的时候才会进行通知

  • 但是无论在那里进行创建,整体的步骤都是相同的

  • 首先需要一个Builder构造器来创建Notification对象,但是问题在于Android系统的每一个版本对通知的功能或多或少都是有一定的改动的,API不稳定的问题在通知上凸显的比较严重.

  • 比如通知渠道功能在Android8.0之前就是没有的,那么如何解决该问题,就是使用AndroidX库中提供的兼容API.AndroidX库中提供了一个NotificationCompat类,使用这个类的构造器创建Notification对象就可以保证我们的程序在所有的Android系统版本上都能够正常工作了,代码如下所示.

val notification = NotificationCompat.Builder(context, channelId).build()
  • NotificationCompat.Builder的构造函数当中接受两个参数
  • 第一个参数是context
  • 第二个参数是渠道ID,需要和我们在创建通知渠道的时候指定的渠道id匹配
  • 上述代码只是创建了一个空的Notification对象,并不具有实际意义,我们可以在最终build()方法之前连缀任意多的设置方法来创建一个丰富的Notification对象,下面是一些最基本的设置
val notification = NotificationCompat.Builder(context, channelId)
	.setContentTitle("This is content title")
	.setContentText("This is content text")
	.setSmallIcon(R.drawable.small_icon)
	.setLargeIcon(BitmapFactory.decodeResource(getResource(), R.drawable.large_icon))
	.build()
  • 上述代码一共调用了四个设置方法分别用来指定通知的标题内容,正文内容,通知的小图标,通知的大图标等
  • 以上工作都完成之后,只需要调用NotificationManager.notfy()方法就可以让通知显示出来了
  • notify()方法接受两个参数,第一个参数是id,要保证为每个通知指定id都是不同的,第二个参数是Notification对象,这里我们直接将刚刚创建好的Notification对象传入即可,因此显示一个通知就可以完成了
manager.notify(1, notification)
  • 创建NotificationTest项目来编写示例
  • 先编写布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <Button
        android:id="@+id/sendNotice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Notice" />
</LinearLayout>
  • 编辑按钮的点击事件
package com.zb.notificationtest

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.BitmapFactory
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.NotificationCompat
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //先获取NotificationManager的实例
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        //创建一个ID为normal的渠道
        //创建渠道的代码只在第一次执行的时候才会创建,当下次再次执行创建代码的时候
        //系统会检测到该通知渠道已经创建成功,因此不会重复创建,也不会影响执行效率
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel =
                NotificationChannel("normal", "Normal", NotificationManager.IMPORTANCE_DEFAULT)
            manager.createNotificationChannel(channel)
        }
        //设置按钮的点击事件
        sendNotice.setOnClickListener {
            val notification = NotificationCompat.Builder(this, "normal")
                .setContentTitle("this is content title")
                .setContentText("this is content text")
                .setSmallIcon(R.drawable.small_icon)
                .setLargeIcon(
                    BitmapFactory.decodeResource(
                        resources,
                        R.drawable.large_icon
                    )
                )
                .build()
            manager.notify(1, notification)
        }
    }
}
  • 运行项目,点击按钮就可以发现手机的通知栏给我们发送了一条通知,下拉通知栏之后就可以看到这条通知的详情.
  • 但是此时点击这条通知,是没有任何反应的,但是我们日常使用的应用发送的通知一般点击之后都会跳转到具体的通知详情页面,想要实现这种效果,我们还需要在代码的相应位置进行设置,这就要涉及一个全新的PendingIntent概念了.
  • PendingIntent从名字上面来看和Intent有点类似,它们确实存在不少的共同点,比如它们都可以指明一个意图,都可以用来启动一个Activity,启动Service以及发送广播等等
  • 不同的是Intent倾向于立即执行某个动作,而PendingIntent倾向于某个合适的时机执行某个动作,所以可以把PendingIntent简单理解为延迟执行的Intent
  • PendingIntent它主要提供了几个静态方法用于获取PendingIntent实例,可以根据需求来选择是使用getActivity()方法,getBroadcast()方法,还是getService()方法,这几个方法所接收的参数都是相同的
  • 第一个参数依旧是Context
  • 第二个参数一般用不到传入0即可
  • 第三个参数是一个Intent对象,我们可以通过这个对象构建出PendingIntent的意图
  • 第四个参数用于确定PendingIntent的行为,有FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT这4个值可以选择.
  • 每种值得具体含义可以查看文档,通常情况下这个参数传入0就可以了.
  • 之前NotificationCompat.Builder这个构造器还可以连缀一个setContentInent()方法,接收的参数正是一个PendingIntent对象
  • 因此这里就可以通过PendingIntent构建一个延迟执行的"意图",当用户点击这条通知的时候,就会执行相应的逻辑
  • 现在来优化一下NotificationTest项目,给刚才的通知加上点击的功能,让用户点击这条通知的时候,就可以启动另外一个Activity
  • 首先我们需要准备好一个另外的Activity,NotificationActivity
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="This is notification layout"
        android:textSize="24sp" />
</RelativeLayout>
  • 这样就将Notification准备好了,下面修改MainActivity中的代码
 //设置按钮的点击事件
 sendNotice.setOnClickListener {
     val intent = Intent(this, NotificationActivity::class.java)
     val pi = PendingIntent.getActivity(this, 0, intent, 0)
     val notification = NotificationCompat.Builder(this, "normal")
         .setContentTitle("this is content title")
         .setContentText("this is content text")
         .setSmallIcon(R.drawable.small_icon)
         .setLargeIcon(
             BitmapFactory.decodeResource(
                 resources,
                 R.drawable.large_icon
             )
         )
         .setContentIntent(pi)
         .build()
     manager.notify(1, notification)
 }
  • 可以看到这里先使用了Intent表达出我们想要启动NotificationActivity的意图,然后将构建好的Intent对象传入PendingInent的getActivity()方法当中,以得到PendingIntent的实例,接着在Notification.Builder中调用setContentIntent()方法,把它作为参数传入即可.
  • 现在点击弹出的通知之后就可以跳转到我们新创建的Activity上面去了.
  • 但是点击完成之后发现通知图标还没有消失,原因是如果我们没有在代码当中对该通知进行取消,它就会一直显示在该系统的状态栏之上,解决的方法有两种
  • 第一种方法是:在NotificationCompat.Builder中再连缀一个setAutoCancel()方法
val notification = NotificationCompat.Builder(this, "normal")
    ...
    .setAutoCancel(true)
    .build()
  • 可以看到当setAutoCancel()方法传入true之后,就表示当点击这个通知的时候,通知会自动取消

  • 第二种方法是显示的调用NotificationManager的cancel()方法将它取消.

class MainActivity : AppCompatActivity() {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main) 
      val manager = getSystemService(Context.NOTIFICATION_SERVICE) as
          NotificationManager
      manager.cancel(1)
}
  • 这里我们给cancel()方法传入了1,是因为我们在创建通知的时候,给通知指定的id,因此你想要取消哪条通知再cancel()方法中传入该通知的id就可以了.

通知的进阶技巧

setStyle()方法

  • 上面的示例都是通知最基本的一些用法,实际上NotificationCompat.Builder中提供了非常丰富的API,以便于我们创建出更多种的通知效果,下面是一些比较常用的API
  • setStyle()方法,这个方法允许我们构建出富文本的通知内容,也就是说,通知中不光可以有文字图标,还可以包含更多的东西.setStyle()方法接收一个NotificationCompat.Style参数,这个参数就是用来构建具体富文本信息的,如长文字,图片等.
  • 使用之前的方法,如果我们在内容正文当中设置了很多的内容,通知出来的效果是不会全部显示,多余的部分会使用省略号进行代替,这也很正常,因为通知本来就应该言简意赅,多余的部分放在后面的Activity当中进行展示比较合适
  • 但是如果真的要在通知当中显示一段比较长的文字,Android也是支持的,通过setStyle()方法就可以做到,具体的写法如下:
.setStyle(NotificationCompat.BigTextStyle().bigText("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +
        "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" +
        "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"))
  • 就是使用setStyle()方法来代替setContentText()方法,我们在方法当中创建了一个NotificationCompat.BigTextStyle对象,这个对象就是用来封装长文字信息的,只要调用它的bigText()方法就可以将文字内容传入就可以了.
  • 除了显示长文字之外还可以显示一张大的图片,这次在参数中创建一个NotificationCompat.BigPictureStyle对象,这个对象就是用于设置大图片的,然后调用它的bigPicture()方法将图片进行传入
.setStyle(
    NotificationCompat.BigPictureStyle().bigPicture(
        BitmapFactory.decodeResource(resources, R.drawable.large_icon)
    )
)
  • 事先准备一张图片,通过BitmapFactory的decodeResource()方法将图片解析成Bitmap对象,再传入bigPicture()方法中就可以了
  • 以上就是setStyle()方法当中比较重要的内容了

不同重要等级的通知渠道

  • 通知渠道的重要等级越高,发出的通知就越容易获得用户的注意,比如高重要等级的通知渠道发出的通知可以弹出横幅,发出声音,而低重要等级的通知渠道发出的通知不仅可能会在某些情况下被隐藏,而且还有可能被改变显示顺序,将其更重要的通知后面.
  • 需要注意的是,开发者只能在创建通知渠道的时候为它指定初始的重要等级,如果用户不认可这个重要等级的话,可以随时进行修改,开发者无法再进行调整和修改,因为通知渠道一旦创建就不能再通过代码进行修改了.
  • 再创建一个新的通知渠道来进行测试,修改MainActiviy中的代码如下所示
val channel2 =
     NotificationChannel("important", "Important", NotificationManager.IMPORTANCE_HIGH)
 manager.createNotificationChannel(channel2)
  • 这里将通知渠道的重要等级设置成为了高,表示这是一条非常重要的通知,要求用户必须看到
  • 运行项目之后可以看到这次的通知不是在系统状态栏显示一个小图标了,而是弹出了一个横幅,并且附带了通知的详细内容,表示这是一条非常重要的通知,不管用户是在玩游戏还是在看电影,这条通知都会显示在最上方,以此引起用户的关注
  • 当然在使用这个等级的通知渠道的时候,一定要特别小心,一定要确保这条通知足够的重要,否则就会引起用户的排斥感.

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

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

相关文章

推荐系统学习笔记-推荐系统分布式离线训练

背景 在推荐、广告、搜索等互联网场景下&#xff0c;动则TB甚至PB级数据量。导致几乎不可能在传统单机环境下完成机器学习模型的训练。分布式机器学习训练成为称为唯一选择。 主要手段 • Spark MLlib • Parameter Server • Tensorflow Spark MLlib MLlib从功能上说与Sc…

如何利用地表温度遥感数据和气象资料计算农田地表水热通量

地表水热通量主要包括感热/显热通量和潜热通量&#xff0c;是陆-气交互以及水-热-碳循环研究的重要变量。其中&#xff0c;潜热通量是地表蒸散发的能量形式&#xff0c;对农业水资源管理、作物水分利用效率等非常关键。由于热红外遥感对地表干湿变化、以及农业干旱响应快速&…

WeakHashMap源码解析

WeakHashMap源码解析 简介 WeakHashMap 是一种 弱引用 map&#xff0c;内部的 key 会存储为弱引用&#xff0c;当 jvm gc 的时候&#xff0c;如果这些 key 没有强引用存在的话&#xff0c;会被 gc 回收掉&#xff0c;下一次当我们操作 map 的时候会把对应的 Entry 整个删除掉…

金融信息科技服务外包风险管理能力成熟度评估规范 学习笔记 附录下载地址

金融信息科技服务外包风险管理的范围 本标准规定了金融业信息科技服务外包风险管理能力成熟度评估体系以及对发包方和承包方的总体要求&#xff0c;分别对发包方、承包方的服务外包风险管理能力成熟度进行了分级定义&#xff0c;并规定了对发包方和承包方进行服务外包风险管理…

《OpenGL 模型》 渲染出帅气的暗影战士

模型Assimp流程网格模型效果Assimp 3D建模工具&#xff0c;可以让艺术家创建复杂的形状&#xff0c;Assimp库用于加载&#xff0c;如加载obj格式的文件到我们的程序之中&#xff0c;下载CMAKE用于构建该库&#xff08;会有很多问题&#xff09;&#xff0c;不过&#xff01;我…

【小程序】小程序代码的构成

目录 项目结构 1. 了解项目的基本组成结构 2. 小程序页面的组成部分 JSON配置文件 1. JSON 配置文件的作用 2. app.json 文件 3. project.config.json 文件 4. sitemap.json 文件 5. 页面的 .json 配置文件 6. 新建小程序页面 7. 修改项目首页 项目结构 1. 了解项…

别再用过时的方式了!全新版本Spring Security,这样用才够优雅!

基本使用 我们先对比下Spring Security提供的基本功能登录认证&#xff0c;来看看新版用法是不是更好。 升级版本 首先修改项目的pom.xml文件&#xff0c;把Spring Boot版本升级至2.7.0版本。 <parent><groupId>org.springframework.boot</groupId><art…

Lua 元表(Metatable)

在 Lua table 中我们可以访问对应的 key 来得到 value 值&#xff0c;但是却无法对两个 table 进行操作(比如相加)。 因此 Lua 提供了元表(Metatable)&#xff0c;允许我们改变 table 的行为&#xff0c;每个行为关联了对应的元方法。 例如&#xff0c;使用元表我们可以定义 …

STM32程序设计规范浅析

这篇博客写到“STM32基础知识篇”里&#xff0c;一方面是一个很好地对过往工作的总结&#xff0c;另一方面也是整个专栏撰写计划的开端&#xff0c;古人云&#xff1a;良好的开端是成功的一半&#xff0c;在文章的最后详细地规划了整个专栏后期的更新计划。 笔者前段时间休息的…

无人机遥感图像拼接与处理操作技术

【内容简述】&#xff1a; 无人机遥感图像采集流程&#xff1a; 无人机遥感监测介绍 无人机航线规划设计 无人机飞行软件操作 无人机航拍一般过程 无人机遥感图像拼接软件操作&#xff1a; Photoscan软件介绍 软件基本操作与实践 遥感图像拼接的一般流程 遥感图像分组拼接与点…

【centos】安装nvida CUDA平台附带安装cudnn库

目录1.安装 CUDAToolKit2.安装cudnn库1.安装 CUDAToolKit 使用 lspci | grep -i nvidia列出所有支持的GPU 安装内核开发依赖包&#xff1a; yum install kernel-devel查看内核版本号&#xff0c;用来看与开发包版本号是否一致&#xff1a; uname -r查看nvida显卡驱动&#…

设计模式之迭代器模式

Iterator design pattern 迭代器模式的概念、迭代器模式的结构、迭代器模式的优缺点、迭代器模式的使用场景、迭代器模式的实现示例、迭代器模式的源码分析 1、迭代器模式的概念 迭代器模式&#xff0c;即提供一种方法来顺序访问聚合对象内的元素&#xff0c;而不暴露聚合对象…

LeetCode HOT 100 —— 448. 找到所有数组中消失的数字

题目 给你一个含 n 个整数的数组 nums &#xff0c;其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字&#xff0c;并以数组的形式返回结果。 思路 原地哈希&#xff08;简单模拟&#xff09;&#xff1a; 核心思路&#xff1a; 因为…

Python 和 PyQt5 实现打地鼠小游戏

Python 和 PyQt5 实现打地鼠小游戏 实现效果&#xff1a; 视频效果&#xff1a; https://live.csdn.net/v/264602https://live.csdn.net/v/264602 代码&#xff1a; import random import sysfrom PyQt5.QtCore import QBasicTimer, Qt, QTimer from PyQt5.QtGui import QCo…

CSS3【基础选择器、字体样式、文本样式、行高样式】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录基础选择器1. 标签选择器2. 类选择器3. id选择器字体和文本样式1.字体样式1.1 字体大小1.2 字体粗细1.3 字体样式&#xff08;是否倾斜&#xff09;1.4 常见字体系列…

JAVA中实现多线程-单例双重锁(DCL(Double Check Lock)双重锁检查)

一 .多线程 继承 Thread 类实现 Runnable 接口实现 Callable 接口线程池 重写run方法&#xff0c;创建对象&#xff0c;调用start()方法启动线程 1&#xff0c;新生状态 – 用new关键字建立一个线程后&#xff0c;该线程对象就处于新生状态。 – 处于新生状态的线程有自己的…

Netty前置知识

传统IO 这里以文件输入输出流&#xff1a;FileInputStream 、 FileOutputStream 来进行解释。由继承关系得知&#xff0c;这两个输入和输出类继承自 InputStream 和 OutputStream 这两个基础的输入、输出的抽象类&#xff0c;这时我们可以看到当我们需要读写文件的时候&#x…

leetcode--搜索

搜索1.深度优先搜索(DFS)&#xff08;1&#xff09;岛屿的最大面积(695)&#xff08;2&#xff09;省份数量&#xff08;3&#xff09;太平洋大西洋水流问题(417)2.回溯法&#xff08;1&#xff09;全排列(46)&#xff08;2&#xff09;组合(77)&#xff08;3&#xff09;单词搜…

C++ allocator设计内存管理器

文章目录allocator内存管理器基本属性类的设计关键功能的实现完整的内存管理器内存管理器的测试&#xff1a;设计自定义的String类。前情回顾&#xff1a; allocator内存管理类 allocator内存管理器 某些类需要在运行时分配可变大小的内存空间&#xff0c;一般来说我们使用容器…

从零搭建完整python自动化测试框架(UI自动化和接口自动化)

从零搭建完整python自动化测试框架&#xff08;UI自动化和接口自动化&#xff09; 文章目录 总体框架 PO模式、DDT数据驱动、关键字驱动 框架技术选择 框架运行结果 各用例对应的定义方式&#xff08;PO/DDT&#xff09; 测试执行结果 从零开始搭建项目 一、开发环境搭…