1.PixelCopy这个类是安卓提供的截取SurfaceView 的一个类:
val surfaceView: SurfaceView = binding.realTimeMap.getBinding()
val bitmap = Bitmap.createBitmap(surfaceView.width, surfaceView.height, Bitmap.Config.ARGB_8888)
val surfaceHolder = surfaceView.holder
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val copyResult = PixelCopy.request(
surfaceHolder.surface,
bitmap,
PixelCopy.OnPixelCopyFinishedListener { copyResult ->
if (copyResult == PixelCopy.SUCCESS) {
// 截图成功,可以在这里处理Bitmap对象
binding.ivMaxSpeed.setImageBitmap(bitmap)
} else {
// 截图失败,根据需要进行处理
}
},
Handler() // 可选的Handler对象,用于指定回调在哪个线程执行,如果不指定,默认在主线程执行
)
}
2.使用MediaProjection ,这个是系统级的截屏方法,但是比较繁琐:
a.建立前台服务;
//启动MediaService服务
fun startMediaService() {
if (isstartservice) {
startService(Intent(this, MediaService::class.java))
isstartservice = false
}
}
***
## MediaSercice:
***:
package com.allynav.iefa.service
import android.R
import android.app.*
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
class MediaService : Service() {
private val NOTIFICATION_CHANNEL_ID = "com.tencent.trtc.apiexample.MediaService"
private val NOTIFICATION_CHANNEL_NAME = "com.tencent.trtc.apiexample.channel_name"
private val NOTIFICATION_CHANNEL_DESC = "com.tencent.trtc.apiexample.channel_desc"
override fun onCreate() {
super.onCreate()
startNotification()
}
fun startNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//Call Start foreground with notification
val notificationIntent = Intent(this, MediaService::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0)
val notificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setLargeIcon(
BitmapFactory.decodeResource(
getResources(),
R.drawable.alert_dark_frame
)
)
.setSmallIcon(R.drawable.alert_dark_frame)
.setContentTitle("Starting Service")
.setContentText("Starting monitoring service")
.setContentIntent(pendingIntent)
val notification: Notification = notificationBuilder.build()
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT
)
channel.description = NOTIFICATION_CHANNEL_DESC
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
startForeground(
1,
notification
) //必须使用此方法显示通知,不能使用notificationManager.notify,否则还是会报上面的错误
}
}
override fun onBind(intent: Intent?): IBinder {
throw UnsupportedOperationException("Not yet implemented")
}
}
b.// 申请截屏权限
private fun getScreenShotPower() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mediaProjectionManager =
getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
if (mediaProjectionManager != null) {
val intent = mediaProjectionManager!!.createScreenCaptureIntent()
startActivityForResult(intent, REQUEST_MEDIA_PROJECTION)
}
}
}
c. @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
override fun onActivityResult(requestCode: Int, resultCode: Int, @Nullable data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_MEDIA_PROJECTION && data != null) {
// mediaProjection = mediaProjectionManager!!.getMediaProjection(RESULT_OK, data)
val mediaPro = mediaProjectionManager!!.getMediaProjection(RESULT_OK, data)
val bitmap = screenShot(mediaPro) //截屏
val bs = getBitmapByte(bitmap)
//对图片进行处理逻辑 例如可以保存本地、进行图片分享等
Log.e("WWW", "EEE" + bitmap)
if (bitmap != null) {
shareTipsPop.setShare(bitmap)
shareTipsPop.showPopupWindow()
}
}
}
d.处理图片的方法:
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
fun screenShot(mediaProjection: MediaProjection): Bitmap? {
val wm1 = this.windowManager
val width = wm1.defaultDisplay.width
val height = wm1.defaultDisplay.height
Objects.requireNonNull(mediaProjection)
@SuppressLint("WrongConstant") val imageReader: ImageReader =
ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 60)
var virtualDisplay: VirtualDisplay? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
virtualDisplay = mediaProjection.createVirtualDisplay(
"screen",
width,
height,
1,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
imageReader.getSurface(),
null,
null
)
}
SystemClock.sleep(1000)
//取最新的图片
val image: Image = imageReader.acquireLatestImage()
// Image image = imageReader.acquireNextImage();
//释放 virtualDisplay,不释放会报错
virtualDisplay!!.release()
return image2Bitmap(image)
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
fun image2Bitmap(image: Image?): Bitmap? {
if (image == null) {
println("image 为空")
return null
}
val width: Int = image.getWidth()
val height: Int = image.getHeight()
val planes: Array<Image.Plane> = image.planes
val buffer: ByteBuffer = planes[0].buffer
val pixelStride: Int = planes[0].pixelStride
val rowStride: Int = planes[0].rowStride
val rowPadding = rowStride - pixelStride * width
val bitmap =
Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888)
bitmap.copyPixelsFromBuffer(buffer)
//截取图片
// Bitmap cutBitmap = Bitmap.createBitmap(bitmap,0,0,width/2,height/2);
//压缩图片
// Matrix matrix = new Matrix();
// matrix.setScale(0.5F, 0.5F);
// System.out.println(bitmap.isMutable());
// bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
image.close()
return bitmap
}
3.使用 holder.lockCanvas():
// 获取SurfaceView
SurfaceView surfaceView = findViewById(R.id.surface_view);
// 获取SurfaceView的Holder对象
SurfaceHolder holder = surfaceView.getHolder();
// 创建Canvas对象
Canvas canvas = holder.lockCanvas();
// 绘制你想要的内容
// ...
// 将Canvas中的内容转换为Bitmap
Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
// 解锁Canvas并刷新SurfaceView
holder.unlockCanvasAndPost(canvas);
// 至此,你已经成功获取SurfaceView的图片了
或者:
// 1. 创建一个与 SurfaceView 大小相同的 Bitmap 对象
val surfaceView: SurfaceView = findViewById(R.id.your_surface_view_id)
val bitmap = Bitmap.createBitmap(surfaceView.width, surfaceView.height, Bitmap.Config.ARGB_8888)
// 2. 获取 SurfaceView 的 SurfaceHolder
val surfaceHolder = surfaceView.holder
// 3. 锁定 Surface,并将其绘制到 Bitmap 中
var canvas: Canvas? = null
try {
canvas = surfaceHolder.lockCanvas(null)
canvas?.drawBitmap(bitmap, 0f, 0f, null)
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas)
}
}
// 现在,bitmap 中就包含了 SurfaceView 的内容
其他方法不做表述。