Android开发,使用kotlin学习多媒体功能(详细)

2023-12-19

一、通知

1.用到的类和方法

(1) Context类

getSystemService() 接收一个字符串参数用于确定获取系统的哪个服务,这里我们传入Context.NOTIFICATION_SERVICE,获取NotificationManager

(2) NotificationManager类

createNotificationChannel() 创建通知渠道
notify() 让通知显示出来,第一个参数是id,第二个参数是Notification对象

(3) NotificationChannel类

NotificationChannel() 构建通知渠道,第一个参数,渠道ID,第二个参数,渠道名称,第三个参数,通知的重要等级,等级从高到低有IMPORTANCE_HIGH、IMPORTANCE_DEFAULT、IMPORTANCE_LOW、IMPORTANCE_MIN这几种。

(4) NotificationCompat类

NotificationCompat.builder() 创建Notification对象,第一个参数是context,第二个参数是渠道ID。

(5) Notification

setContentTitle() 指定通知的标题内容
setContentText() 指定通知的正文内容
setSmallIcon() 设置通知的小图标
setLargeIcon() 设置通知的大图标
setWhen() 设置创建的时间
setContentIntent() 通过PendingIntent构建一个延迟执行的”意图“,参数为PendingIntent对象
setAutoCancel() 方法传入true,就表示点击这个通知时,通知会自动取消
setStyle() 接收一个NotificationCompat.Style参数,这个参数时用来构建具体的富文本信息的,如长文字、图片等。
.setStyle(NotificationCompat.BigTextStyle().bigText(".........................")

.setStyle(NotificationCompat.BigPictureStyle().bigPicture(BigmapFactory.decodeResource(resources,R.drawable.big_image)))

(6) PendingIntent

getActivity() 获得PendingIntent对象,第一个参数是Context,第二个参数用不到,传入0,第三个参数是一个Intent对象,第四个参数是确定PendingIntent的行为,行为有FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT四种可选。

2.创建通知

步骤

(1)创建通知渠道

获取NotificationManager的实例,,由于NotificationManager类和createNotificationChannel()方法都是Android 8.0系统新增的API,因此在使用的时候要进行版本判断,接下来使用NotificationChannel类构建通知渠道,并调用NotificationManager类的createNotificationChannel()方法完成创建。

val manager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
            val channel=NotificationChannel("normal","Normal",NotificationManager.IMPORTANCE_DEFAULT)
            manager.createNotificationChannel(channel)
        }

(2)设置通知点击事件,构建Notification对象并显示通知。

val sendNotion:Button=findViewById(R.id.sendNotion)
        sendNotion.setOnClickListener {
            val intent= Intent(this,otherActivity::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)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.big))
                .setWhen(System.currentTimeMillis())
                .setContentIntent(pi)
                .setAutoCancel(true)
                .build()
            manager.notify(1,notification)
        }

二、调用摄像头和相册

1.用到的方法

Uri.fromFile() 将File对象转换成Uri对象,参数为File对象
FileProvider.getUriForFile() 将File对象转换成一个封装过的Uri对象,第一个参数是    Context   对象,第二个参数是任意唯一的字符串,第三个参数是File对象。
BitmapFactory.decodeStream() 将输入流传入,把图片加载成Bitmap
imageView.setImageBitmap(): 显示图片
File类常用方法
File(pathname:String) 通过路径名创建一个新的File实例
File(parent:File,child:String) 从父抽象路径和子路径名字符串创建新的File实例
File(parent:String,child:String) 从父路径名字符串和子路径名字符串创建新的File实例
exists() 路径是否存在
delete() 删除文件或者路径
createNewFile() 创建新文件
getPath() 得到File的路径

2.步骤

(1)在布局文件中,添加Button和ImageView

<Button
        android:id="@+id/takePhotoBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="take Photo"/>
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

(2)设置变量

    private val takePhoto=1
    lateinit var imageUri: Uri
    lateinit var outputImage:File

(3)创建File对象

将图片命名为output_image.jpg并存放在手机SD卡的应用关联缓存目录下

outputImage = File(externalCacheDir, "output_image.jpg")
            if (outputImage.exists()) {//如果路径存在,就先删除
                outputImage.delete()
            }
            outputImage.createNewFile()//创建一个新的File

(4)把File转换成Uri

