问题描述
我正在关注以下示例:
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);
}
}
在Android ver >=21
上截屏.
该示例的问题在于,一旦我截取了屏幕截图,top
,right
& Image
的bottom
.
The problem with that example is that once I take the screenshot , there are black edges on the top
, right
& bottom
of the Image
.
我看不到问题出在哪里,因为同时给VirtualDisplay
和Bitmap
的Width
和Height
是正确的,我在这里缺少什么?
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.
这篇关于截取的屏幕截图周围的黑色边缘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!