问题描述
我正在尝试用 3 根手指向下滑动截取屏幕截图。我成功地在 3 根手指向下滑动的活动中截取屏幕截图,但我无法在应用程序外截取屏幕截图,即我想听触摸事件/应用程序启动媒体投影时的手势.. 触摸/滑动/手势在应用程序内工作正常并且还可以截取屏幕截图.. 这是我目前使用的代码, ScreenCaptureService.java
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Notification;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
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.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.view.display;
import android.view.OrientationEventListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Objects;
import androidx.core.util.Pair;
public class ScreenCaptureService extends Service {
private static final String TAG = "ScreenCaptureService";
private static final String RESULT_CODE = "RESULT_CODE";
private static final String DATA = "DATA";
private static final String ACTION = "ACTION";
private static final String START = "START";
private static final String STOP = "STOP";
private static final String SCREENCAP_NAME = "screencap";
private static int IMAGES_PRODUCED;
private MediaProjection mMediaProjection;
private String mStoreDir;
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;
public static Intent getStartIntent(Context context,int resultCode,Intent data) {
Intent intent = new Intent(context,ScreenCaptureService.class);
intent.putExtra(ACTION,START);
intent.putExtra(RESULT_CODE,resultCode);
intent.putExtra(DATA,data);
return intent;
}
public static Intent getStopIntent(Context context) {
Intent intent = new Intent(context,STOP);
return intent;
}
private static boolean isstartCommand(Intent intent) {
return intent.hasExtra(RESULT_CODE) && intent.hasExtra(DATA)
&& intent.hasExtra(ACTION) && Objects.equals(intent.getStringExtra(ACTION),START);
}
private static boolean isstopCommand(Intent intent) {
return intent.hasExtra(ACTION) && Objects.equals(intent.getStringExtra(ACTION),STOP);
}
private static int getVirtualdisplayFlags() {
return displayManager.VIRTUAL_disPLAY_FLAG_OWN_CONTENT_ONLY | displayManager.VIRTUAL_disPLAY_FLAG_PUBLIC;
}
private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
@Override
public void onImageAvailable(ImageReader reader) {
FileOutputStream fos = null;
Bitmap bitmap = null;
try (Image 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(mStoreDir + "/myscreen_" + IMAGES_PRODUCED + ".png");
bitmap.compress(Bitmap.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();
}
}
}
}
private class OrientationChangeCallback extends OrientationEventListener {
OrientationChangeCallback(Context context) {
super(context);
}
@Override
public void onorientationChanged(int orientation) {
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(TAG,"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();
mMediaProjection.unregisterCallback(MediaProjectionStopCallback.this);
}
});
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// create store dir
File externalFilesDir = getExternalFilesDir(null);
if (externalFilesDir != null) {
mStoreDir = externalFilesDir.getAbsolutePath() + "/screenshots/";
File storeDirectory = new File(mStoreDir);
if (!storeDirectory.exists()) {
boolean success = storeDirectory.mkdirs();
if (!success) {
Log.e(TAG,"Failed to create file storage directory.");
stopSelf();
}
}
} else {
Log.e(TAG,"Failed to create file storage directory,getExternalFilesDir is null.");
stopSelf();
}
// start capture handling thread
new Thread() {
@Override
public void run() {
Looper.prepare();
mHandler = new Handler();
Looper.loop();
}
}.start();
}
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
if (isstartCommand(intent)) {
// create notification
Pair<Integer,Notification> notification = NotificationUtils.getNotification(this);
startForeground(notification.first,notification.second);
// start projection
int resultCode = intent.getIntExtra(RESULT_CODE,Activity.RESULT_CANCELED);
Intent data = intent.getParcelableExtra(DATA);
startProjection(resultCode,data);
} else if (isstopCommand(intent)) {
stopProjection();
stopSelf();
} else {
stopSelf();
}
return START_NOT_STICKY;
}
private void startProjection(int resultCode,Intent data) {
mediaprojectionmanager mpManager =
(mediaprojectionmanager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mMediaProjection == null) {
mMediaProjection = mpManager.getMediaProjection(resultCode,data);
if (mMediaProjection != null) {
// display metrics
mDensity = Resources.getSystem().getdisplayMetrics().densityDpi;
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mdisplay = windowManager.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
mMediaProjection.registerCallback(new MediaProjectionStopCallback(),mHandler);
}
}
}
private void stopProjection() {
if (mHandler != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mMediaProjection != null) {
mMediaProjection.stop();
}
}
});
}
}
@SuppressLint("WrongConstant")
private void createVirtualdisplay() {
// get width and height
mWidth = Resources.getSystem().getdisplayMetrics().widthPixels;
mHeight = Resources.getSystem().getdisplayMetrics().heightPixels;
// start capture reader
mImageReader = ImageReader.newInstance(mWidth,PixelFormat.RGBA_8888,2);
mVirtualdisplay = mMediaProjection.createVirtualdisplay(SCREENCAP_NAME,mWidth,mDensity,getVirtualdisplayFlags(),mImageReader.getSurface(),null,mHandler);
mImageReader.setonImageAvailableListener(new ImageAvailableListener(),mHandler);
startListen(mImageReader);
}
public void startListen(ImageReader virtualdisplay)
{
Toast.makeText(this,"listen",Toast.LENGTH_SHORT).show();
SimpleFingerGestures sfg = new SimpleFingerGestures();
sfg.setDebug(true);
sfg.setConsumetouchEvents(true);
sfg.setonFingerGestureListener(new SimpleFingerGestures.OnFingerGestureListener() {
@Override
public boolean onSwipeUp(int fingers,long gestureDuration,double gesturedistance) {
//grtv.setText("You swiped " + fingers + " fingers up " + gestureDuration + " milliseconds " + gesturedistance + " pixels far");
return false;
}
@Override
public boolean onSwipeDown(int fingers,double gesturedistance) {
//grtv.setText("You swiped " + fingers + " fingers down " + gestureDuration + " milliseconds " + gesturedistance + " pixels far");
if (fingers==3)
{
Toast.makeText(ScreenCaptureService.this,"3 fingers",Toast.LENGTH_SHORT).show();
//screenshot.takeScreenshot();
// savetogallery();
}
return false;
}
@Override
public boolean onSwipeLeft(int fingers,double gesturedistance) {
//grtv.setText("You swiped " + fingers + " fingers left " + gestureDuration + " milliseconds " + gesturedistance + " pixels far");
return false;
}
@Override
public boolean onSwipeRight(int fingers,double gesturedistance) {
//grtv.setText("You swiped " + fingers + " fingers right " + gestureDuration + " milliseconds " + gesturedistance + " pixels far");
return false;
}
@Override
public boolean onPinch(int fingers,double gesturedistance) {
//grtv.setText("You pinched " + fingers + " fingers " + gestureDuration + " milliseconds " + gesturedistance + " pixels far");
return false;
}
@Override
public boolean onUnpinch(int fingers,double gesturedistance) {
//grtv.setText("You unpinched " + fingers + "fingers" + gestureDuration + " milliseconds " + gesturedistance + " pixels far");
return false;
}
@Override
public boolean onDoubleTap(int fingers) {
//grtv.setText("You double tapped");
return false;
}
});
virtualdisplay.setonTouchListener(sfg);//here want to set on touch listener but doesn't works
}
}
如何在 startListen() 函数中监听触摸事件?我应该在哪里调用这个函数?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)