从Android7.0系统开始,直接使用本地路径的Uri被认为是不安全,会抛出一个FileUriExposedException异常,而FileProvide则是一种特殊的ContentProvider,它使用了和ContentProvider类似的机制来对数据进行保护,可以选择性地将封装过的Uri共享给外部,从而提高了应用的安全性。

imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                FileProvider.getUriForFile(this, "com.example.cameraman's.fileprovider", outputImage);
            } else {
                Uri.fromFile(outputImage);
            }

(5)启动相机程序

// 启动相机程序
           val intent= Intent("android.media.action.IMAGE_CAPTURE")
            intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)
            requestDataLauncher.launch(intent)

(6)在onActivityResult()函数中,在相机程序拍到的图片显示出来

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        val imageView: ImageView = findViewById(R.id.imageView)
        when (requestCode) {
            takePhoto -> {
                if (resultCode == RESULT_OK) {
                    // 将拍摄的照片显示出来
                    val bitmap =
                        BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
                    imageView.setImageBitmap(rotateIfRequired(bitmap))
                }
            }
        }
    }

(7)解决调用相机程序去拍照有可能会在一些手机上发生照片旋转的情况

private fun rotateIfRequired(bitmap: Bitmap): Bitmap {
            val exif = ExifInterface(outputImage.path)
            val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
            return when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> rotateBitmap(bitmap, 90)
                ExifInterface.ORIENTATION_ROTATE_180 -> rotateBitmap(bitmap, 180)
                ExifInterface.ORIENTATION_ROTATE_270 -> rotateBitmap(bitmap, 270)
                else -> bitmap
            }
        }

        private fun rotateBitmap(bitmap: Bitmap, degree: Int): Bitmap {
            val matrix = Matrix()
            matrix.postRotate(degree.toFloat())
            val rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
            bitmap.recycle()
            return rotatedBitmap
        }

(8)在AndroidManifeest.xml对ContentProvider进行注册

android:authorities属性的值必须和刚才FileProvider.getUriForFile()方法中的第二个参数一致,另外,这里还在<provider>标签的内部使用<meta-data>指定Uri的共享路径,并引入一个@xml/file_paths资源。

<provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.example.cameraman's.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

(9)右击res目录->New->Directory,创建一个xml目录,接着右击xml目录->New->File,创建一个file_paths.xml文件

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="/" />
</paths>

三、从相册中选择图片

步骤

(1)在布局文件中加入Button:fromAlbumBtn

<Button
        android:id="@+id/fromAlbumBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="From Album"/>

(2)初始化fromAlbum

val fromAlbum = 2

(3)在按键fromAlbumBtn的点击事件中,打开文件选择器,显示图片

val fromAlbumBtn: Button = findViewById(R.id.fromAlbumBtn)
        fromAlbumBtn.setOnClickListener {
            val intent1=Intent(Intent.ACTION_OPEN_DOCUMENT)
            intent1.addCategory(Intent.CATEGORY_OPENABLE)
            intent1.type="image/*"
            requestDataLauncher1.launch(intent1)
        }

(4)在onActivityResult()函数中,将选择的图片显示出来

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        val imageView: ImageView = findViewById(R.id.imageView)
        when (requestCode) {
            ...
            fromAlbum -> {
                if (resultCode == RESULT_OK && data != null) {
                    data.data?.let { uri ->
                        //将选择的图片显示
                        val bitmap = getBitmapFromUri(uri)
                        imageView.setImageBitmap(bitmap)
                    }
                }
            }
        }
    }

(5)将Uri转换成Bitmap

private fun getBitmapFromUri(uri: Uri) =
        contentResolver.openFileDescriptor(uri, "r")?.use{
            BitmapFactory.decodeFileDescriptor(it.fileDescriptor)
        }

四、播放多媒体文件

1、播放音频

步骤

(1)创建一个MediaPlayer的实例

private val mediaPlayer=MediaPlayer()

(2)为MediaPlayer对象进行初始化操作

通过getAssets()方法得到一个AssetManager的实例,AssetManager可用于读取assets目录下的任何资源,接着调用openFd()方法将音频文件句柄打开,后来调用setDataSource()方法设置要播放的音频文件的位置和prepare()方法完成准备工作。

private fun initMediaPlayer() {
        val assetManager=assets
        val fd=assetManager.openFd("music.mp3")
        mediaPlayer.setDataSource(fd.fileDescriptor,fd.startOffset,fd.length)
        mediaPlayer.prepare()
    }

