Skip to content

Instantly share code, notes, and snippets.

@nosix nosix/Capture.kt
Created Sep 18, 2016

Embed
What would you like to do?
Taking a snapshot of the screen for Android (SDK 21) in Kotlin 1.0.3
package xxx
import android.content.Context
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.util.Log
class Capture(val context: Context) : ImageReader.OnImageAvailableListener {
companion object {
private val TAG = Capture::class.qualifiedName
}
private var display: VirtualDisplay? = null
private var onCaptureListener: ((Bitmap) -> Unit)? = null
fun run(mediaProjection: MediaProjection, onCaptureListener: (Bitmap) -> Unit) {
this.onCaptureListener = onCaptureListener
if (display == null) {
display = createDisplay(mediaProjection)
}
}
private fun createDisplay(mediaProjection: MediaProjection): VirtualDisplay {
context.resources.displayMetrics.run {
val maxImages = 2
val reader = ImageReader.newInstance(
widthPixels, heightPixels, PixelFormat.RGBA_8888, maxImages)
reader.setOnImageAvailableListener(this@Capture, null)
val display = mediaProjection.createVirtualDisplay(
"Capture Display", widthPixels, heightPixels, densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
reader.surface, null, null)
Log.d(TAG, "createVirtualDisplay")
return display
}
}
override fun onImageAvailable(reader: ImageReader) {
if (display != null) {
onCaptureListener?.invoke(captureImage(reader))
}
}
private fun captureImage(reader: ImageReader): Bitmap {
Log.d(TAG, "captureImage")
val image = reader.acquireLatestImage()
context.resources.displayMetrics.run {
image.planes[0].run {
val bitmap = Bitmap.createBitmap(
rowStride / pixelStride, heightPixels, Bitmap.Config.ARGB_8888)
bitmap.copyPixelsFromBuffer(buffer)
image.close()
return bitmap
}
}
}
fun stop() {
display?.release()
display = null
onCaptureListener = null
}
}
package xxx
import android.app.Activity
import android.app.Service
import android.content.Intent
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Bundle
import android.widget.Toast
class CaptureActivity : Activity() {
companion object {
private const val REQUEST_CAPTURE = 1
var projection: MediaProjection? = null
}
private lateinit var mediaProjectionManager: MediaProjectionManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mediaProjectionManager = getSystemService(Service.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CAPTURE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CAPTURE) {
if (resultCode == RESULT_OK) {
projection = mediaProjectionManager.getMediaProjection(resultCode, data)
val intent = Intent(this, CaptureService::class.java)
.setAction(CaptureService.ACTION_ENABLE_CAPTURE)
startService(intent)
} else {
projection = null
Toast.makeText(this, R.string.capture_error, Toast.LENGTH_SHORT).show()
}
}
finish()
}
}
package xxx
import android.app.Notification
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log
import java.util.*
import xxx.Capture
class CaptureService : Service() {
companion object {
private val TAG = CaptureService::class.qualifiedName
val ACTION_ENABLE_CAPTURE = "enable_capture"
}
private val notificationId = Random().nextInt()
private val capture = Capture(this)
// ... snip ...
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent != null) {
when (intent.action) {
ACTION_ENABLE_CAPTURE -> onEnableCapture()
}
}
return Service.START_STICKY
}
private fun enableCapture() {
if (CaptureActivity.projection == null) {
Log.d(TAG, "startActivity(CaptureActivity)")
val intent = Intent(this, CaptureActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
} else {
onEnableCapture()
}
}
private fun onEnableCapture() {
CaptureActivity.projection?.run {
capture.run(this) {
capture.stop()
// save bitmap
}
}
}
private fun disableCapture() {
capture.stop()
CaptureActivity.projection = null
}
override fun onDestroy() {
super.onDestroy()
disableCapture()
}
}
@sshikhar1234

This comment has been minimized.

Copy link

commented Sep 26, 2017

Where is the densityDpi ????

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.