问题是我想编写一个应用程序来捕获音频并使用前台服务在后台处理它,从 MainActivity 上的一个按钮开始,它是 here。 我想添加截屏功能,我找到了这个 question,通过它我找到了示例 here。这个模板使用 mediaproject 来做,每当我按下图标启动它我的 MainActivity 没有显示应用程序将在后台开始运行,对吧。 有没有其他方法可以从MainActivity上的按钮开始截图(或者如何连拍屏幕),如果可能我可以完全连续截图。
PS:我搜索了但仍然不知道在哪里做可能是因为使用了onActivityResult
,
这是使用 mediaproject 捕获屏幕的代码:
MainActivity.java
package com.commonsware.android.andshooter;
import android.app.Activity;
import android.content.Intent;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
public class MainActivity extends Activity {
private static final int REQUEST_SCREENSHOT=59706;
private MediaProjectionManager mgr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mgr=(MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
startActivityForResult(mgr.createScreenCaptureIntent(),
REQUEST_SCREENSHOT);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==REQUEST_SCREENSHOT) {
if (resultCode==RESULT_OK) {
Intent i=
new Intent(this, ScreenshotService.class)
.putExtra(ScreenshotService.EXTRA_RESULT_CODE, resultCode)
.putExtra(ScreenshotService.EXTRA_RESULT_INTENT, data);
startService(i);
}
}
finish();
}
}
ImageTransmogrifier.java
package com.commonsware.android.andshooter;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.media.Image;
import android.media.ImageReader;
import android.view.Display;
import android.view.Surface;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
public class ImageTransmogrifier implements ImageReader.OnImageAvailableListener {
private final int width;
private final int height;
private final ImageReader imageReader;
private final ScreenshotService svc;
private Bitmap latestBitmap=null;
ImageTransmogrifier(ScreenshotService svc) {
this.svc=svc;
Display display=svc.getWindowManager().getDefaultDisplay();
Point size=new Point();
display.getRealSize(size);
int width=size.x;
int height=size.y;
while (width*height > (2<<19)) {
width=width>>1;
height=height>>1;
}
this.width=width;
this.height=height;
imageReader=ImageReader.newInstance(width, height,
PixelFormat.RGBA_8888, 2);
imageReader.setOnImageAvailableListener(this, svc.getHandler());
}
@Override
public void onImageAvailable(ImageReader reader) {
final Image image=imageReader.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 * width;
int bitmapWidth=width + rowPadding / pixelStride;
if (latestBitmap == null ||
latestBitmap.getWidth() != bitmapWidth ||
latestBitmap.getHeight() != height) {
if (latestBitmap != null) {
latestBitmap.recycle();
}
latestBitmap=Bitmap.createBitmap(bitmapWidth,
height, Bitmap.Config.ARGB_8888);
}
latestBitmap.copyPixelsFromBuffer(buffer);
image.close();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
Bitmap cropped=Bitmap.createBitmap(latestBitmap, 0, 0,
width, height);
cropped.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] newPng=baos.toByteArray();
svc.processImage(newPng);
}
}
Surface getSurface() {
return(imageReader.getSurface());
}
int getWidth() {
return(width);
}
int getHeight() {
return(height);
}
void close() {
imageReader.close();
}
}
ScreenshotService.java
package com.commonsware.android.andshooter;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.AudioManager;
import android.media.MediaScannerConnection;
import android.media.ToneGenerator;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.WindowManager;
import java.io.File;
import java.io.FileOutputStream;
public class ScreenshotService extends Service {
private static final String CHANNEL_WHATEVER="channel_whatever";
private static final int NOTIFY_ID=9906;
static final String EXTRA_RESULT_CODE="resultCode";
static final String EXTRA_RESULT_INTENT="resultIntent";
static final String ACTION_RECORD=
BuildConfig.APPLICATION_ID+".RECORD";
static final String ACTION_SHUTDOWN=
BuildConfig.APPLICATION_ID+".SHUTDOWN";
static final int VIRT_DISPLAY_FLAGS=
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
private MediaProjection projection;
private VirtualDisplay vdisplay;
final private HandlerThread handlerThread=
new HandlerThread(getClass().getSimpleName(),
android.os.Process.THREAD_PRIORITY_BACKGROUND);
private Handler handler;
private MediaProjectionManager mgr;
private WindowManager wmgr;
private ImageTransmogrifier it;
private int resultCode;
private Intent resultData;
final private ToneGenerator beeper=
new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
@Override
public void onCreate() {
super.onCreate();
mgr=(MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
wmgr=(WindowManager)getSystemService(WINDOW_SERVICE);
handlerThread.start();
handler=new Handler(handlerThread.getLooper());
}
@Override
public int onStartCommand(Intent i, int flags, int startId) {
if (i.getAction()==null) {
resultCode=i.getIntExtra(EXTRA_RESULT_CODE, 1337);
resultData=i.getParcelableExtra(EXTRA_RESULT_INTENT);
foregroundify();
}
else if (ACTION_RECORD.equals(i.getAction())) {
if (resultData!=null) {
startCapture();
}
else {
Intent ui=
new Intent(this, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(ui);
}
}
else if (ACTION_SHUTDOWN.equals(i.getAction())) {
beeper.startTone(ToneGenerator.TONE_PROP_NACK);
stopForeground(true);
stopSelf();
}
return(START_NOT_STICKY);
}
@Override
public void onDestroy() {
stopCapture();
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
throw new IllegalStateException("Binding not supported. Go away.");
}
WindowManager getWindowManager() {
return(wmgr);
}
Handler getHandler() {
return(handler);
}
void processImage(final byte[] png) {
new Thread() {
@Override
public void run() {
File output=new File(getExternalFilesDir(null),
"screenshot.png");
try {
FileOutputStream fos=new FileOutputStream(output);
fos.write(png);
fos.flush();
fos.getFD().sync();
fos.close();
MediaScannerConnection.scanFile(ScreenshotService.this,
new String[] {output.getAbsolutePath()},
new String[] {"image/png"},
null);
}
catch (Exception e) {
Log.e(getClass().getSimpleName(), "Exception writing out screenshot", e);
}
}
}.start();
beeper.startTone(ToneGenerator.TONE_PROP_ACK);
stopCapture();
}
private void stopCapture() {
if (projection!=null) {
projection.stop();
vdisplay.release();
projection=null;
}
}
private void startCapture() {
projection=mgr.getMediaProjection(resultCode, resultData);
it=new ImageTransmogrifier(this);
MediaProjection.Callback cb=new MediaProjection.Callback() {
@Override
public void onStop() {
vdisplay.release();
}
};
vdisplay=projection.createVirtualDisplay("andshooter",
it.getWidth(), it.getHeight(),
getResources().getDisplayMetrics().densityDpi,
VIRT_DISPLAY_FLAGS, it.getSurface(), null, handler);
projection.registerCallback(cb, handler);
}
private void foregroundify() {
NotificationManager mgr=
(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O &&
mgr.getNotificationChannel(CHANNEL_WHATEVER)==null) {
mgr.createNotificationChannel(new NotificationChannel(CHANNEL_WHATEVER,
"Whatever", NotificationManager.IMPORTANCE_DEFAULT));
}
NotificationCompat.Builder b=
new NotificationCompat.Builder(this, CHANNEL_WHATEVER);
b.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL);
b.setContentTitle(getString(R.string.app_name))
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker(getString(R.string.app_name));
b.addAction(R.drawable.ic_record_white_24dp,
getString(R.string.notify_record),
buildPendingIntent(ACTION_RECORD));
b.addAction(R.drawable.ic_eject_white_24dp,
getString(R.string.notify_shutdown),
buildPendingIntent(ACTION_SHUTDOWN));
startForeground(NOTIFY_ID, b.build());
}
private PendingIntent buildPendingIntent(String action) {
Intent i=new Intent(this, getClass());
i.setAction(action);
return(PendingIntent.getService(this, 0, i, 0));
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.commonsware.android.andshooter"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
<activity
android:name=".MainActivity"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".ScreenshotService"
android:exported="true" />
</application>
</manifest>
在我的应用程序中,我只是简单地复制 ScreenshotService ImageTransmogrifier 文件,然后从 MainActivity 运行它,如上所述。