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

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

一、通知

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()
    }
目录
相关文章
|
23天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
24天前
|
数据库 Android开发 开发者
构建高效Android应用:Kotlin协程的实践指南
【4月更文挑战第2天】随着移动应用开发的不断进步,开发者们寻求更流畅、高效的用户体验。在Android平台上,Kotlin语言凭借其简洁性和功能性赢得了开发社区的广泛支持。特别是Kotlin协程,作为一种轻量级的并发处理方案,使得异步编程变得更加简单和直观。本文将深入探讨Kotlin协程的核心概念、使用场景以及如何将其应用于Android开发中,以提高应用性能和响应能力。通过实际案例分析,我们将展示协程如何简化复杂任务,优化资源管理,并为最终用户提供更加流畅的体验。
|
25天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
30天前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
在开发高性能的Android应用时,选择合适的编程语言至关重要。近年来,Kotlin因其简洁性和功能性受到开发者的青睐,但其性能是否与传统的Java相比有所不足?本文通过对比分析Kotlin与Java在Android平台上的运行效率,揭示二者在编译速度、运行时性能及资源消耗方面的具体差异,并探讨在实际项目中如何做出最佳选择。
18 4
|
23小时前
|
安全 数据处理 Android开发
构建高效Android应用:Kotlin协程的实践之路
【4月更文挑战第26天】 在面对现代Android开发时,性能优化和流畅的用户体验成为了开发者们追求的目标。Kotlin作为一种现代化的编程语言,通过其协程特性为Android应用带来了前所未有的并发处理能力。本文将深入探讨如何利用Kotlin协程提升Android应用的响应性和效率,同时保持代码的简洁性。我们将从协程的基础概念出发,逐步揭示如何在实际应用中运用这些强大的工具,以及它们如何改善应用架构和用户交互体验。
|
3天前
|
移动开发 Java Android开发
构建高效Android应用:采用Kotlin协程优化网络请求
【4月更文挑战第24天】 在移动开发领域,尤其是对于Android平台而言,网络请求是一个不可或缺的功能。然而,随着用户对应用响应速度和稳定性要求的不断提高,传统的异步处理方式如回调地狱和RxJava已逐渐显示出局限性。本文将探讨如何利用Kotlin协程来简化异步代码,提升网络请求的效率和可读性。我们将深入分析协程的原理,并通过一个实际案例展示如何在Android应用中集成和优化网络请求。
|
3天前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第24天】随着移动开发技术的不断演进,提升应用性能和用户体验已成为开发者的核心任务。在Android平台上,Kotlin语言凭借其简洁性和功能性成为主流选择之一。特别是Kotlin的协程功能,它为异步编程提供了一种轻量级的解决方案,使得处理并发任务更加高效和简洁。本文将深入探讨Kotlin协程在Android开发中的应用,通过实际案例分析协程如何优化应用性能,以及如何在项目中实现协程。
|
4天前
|
网络协议 Shell Android开发
Android 深入学习ADB调试原理(1)
Android 深入学习ADB调试原理(1)
20 1
|
9天前
|
移动开发 Android开发 开发者
构建高效Android应用:采用Kotlin进行内存优化的策略
【4月更文挑战第18天】 在移动开发领域,性能优化一直是开发者关注的焦点。特别是对于Android应用而言,由于设备和版本的多样性,确保应用流畅运行且占用资源少是一大挑战。本文将探讨使用Kotlin语言开发Android应用时,如何通过内存优化来提升应用性能。我们将从减少不必要的对象创建、合理使用数据结构、避免内存泄漏等方面入手,提供实用的代码示例和最佳实践,帮助开发者构建更加高效的Android应用。
14 0
|
19天前
|
移动开发 API Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第7天】 在移动开发领域,性能优化和应用响应性的提升一直是开发者追求的目标。近年来,Kotlin语言因其简洁性和功能性在Android社区中受到青睐,特别是其对协程(Coroutines)的支持,为编写异步代码和处理并发任务提供了一种更加优雅的解决方案。本文将探讨Kotlin协程在Android开发中的应用,揭示其在提高应用性能和简化代码结构方面的潜在优势,并展示如何在实际项目中实现和优化协程。