日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 实现全屏截图、剪裁图片、分享图片至其他应用进程功能(踩坑记录)

發布時間:2024/3/24 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 实现全屏截图、剪裁图片、分享图片至其他应用进程功能(踩坑记录) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android 實現全屏截圖、剪裁、分享功能

項目中需要用到 截圖分享 的功能,特此寫下查詢資料過程中的踩坑記錄。
android 26以上,google 官方文檔支持 PixelCopy 實現截圖效果
獲取虛擬導航欄的高度并剪裁圖片
?

1、全屏截圖

1.1 踩坑記錄

第一個坑:方法已被棄用

(先前實現的全屏截圖方法,已經在api28及以上棄用)

// View是全屏截圖 **已棄用**View getView = this.getWindow().getDecorView();getView.setDrawingCacheEnabled(true);getView.buildDrawingCache();Bitmap b1 = getView.getDrawingCache();

?

第二個坑:能實現全屏截圖,但是 MaterialCardView 圓角顯示失效

//獲取全屏截圖(包括狀態欄、標題欄和底部)val screenView = window.decorViewval bitmap = screenView.drawToBitmap()

?

1.2 正確截圖方式

經過查詢資料,終于找到了能正確顯示 MaterialCardView 圓角的截圖方式

val EVENT_SCREENSHOT = 22 //截圖事件private var mediaProjectionManager: MediaProjectionManager? = nullprivate var mediaProjection: MediaProjection? = nullprivate var image: Image? = nullprivate fun takeScreenShot() {mediaProjectionManager = application.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManagerstartActivityForResult(mediaProjectionManager!!.createScreenCaptureIntent(), EVENT_SCREENSHOT)}@SuppressLint("WrongConstant")override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)if(requestCode == EVENT_SCREENSHOT_LOCK ||requestCode == EVENT_SCREENSHOT_SHARE){val displayMetrics = resources.displayMetricsval width = displayMetrics.widthPixelsval height = displayMetrics.heightPixelsval mImageReader: ImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2)mediaProjection = mediaProjectionManager!!.getMediaProjection(resultCode, data!!)val virtualDisplay = mediaProjection!!.createVirtualDisplay("screen-mirror", width, height,displayMetrics.densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.surface, null, null)Handler(Looper.myLooper()!!).postDelayed({try {image = mImageReader.acquireLatestImage()if (image != null) {val planes: Array<Image.Plane> = image!!.planesval buffer: ByteBuffer = planes[0].bufferval width: Int = image!!.widthval height: Int = image!!.heightval pixelStride: Int = planes[0].pixelStrideval rowStride: Int = planes[0].rowStrideval rowPadding = rowStride - pixelStride * widthvar bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888)bitmap!!.copyPixelsFromBuffer(buffer)bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.width, bitmap.height, false)if (bitmap != null) {if (requestCode == EVENT_SCREENSHOT_SHARE) {cutScreenShotToShare(bitmap)}else if(requestCode == EVENT_SCREENSHOT_LOCK){cutScreenShotToLock(bitmap)}}bitmap.recycle()}} catch (e: Exception) {e.printStackTrace()} finally {image?.close()mImageReader.close()virtualDisplay?.release()//必須代碼,否則出現BufferQueueProducer: [ImageReader] dequeueBuffer: BufferQueue has been abandonedmImageReader.setOnImageAvailableListener(null, null)mediaProjection!!.stop()}}, 100)}}

?
android 26以上,google 官方文檔支持 PixelCopy 實現截圖效果

val view = window.decorViewif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//獲取layout的位置val location = IntArray(2)view.getLocationInWindow(location)//準備一個bitmap對象,用來將copy出來的區域繪制到此對象中val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888, true)PixelCopy.request(this.window,Rect(location[0], location[1], location[0] + view.width, location[1] + view.height),bitmap, { copyResult ->//如果成功if (copyResult == PixelCopy.SUCCESS) {cutScreenShotToShare(bitmap)}else{Toast.makeText(this, "截圖出現錯誤", Toast.LENGTH_SHORT).show()}}, Handler(Looper.getMainLooper()))}else{takeScreenShotToShare()}

