通知
class MainActivity : AppCompatActivity() {
@SuppressLint("MissingInflatedId")
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// 获取系统的通知服务,以便在后续代码中创建和发送通知
val channel = NotificationChannel("normal", "Normal",NotificationManager.IMPORTANCE_DEFAULT)
// channel设置通知渠道,重要等级可自行设置
manager.createNotificationChannel(channel)
val btn:Button = findViewById(R.id.btn)
btn.setOnClickListener {
val intent = Intent(this, notice::class.java)
val pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
// 设置点击事件
val notification = NotificationCompat.Builder(this, "normal")
.setContentTitle("This is content title")
.setStyle(NotificationCompat.BigTextStyle().bigText("设置长通知显示啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"))
.setContentIntent(pi) // 设置点击后跳转的意图
.setAutoCancel(true) // 点击后通知图标自动关闭
.setContentText("This is content text")
.build()
manager.notify(1, notification)
}
}
}
摄像头和相册
拍照
class MainActivity : AppCompatActivity() {
private val takePhoto = 1
private lateinit var imageUri: Uri
private lateinit var outputImage: File
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val takePhotoBtn:Button = findViewById(R.id.takePhotoBtn)
takePhotoBtn.setOnClickListener {
outputImage = File(externalCacheDir, "output_image.jpg")
if (outputImage.exists()) {
outputImage.delete()
}
outputImage.createNewFile()
imageUri = FileProvider.getUriForFile(this, "com.example.myapplication.fileprovider", outputImage)
// FileProvider 是一种contentProvider,提供数据保护,这里指访问文件的保护
val intent = Intent("android.media.action.IMAGE_CAPTURE")
// 创建拍照意图intent
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
startActivityForResult(intent, takePhoto)
// 将拍照后的照片的Uri添加到Intent中,以便在拍照操作完成后,系统将照片保存到指定的位置。
// 这样,我们可以在后续的操作中获取到拍照后的照片。
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
takePhoto -> {
if (resultCode == Activity.RESULT_OK) {
// 如果拍照成功
val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
// 从imageUri解码照片,并转换为Bitmap对象
val imageView:ImageView = findViewById(R.id.imageView)
imageView.setImageBitmap(rotateIfRequired(bitmap))
// 检查并旋转照片(如果需要),然后将旋转后的照片设置为ImageView的图像
}
}
}
}
private fun rotateIfRequired(bitmap: Bitmap): Bitmap {
val exif = ExifInterface(outputImage.path)
// 创建一个ExifInterface对象,用于读取照片的EXIF信息。
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 {
// 接受一个Bitmap对象和旋转角度作为参数,使用Matrix对象旋转照片,并返回旋转后的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
}
}
Manifest.xml:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapplication.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:resource="@xml/file_paths"
android:name="android.support.FILE_PROVIDER_PATHS" />
</provider>
files_path.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path android:name="my_images" android:path="/" />
</paths>
1. 元素定义了一个名为my_images的外部存储路径。
2. android:path="/" 属性表示该路径指向外部存储的根目录。此处指的是SD卡
在Android应用程序中,使用Bitmap对象存储照片有以下几个原因:
-
内存管理:Bitmap对象可以直接在内存中操作图像数据,这使得在处理图像时可以更快地访问和修改数据。与从文件系统或其他存储方式加载图像相比,使用Bitmap对象可以减少I/O操作,提高性能。
-
便于操作:Bitmap对象提供了丰富的API,可以方便地对图像进行各种操作,如缩放、裁剪、旋转、滤镜等。这使得在Android应用程序中处理图像变得更加简单和高效。
-
兼容性:Bitmap对象是Android平台的一部分,因此它具有很好的兼容性。这意味着我们可以在不同的Android设备和版本上使用相同的Bitmap对象来处理图像。
-
易于传输和共享:使用Bitmap对象可以轻松地在应用程序、服务和设备之间传输和共享图像。例如,我们可以将Bitmap对象发送给其他应用程序或服务,以便它们可以访问和处理图像。这使得在应用程序之间共享和传输图像变得更加简单和高效。
-
节省存储空间:Bitmap对象可以直接在内存中操作图像数据,因此它们通常比文件系统中的图像文件更小。这意味着使用Bitmap对象可以节省设备的存储空间。
相册
class MainActivity : AppCompatActivity() {
private val fromAlbum = 2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
fromAlbumBtn.setOnClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
// 意向为打开文档,让用户选择文件
intent.addCategory(Intent.CATEGORY_OPENABLE)
// 向Intent对象添加一个类别,表示我们希望打开的文档应该是可打开的(即可读取的)。
intent.type = "image/*"
// 设置Intent对象的MIME类型为image/*,表示我们希望打开的文档应该是图像文件。
startActivityForResult(intent, fromAlbum)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
fromAlbum -> {
if (resultCode == Activity.RESULT_OK && data != null) {
data.data?.let { uri ->
val bitmap = getBitmapFromUri(uri)
imageView.setImageBitmap(bitmap)
}
}
}
}
}
private fun getBitmapFromUri(uri: Uri) = contentResolver.openFileDescriptor(uri, "r")?.use {
BitmapFactory.decodeFileDescriptor(it.fileDescriptor)
}
}
播放多媒体文件
播放音乐
MediaPlayer的常用方法:
class MainActivity : AppCompatActivity() {
private val mediaPlayer = MediaPlayer()
// 操作音频相关的需要引用MediaPlayer()对象中的方法
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initMediaPlayer()
play.setOnClickListener {
if (!mediaPlayer.isPlaying) {
mediaPlayer.start() //
}
}
pause.setOnClickListener {
if (mediaPlayer.isPlaying) {
mediaPlayer.pause() //
}
}
stop.setOnClickListener {
if (mediaPlayer.isPlaying) {
mediaPlayer.reset() //
initMediaPlayer()
}
}
}
private fun initMediaPlayer() {
val assetManager = assets
// assetManger可以读取asserts下的所有资源
val fd = assetManager.openFd("music.mp3")
// 将名为music.mp3的文件放在asserts目录下
mediaPlayer.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)
mediaPlayer.prepare()
}
override fun onDestroy() {
super.onDestroy()
mediaPlayer.stop()
mediaPlayer.release()
}
}
播放视频
VideoView常用方法
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val uri = Uri.parse("android.resource://$packageName/${R.raw.video}")
videoView.setVideoURI(uri)
play.setOnClickListener {
if (!videoView.isPlaying) {
videoView.start()
}
}
pause.setOnClickListener {
if (videoView.isPlaying) {
videoView.pause()
}
}
replay.setOnClickListener {
if (videoView.isPlaying) {
videoView.resume()
}
}
}
override fun onDestroy() {
super.onDestroy()
videoView.suspend()
}
}
音频和视频播放的方法有所不同。对于音频文件,MediaPlayer
类提供了一个简单的方法来直接指定文件路径或资源ID。而对于视频文件,VideoView
类需要一个Uri
对象来指定文件位置,以便与底层的MediaPlayer
进行交互。这是因为VideoView
是基于SurfaceView
实现的,而SurfaceView
需要一个Uri
对象来确定要播放的视频文件