java 截屏 锁屏黑色,截取的屏幕截图周围的黑色边缘

I'm following this example :

package com.mtsahakis.mediaprojectiondemo;

import android.app.Activity;

import android.content.Context;

import android.content.Intent;

import android.graphics.Bitmap;

import android.graphics.Bitmap.CompressFormat;

import android.graphics.PixelFormat;

import android.graphics.Point;

import android.hardware.display.DisplayManager;

import android.hardware.display.VirtualDisplay;

import android.media.Image;

import android.media.ImageReader;

import android.media.projection.MediaProjection;

import android.media.projection.MediaProjectionManager;

import android.os.Bundle;

import android.os.Handler;

import android.os.Looper;

import android.util.DisplayMetrics;

import android.util.Log;

import android.view.Display;

import android.view.OrientationEventListener;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.nio.ByteBuffer;

public class ScreenCaptureImageActivity extends Activity {

private static final String TAG = ScreenCaptureImageActivity.class.getName();

private static final int REQUEST_CODE = 100;

private static String STORE_DIRECTORY;

private static int IMAGES_PRODUCED;

private static final String SCREENCAP_NAME = "screencap";

private static final int VIRTUAL_DISPLAY_FLAGS = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;

private static MediaProjection sMediaProjection;

private MediaProjectionManager mProjectionManager;

private ImageReader mImageReader;

private Handler mHandler;

private Display mDisplay;

private VirtualDisplay mVirtualDisplay;

private int mDensity;

private int mWidth;

private int mHeight;

private int mRotation;

private OrientationChangeCallback mOrientationChangeCallback;

private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {

@Override

public void onImageAvailable(ImageReader reader) {

Image image = null;

FileOutputStream fos = null;

Bitmap bitmap = null;

try {

image = mImageReader.acquireLatestImage();

if (image != null) {

Image.Plane[] planes = image.getPlanes();

ByteBuffer buffer = planes[0].getBuffer();

int pixelStride = planes[0].getPixelStride();

int rowStride = planes[0].getRowStride();

int rowPadding = rowStride - pixelStride * mWidth;

// create bitmap

bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);

bitmap.copyPixelsFromBuffer(buffer);

// write bitmap to a file

fos = new FileOutputStream(STORE_DIRECTORY + "/myscreen_" + IMAGES_PRODUCED + ".png");

bitmap.compress(CompressFormat.JPEG, 100, fos);

IMAGES_PRODUCED++;

Log.e(TAG, "captured image: " + IMAGES_PRODUCED);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if (fos!=null) {

try {

fos.close();

} catch (IOException ioe) {

ioe.printStackTrace();

}

}

if (bitmap!=null) {

bitmap.recycle();

}

if (image!=null) {

image.close();

}

}

}

}

private class OrientationChangeCallback extends OrientationEventListener {

public OrientationChangeCallback(Context context) {

super(context);

}

@Override

public void onOrientationChanged(int orientation) {

synchronized (this) {

final int rotation = mDisplay.getRotation();

if (rotation != mRotation) {

mRotation = rotation;

try {

// clean up

if(mVirtualDisplay != null) mVirtualDisplay.release();

if(mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);

// re-create virtual display depending on device width / height

createVirtualDisplay();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

}

private class MediaProjectionStopCallback extends MediaProjection.Callback {

@Override

public void onStop() {

Log.e("ScreenCapture", "stopping projection.");

mHandler.post(new Runnable() {

@Override

public void run() {

if(mVirtualDisplay != null) mVirtualDisplay.release();

if(mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);

if(mOrientationChangeCallback != null) mOrientationChangeCallback.disable();

sMediaProjection.unregisterCallback(MediaProjectionStopCallback.this);

}

});

}

}

/****************************************** Activity Lifecycle methods ************************/

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// call for the projection manager

mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);

// start projection

Button startButton = (Button)findViewById(R.id.startButton);

startButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

startProjection();

}

});

// stop projection

Button stopButton = (Button)findViewById(R.id.stopButton);

stopButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

stopProjection();

}

});

// start capture handling thread

new Thread() {

@Override

public void run() {

Looper.prepare();

mHandler = new Handler();

Looper.loop();

}

}.start();

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if (requestCode == REQUEST_CODE) {

sMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);

if (sMediaProjection != null) {

File externalFilesDir = getExternalFilesDir(null);

if (externalFilesDir != null) {

STORE_DIRECTORY = externalFilesDir.getAbsolutePath() + "/screenshots/";

File storeDirectory = new File(STORE_DIRECTORY);

if (!storeDirectory.exists()) {

boolean success = storeDirectory.mkdirs();

if (!success) {

Log.e(TAG, "failed to create file storage directory.");

return;

}

}

} else {

Log.e(TAG, "failed to create file storage directory, getExternalFilesDir is null.");

return;

}

// display metrics

DisplayMetrics metrics = getResources().getDisplayMetrics();

mDensity = metrics.densityDpi;

mDisplay = getWindowManager().getDefaultDisplay();

// create virtual display depending on device width / height

createVirtualDisplay();

// register orientation change callback

mOrientationChangeCallback = new OrientationChangeCallback(this);

if (mOrientationChangeCallback.canDetectOrientation()) {

mOrientationChangeCallback.enable();

}

// register media projection stop callback

sMediaProjection.registerCallback(new MediaProjectionStopCallback(), mHandler);

}

}

}

/****************************************** UI Widget Callbacks *******************************/

private void startProjection() {

startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);

}

private void stopProjection() {

mHandler.post(new Runnable() {

@Override

public void run() {

if (sMediaProjection != null) {

sMediaProjection.stop();

}

}

});

}

/****************************************** Factoring Virtual Display creation ****************/

private void createVirtualDisplay() {

// get width and height

Point size = new Point();

mDisplay.getSize(size);

mWidth = size.x;

mHeight = size.y;

// start capture reader

mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);

mVirtualDisplay = sMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight, mDensity, VIRTUAL_DISPLAY_FLAGS, mImageReader.getSurface(), null, mHandler);

mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler);

}

}

to take a screenshot on Android ver >=21.

The problem with that example is that once I take the screenshot , there are black edges on the top , right & bottom of the Image.

I can't see where is the problem since the given Width and Height to both the VirtualDisplay and the Bitmap are correct, what I'm missing here?

解决方案

Problem is probably the size of the virtual display.

mDisplay.getSize(size);

may return something different than the real size of the device if your device have a virtual navigation bar (usually swipe from bottom of the screen to display it).

mDisplay.getRealSize(size);

will probably fix your problem with black edges.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值