(3)设置三个按键的点击事件

        val play:Button=findViewById(R.id.play)
        val pause:Button=findViewById(R.id.pause)
        val stop:Button=findViewById(R.id.stop)
        play.setOnClickListener {
            if(!mediaPlayer.isPlaying)
                mediaPlayer.start()
        }
        pause.setOnClickListener {
            if(mediaPlayer.isPlaying){
                mediaPlayer.pause()
            }
        }
        stop.setOnClickListener {
            if(mediaPlayer.isPlaying){
                mediaPlayer.reset()
                initMediaPlayer()
            }
        }

(4)最后在onDestroy()方法中,我们需要调用stop()方法和release()方法将MediaPlayer相关的资源释放掉。

override fun onDestroy() {
        super.onDestroy()
        mediaPlayer.stop()
        mediaPlayer.release()
    }


2、播放视频

步骤

(1)在布局文件中放置三个按钮,分别控制视频的播放,暂停,和重新播放,在按钮下面放置视频VideoView。

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/play"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="play"/>
        <Button
            android:id="@+id/pause"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="pause"/>
        <Button
            android:id="@+id/replay"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="replay"/>
    </LinearLayout>

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="videoView"/>

(2)点击res->New->Directory,然后输入raw,把视频资源放在这。

(3)初始化VideoView

val uri=Uri.parse("android.resource://$packageName/${R.raw.video}")
        videoView.setVideoURI(uri)

(4)设置三个按键的点击事件

 play.setOnClickListener {
            if(!videoView.isPlaying)
                videoView.start()
        }
        pause.setOnClickListener {
            if(videoView.isPlaying){
                videoView.pause()
            }
        }
        replay.setOnClickListener {
            if(videoView.isPlaying){
                videoView.resume()
            }
        }

(5)在onDestroy()方法中,需要调用suspend()方法,将VideoView所占用的资源释放掉。

