Android 8.0 引入了通知渠道的概念
* 首先需要一个NotificationManager对通知进行管理,调用context的getSystemService()获取
* 此方法接收一个字符串参数用于确定获取系统的哪个服务,这里传入Context.NOTIFICATION_SERVICE
* 所以获取NotificationManager实例可以写成
* val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
*
* 接下来使用NotificationChannel类创建一个通知渠道,并调用NotificationManager的createNotificationChannel()方法完成创建
* 由于NotificationChannel类和createNotificationChannel都是android8.0新增的API,所以使用时要进行版本判断
* if(Build.VERSION.SDK_INT >= Build.VERSION_CODE.0{
* val channel = NotificationChannel(channelId, channelName, importance)
* manager.createNotificationChannel(channel)
* }
*
* 通知可以在Activity BroadcastReceiver Service中创建,创建步骤如下:
* val notification = NotificationCompat.Builder(context,channelId).build()
* 丰富Notification对象
* val notification = NotificationCompat.Builder(context,channelId)
* .setContentTitle("")
* .setContentText("")
* .setSmallIcon("")
* .setLargeIcon("")
* .build()
* 完成创建后只需调用NotificationManager的notify()方法就可以让通知显示
* manager.notify(1,notification)
*
* PendingIntent可以简单理解为延迟执行的Intent
* NotificationCompat.Builder这个构造器还可以连缀一个setContentIntent()方法,接收的参数正是一个PendingIntent对象
* 这里可以通过PendingIntent构建意图,用户点击通知便会执行相应的逻辑
*
* 高重要等级的通知渠道发出的通知可以弹出横幅,发出声音,
* 而低重要等级通知渠道发出的通知不仅可能被隐藏,而且可能被改变显示的顺序,将其排在更重要通知之后
package com.example.notificationtest
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
class MainActivity : AppCompatActivity() {
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sendNotice :Button = findViewById(R.id.sendNotice)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.cancel(1) /显式取消id为1的通知
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR_0_1){
/创建普通通知渠道
val channel = NotificationChannel("normal","Normal",NotificationManager.IMPORTANCE_DEFAULT)
manager.createNotificationChannel(channel)
/创建另一个重要的通知渠道
val channel2 = NotificationChannel("import","Import",NotificationManager.IMPORTANCE_HIGH)
manager.createNotificationChannel(channel2)
}
sendNotice.setOnClickListener {
val intent = Intent(this,MainActivity2::class.java)
val pendingIntent = PendingIntent.getActivity(this,0,intent,0)
/创建通知
val notification = NotificationCompat.Builder(this,"import") /重要等级为import
.setContentTitle("This is content title")
.setContentText("this is content text")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.setAutoCancel(true)/通知点击后自动消失
.build()
manager.notify(1,notification)
}
}
}
摄像头和相册选取照片
package com.example.cameraalbumtest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.ImageView
import androidx.core.content.FileProvider
import java.io.File
class MainActivity : AppCompatActivity() {
val tackPhoto = 1
val fromAlbum = 2
lateinit var imageUri : Uri
lateinit var outputImage : File
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/控件绑定
val tackPhotoBtn : Button = findViewById(R.id.takePhotoBtn)
val fromAlbumBtn : Button = findViewById(R.id.getPhoto)
val imageView : ImageView = findViewById(R.id.imageView)
tackPhotoBtn.setOnClickListener {
/创建File对象,用于存储拍摄的照片
outputImage = File(externalCacheDir,"output_image.jpg") /getexternalCacheDir得到应用关联缓存目录
if (outputImage.exists()){
outputImage.delete()
}
outputImage.createNewFile()
imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR_0_1){
FileProvider.getUriForFile(this,"com.example.cameraalbumtest.fileprovider",outputImage)
}else{
Uri.fromFile(outputImage)
}
/启动相机程序
val intent = Intent("android.media.action.IMAGE_CAPTURE")
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)
startActivityForResult(intent,tackPhoto)
}
fromAlbumBtn.setOnClickListener {
/打开文件选择器
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
/指定只显示图片
intent.type = "image/*" /***/
startActivityForResult(intent,fromAlbum)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val imageView : ImageView = findViewById(R.id.imageView)
when(requestCode){
tackPhoto -> {
if (resultCode == Activity.RESULT_OK){
/将拍摄的照片显示出来
val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
imageView.setImageBitmap(rotateIfRequired(bitmap))
}
}
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)
}
//图片旋转
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()/将不在需要的Bitmap对象回收
return rotatedBitmap
}
}