?

2、剪裁圖片 (截去狀態欄和標題欄)

private fun cutScreenShot(bitmap: Bitmap) {val screenView = window.decorView//獲取狀態欄高度val frame = Rect()screenView.getWindowVisibleDisplayFrame(frame)val statusbarHeight = frame.top//獲取標題欄高度(toolbar里有menu,需要截掉)val typeValue = TypedValue()theme.resolveAttribute(android.R.attr.actionBarSize, typeValue, true)val toolbarHeight = TypedValue.complexToDimensionPixelSize(typeValue.data, resources.displayMetrics)//獲取屏幕長寬val width = screenView.widthval height = screenView.height//去掉狀態欄和標題欄val screenShot = bitmap.let { Bitmap.createBitmap(it, 0, toolbarHeight + statusbarHeight, width, height - toolbarHeight - statusbarHeight - getVirtualBarHeight()) }if (screenShot != null) {ShotShareUtil(this).shotShare(this, screenShot)}}

獲取虛擬導航欄的高度

//獲取虛擬導航欄的高度private fun getVirtualBarHeight():Int{var height = 0val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {display} else {val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManagerwindowManager.defaultDisplay}val dm = DisplayMetrics()try {val c = Class.forName("android.view.Display")val method = c.getMethod("getRealMetrics", DisplayMetrics::class.java)method.invoke(display, dm)val displayMetrics = resources.displayMetricsheight = dm.heightPixels - displayMetrics.heightPixels} catch (e:Exception) {e.printStackTrace()}return height}

3、實現分享功能

import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.net.Uri import android.os.Build import androidx.core.content.FileProvider import java.io.File import java.io.FileNotFoundException import java.io.FileOutputStream import java.io.IOExceptionclass ShotShareUtil(context: Context){private val BITMAP_DIR = "${context.getExternalFilesDir(null)?.absolutePath}/BitmapCache"private lateinit var bitmapName:Stringprivate lateinit var bitmapPath:Stringfun shotShare(context: Context,bitmap: Bitmap){bitmapName = "${System.currentTimeMillis()}"bitmapPath = "$BITMAP_DIR/$bitmapName.png"SaveBitmap(bitmap)ShareImage(context, bitmapPath)}private fun ShareImage(context: Context, imagePath: String) {val uri: Urival file = File(imagePath)if (context == null || file == null) {throw NullPointerException()}uri = if (Build.VERSION.SDK_INT >= 24) {FileProvider.getUriForFile(context, "com.example.customlockscreen.fileprovider", file)} else {Uri.fromFile(file)}var intent = Intent(Intent.ACTION_SEND)intent.type = "image/*"intent.putExtra(Intent.EXTRA_STREAM, uri) // 分享的內容intent.putExtra(Intent.EXTRA_SUBJECT,"分享")intent = Intent.createChooser(intent, "分享到:")context.startActivity(intent)}private fun SaveBitmap(bitmap: Bitmap) {try { // 獲取SDCard指定目錄下val sdCardDir = BITMAP_DIRval dirFile = File(sdCardDir) //目錄轉化成文件夾if (!dirFile.exists()) { //如果不存在,那就建立這個文件夾dirFile.mkdirs()}val file = File(sdCardDir, "$bitmapName.png") // 在該目錄下創建圖片if (file.exists()) {file.delete()}file.createNewFile() //創建文件val out = FileOutputStream(file)bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)out.flush()out.close()} catch (e: FileNotFoundException) {e.printStackTrace()} catch (e: IOException) {e.printStackTrace()}}}

總結

以上是生活随笔為你收集整理的Android 实现全屏截图、剪裁图片、分享图片至其他应用进程功能(踩坑记录)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。