override fun onDestroy() {
        super.onDestroy()
        videoView.suspend()
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android开发,使用kotlin学习多媒体功能(详细) 的相关文章

  • Android 通知进度条冻结

    这是我正在使用的代码 http pastebin com 3bMCKURu http pastebin com 3bMCKURu 问题是 一段时间后 文件变得更重 通知栏下拉速度变慢 最后它就冻结了 你的通知太频繁了 这就是它冻结的原因 让
  • 导航组件重复 NavArgs 的问题

    我有一个片段 class SomeFragment private val args by navArgs
  • 与 Admob 广告单元 ID 混淆

    我跟着tutorial https developers google com admob android quick start在我的应用程序中创建广告横幅 到目前为止 这有效 我可以看到测试广告 但是 本教程指示我在两个不同的位置使用两
  • Android SoundPool 堆限制

    我正在使用 SoundPool 加载多个声音剪辑并播放它们 据我所知 它的功能 100 正确 但在 load 调用期间 我的日志中充斥着以下内容 06 09 11 30 26 110 ERROR AudioCache 23363 Heap
  • Firebase Analytics 禁用受众国家/地区跟踪

    我正在开发一个严格不允许位置跟踪的应用程序 我想使用 Firebase Analytic 的其他功能 例如 PageTransitions 和 Crashalitics 但如果我无法禁用受众位置跟踪 我就无法使用其中任何功能 这是我在 An
  • Phonegap - 如何将.txt文件保存在Android手机的根目录中

    我正在尝试使用phonegap 将 txt 文件保存在Android 手机的根目录中 我已经安装了这些插件 cordova plugin file 和 cordova plugin file transfer 在 config xml 文件
  • (Ionic 2)尝试回退到 Cordova-lib 执行时发生错误:TypeError:无法读取未定义的属性“then”

    Edit 使用 ionic 2 时会发生这种情况 我知道它还不稳定 但我认为可能有一些解决方案 因为其他人似乎没有遇到这个问题 Edit end 由于某种原因 我在尝试使用 ionic build android 和 ionic build
  • 接近语法错误(代码1)插入Android SQLite

    我正在创建一个通讯录应用程序 用户可以在其中输入姓名 电子邮件地址和号码 我希望将此数据保存在数据库中 但我似乎无法使插入方法起作用 我收到的错误是 android database sqlite SQLiteException near
  • Android 版 Robotium - solo.searchText () 不起作用

    我在使用 Robotium 时遇到 searchText 函数问题 我正在寻找这个字符串
  • ROOM迁移过程中如何处理索引信息

    CODE Entity tableName UserRepo indices Index value id unique true public class GitHubRepo PrimaryKey autoGenerate true p
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • Android Studio:无法启动守护进程

    当我尝试在 Android Studio 中导入 gradle 项目时 遇到以下错误 Unable to start the daemon process This problem might be caused by incorrect
  • Android 设备上的静默安装

    我已经接受了一段时间了 在 Android 上静默安装应用程序是不可能的 也就是说 让程序安装捆绑为 APK 的应用程序 而不提供标准操作系统安装提示并完成应用程序安装程序活动 但现在我已经拿到了 Appbrain 快速网络安装程序的副本
  • 如何将设备连接到Eclipse?

    我无法解决这个简单的问题 我正在尝试通过 USB 电缆将我的设备连接到 Eclipse 在我的 PC 上 我已经安装了 Eclipse 和 Android SDK 并且在模拟器上运行该程序运行良好 我已在我的电脑上下载并安装了 Samsun
  • 下载后从谷歌照片库检索图像

    我正在发起从图库中获取照片的意图 当我在图库中使用 Nexus 谷歌照片应用程序时 一切正常 但如果图像不在手机上 在 Google Photos 在线服务上 它会为我下载 选择图像后 我将图像发送到另一个活动进行裁剪 但在下载的情况下 发
  • 应用程序关闭时的倒计时问题

    我制作了一个 CountDownTimer 代码 我希望 CountDownTimer 在完成时重新启动 即使应用程序已关闭 但它仅在应用程序正在运行或重新启动应用程序时重新启动 因此 如果我在倒计时为 00 10 分钟 秒 时关闭应用程序
  • SharedFlow 和 StateFlow 的主要区别

    两者有什么区别共享流 and 状态流 以及如何使用这些MVI建筑学 使用简单更好吗Flow或者这些作为状态和事件 Flow 是冷的 意味着它仅在收集数据时才发出数据 另外Flow不能保存数据 可以把它看成是水在里面流动的管道 Flow中的数
  • 在 Android 中,如何将字符串从 Activity 传递到 Service?

    任何人都可以告诉如何将字符串或整数从活动传递到服务 我试图传递一个整数 setpossition 4 但它不需要 启动时总是需要 0 Service 我不知道为什么我不能通过使用 Service 实例从 Activity 进行操作 publ
  • 无法运行我的应用程序,要求选择 Android SDK

    今天我已经安装了Android Studio 金丝雀 1 现在我无法运行我的应用程序 将出现以下对话框 我已经通过 文件 gt 项目结构 gt Android SDK 位置 设置了正确的 SDK 位置 期待您的帮助来解决这个问题 警告对话框
  • 无法将 admob 与 firebase iOS/Android 项目链接

    我有两个帐户 A 和 B A 是在 Firebase 上托管 iOS Android unity 手机游戏的主帐户 B 用于将 admob 集成到 iOS Android 手机游戏中 我在尝试将 admob 分析链接到 Firebase 项

随机推荐

  • 对Java Stream 进行二次封装

    对Java Stream 进行二次封装 一共整理了10个工具方法 可以满足 Collection List Set Map 之间各种类型转化 例如 将 Collection
  • idea springboot项目运行出错(运行模式问题)

    问题 解决办法 第一步 第二步 DoperatingMode dev
  • Error: T doesn‘t have .length

    Error T doesn t have length 在 TypeScript 中 当我们使用泛型
  • String.class.equals(value.getClass())

    这段代码是在判断变量 value 是否是 String 类型的示例代码 它使用了 Java 中的反射机制 解析该代码的含义如下 String class 表示获取 String 类的 Class 对象 它是描述 String 类的类对象 v
  • R语言采集获取58商铺出租转让信息

    前两篇文章给我一个朋友分析出店铺商品以及地址房源信息 后来去看了下店铺房租有点贵 还是毛坯房 要自己装修 本着节约成本的原则 熬了个通宵 给他采集了一些转租商铺数据 因为数据比较多 过于先进不方便展示 我就将我爬虫程序的模版展示给大家观看
  • 通俗易懂的讲解Java 中的反射机制

    Java 中的反射机制是指在程序运行时动态地获取类的信息 以及在运行时动态操作类和对象的能力 通过反射机制 我们可以在编译时不知道具体类的情况下 获取类的属性 方法 构造函数等信息 并且可以在运行时调用这些属性 方法或创建对象 反射机制提供
  • 说说一次 Dubbo 服务请求流程?

    Dubbo 是一个高性能 轻量级的开源 Java RPC 框架 用于构建服务化应用程序 下面是一个简单的 Dubbo 服务请求流程 客户端发起请求 客户端通过 Dubbo 提供的 RPC 客户端库发送请求到 Dubbo 服务提供者 请求包含
  • 基于SpringBoot+Vue的中山社区医疗综合服务平台设计实现(源码+lw+部署文档+讲解等)

    文章目录 前言 详细视频演示 具体实现截图 技术栈 后端框架SpringBoot 前端框架Vue 持久层框架MyBaitsPlus 系统测试 系统测试目的
  • 智慧排水检测系统,提升城市生命线管理效率

    随着城市化的快速发展 排水系统作为城市生命线的重要组成部分 其管理和维护对于城市的正常运行至关重要 传统的排水系统监测方法往往依赖人工巡查和定期的设备检查 存在效率低下 易出错等问题 为了解决这些问题 智慧排水监测系统应运而生 本文将详细介
  • Vue 条件渲染 v-if

    v if 指令 用于控制元素的显示或隐藏 执行条件 当条件为 false 时 会将元素从 DOM 中删除 应用场景 适用于显示隐藏切换频率较低的场景 语法格式 div 内容 div 基础用法
  • ISO认证的意义以及费用

    ISO认证是国际标准化组织制定的一套标准体系 它对于企业来说具有重要的意义 ISO认证可以帮助企业提高管理水平 提升产品品质 增强市场竞争力 同时也是企业拓展市场 开拓客户的重要手段 一 ISO认证的意义 ISO认证具有以下几个方面的意义
  • ExperimentalWarning: The http2 module is an experimental API.

    错误提示 Node js ExperimentalWarning The fs promises API is experimental 原因是node的版本不是最新的 而在项目引入的模块是最新的 node js的版本低于模块的版本 解决方
  • 一键证件照换底色软件哪个好?这款让你的证件照独具特色!

    在我们生活中 有很多时候需要用到证件照 无论是报名考试还是申请签证 都需要提供一张规格标准的证件照片 然而 有时候我们拍摄的照片可能存在一些问题 比如背景色不符合要求 这时候 如果有一款一键证件照换底色软件 就能够轻松解决这个问题了 首先
  • 基于单片机设计的电子指南针(LSM303DLH模块(三轴磁场 + 三轴加速度)

    一 前言 本项目是基于单片机设计的电子指南针 主要利用STC89C52作为主控芯片和LSM303DLH模块作为指南针模块 通过LCD1602液晶显示屏来展示检测到的指南针信息 在日常生活中 指南针是一种非常实用的工具 可以帮助我们确定方向
  • C# Tcplistener,Tcp服务端简易封装

    文章目录 前言 相关文章 前言 设计 代码 简单使用 运行结果 前言 我最近有个需求要写Tcp服务端 我发现Tcp服务端的回调函数比较麻烦 简化Tcp的服务 我打算自己封装一个简单的Tcp服务端 相关文章 C TCP应用编程三 异步TCP应
  • 超级好用的SQL语句大全

    文章目录 一 DDL Data Definition Language 数据定义语言 1 操作库 2 操作表 二 DML Data Manipulation Language 数据操作语言 1 增加 insert into 2 删除 del
  • 如何利用 Kubernetes 的新 CronJob API 进行高效的任务调度

    Kubernetes 的 CronJob API 是在云原生环境中自动执行常规任务的关键功能 本指南不仅引导您完成使用此 API 的步骤 还说明了它非常有用的实际用例 先决条件 正在运行的 Kubernetes 集群 版本 1 21 或更高
  • MySQL数据库:为什么它是您的最佳选择?

    MySQL是一个关系型数据库管理系统 由瑞典MySQL AB公司开发 目前属于Oracle旗下产品 MySQL是最流行的关系型数据库管理系统之一 在WEB应用方面 MySQL是最好的RDBMS Relational Database Man
  • Linux中使用HTTP协议进行API交互的示例——你的“API小伙伴”

    大家好 今天我们要聊聊在Linux中如何使用HTTP协议进行API交互 听起来有点高大上 但其实并不难 让我们一起来看看 首先 我们需要了解什么是API API 全名为应用程序接口 Application Programming Inter
  • Android开发,使用kotlin学习多媒体功能(详细)

    一 通知 1 用到的类和方法 1 Context类 getSystemService 接收一个字符串参数用于确定获取系统的哪个服务 这里我们传入Context NOTIFICATION SERVICE 获取NotificationManag