美文网首页
Android 截图最新方案

Android 截图最新方案

作者: Taurus_z | 来源:发表于2023-02-26 19:06 被阅读0次

    使用方式

    import android.content.Context;
    import android.content.Intent;
    import android.media.projection.MediaProjectionManager;
    import android.os.Bundle;
    import android.util.Log;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class ShotActivity extends AppCompatActivity {
        private static final String TAG = ShotActivity.class.getSimpleName();
    
        public static final int REQUEST_MEDIA_PROJECTION = 0x2304;
        private Intent mMediaServiceIntent;
        private String savedPath;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_shot);
            if (mMediaServiceIntent == null) {
                mMediaServiceIntent = new Intent(this, MediaService.class);
            }
            startService(mMediaServiceIntent);
            savedPath = this.getExternalFilesDir("screenshot").getAbsoluteFile() + "/" + System.currentTimeMillis() + ".png";
            findViewById(R.id.shot).setOnClickListener(v -> {
                requestScreenShotPermission();
            });
        }
    
        public void requestScreenShotPermission() {
            MediaProjectionManager mediaMgr = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
            startActivityForResult(mediaMgr.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
        }
    
        @Override
        protected void onActivityResult(int requestCode, final int resultCode, final Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == REQUEST_MEDIA_PROJECTION && resultCode == RESULT_OK && data != null) {
                getWindow().getDecorView().postDelayed(() -> {
                    ShootUtil shootUtil = new ShootUtil(ShotActivity.this, resultCode, data);
                    shootUtil.startScreenShot(savedPath, new ShootUtil.OnShotListener() {
                        @Override
                        public void onFinish(String path) {
                            Log.i(TAG, "onFinish, path = " + path);
                        }
    
                        @Override
                        public void onError() {
                            Log.e(TAG, "onError, ");
                        }
                    });
                }, 100L);
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (mMediaServiceIntent != null) {
                stopService(mMediaServiceIntent);
                mMediaServiceIntent = null;
            }
        }
    }
    

    ShootUtil.java 截图工具类

    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.AsyncTask;
    import android.os.Handler;
    import android.text.TextUtils;
    import android.util.DisplayMetrics;
    import android.view.Display;
    import android.view.WindowManager;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.ref.SoftReference;
    import java.nio.ByteBuffer;
    
    public class ShootUtil {
        private static final String TAG = ShootUtil.class.getSimpleName();
        public static boolean hasPermission;
        private final SoftReference<Context> mRefContext;
        private final ImageReader mImageReader;
        private final MediaProjection mMediaProjection;
        private VirtualDisplay mVirtualDisplay;
        private OnShotListener mOnShotListener;
        private final int mHeight;
        private final int mWidth;
        private String mLocalUrl = "";
    
        private String getSavedPath() {
            if (TextUtils.isEmpty(mLocalUrl)) {
                mLocalUrl = getContext().getExternalFilesDir("screenshot").getAbsoluteFile() + "/" + System.currentTimeMillis() + ".png";
            }
            return mLocalUrl;
        }
    
    
        public ShootUtil(Context context, int reqCode, Intent data) {
            mRefContext = new SoftReference<>(context);
            mMediaProjection = getMediaProjectionManager().getMediaProjection(reqCode, data);
            WindowManager window = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display mDisplay = window.getDefaultDisplay();
            DisplayMetrics metrics = new DisplayMetrics();
            mDisplay.getRealMetrics(metrics);
            mWidth = metrics.widthPixels;//size.x;
            mHeight = metrics.heightPixels;//size.y;
            mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 1);
        }
    
    
        private void virtualDisplay() {
            mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror", mWidth, mHeight, Resources.getSystem().getDisplayMetrics().densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);
        }
    
        public void startScreenShot(String savedPath, OnShotListener onShotListener) {
            mLocalUrl = savedPath;
            startScreenShot(onShotListener);
        }
    
        public void startScreenShot(OnShotListener onShotListener) {
            hasPermission = true;
            mOnShotListener = onShotListener;
            virtualDisplay();
            Handler handler = new Handler();
            handler.postDelayed(() -> {
                Image image = mImageReader.acquireLatestImage();
                new SaveTask().doInBackground(image);
            }, 300);
        }
    
        public class SaveTask extends AsyncTask<Image, Void, Bitmap> {
            @Override
            protected Bitmap doInBackground(Image... params) {
                if (params == null || params.length < 1 || params[0] == null) {
                    return null;
                }
                Image image = params[0];
                int width = image.getWidth();
                int height = image.getHeight();
                final Image.Plane[] planes = image.getPlanes();
                final ByteBuffer buffer = planes[0].getBuffer();
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * width;
                Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
                bitmap.copyPixelsFromBuffer(buffer);
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
                image.close();
                File fileImage;
                if (bitmap != null) {
                    try {
                        fileImage = new File(getSavedPath());
                        if (!fileImage.exists()) {
                            fileImage.createNewFile();
                        }
                        FileOutputStream out = new FileOutputStream(fileImage);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        if (mOnShotListener != null) mOnShotListener.onError();
                        release();
                        return null;
                    }
                }
                if (bitmap != null && !bitmap.isRecycled()) {
                    bitmap.recycle();
                }
                if (mVirtualDisplay != null) {
                    mVirtualDisplay.release();
                }
                if (mMediaProjection != null) {
                    mMediaProjection.stop();
                }
    
                if (mOnShotListener != null) {
                    mOnShotListener.onFinish(getSavedPath());
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(Bitmap bitmap) {
                super.onPostExecute(bitmap);
            }
        }
    
        public void release() {
            if (mVirtualDisplay != null) {
                mVirtualDisplay.release();
            }
            if (mMediaProjection != null) {
                mMediaProjection.stop();
            }
        }
    
    
        private MediaProjectionManager getMediaProjectionManager() {
            return (MediaProjectionManager) getContext().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        }
    
        private Context getContext() {
            return mRefContext.get();
        }
    
        public interface OnShotListener {
            void onFinish(String path);
    
            void onError();
        }
    }
    

    MediaService.java 前台服务

    import android.app.NotificationChannel;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.BitmapFactory;
    import android.os.Build;
    import android.os.IBinder;
    
    import androidx.core.app.NotificationCompat;
    
    public class MediaService extends Service {
        private final String NOTIFICATION_CHANNEL_ID = "com.tencent.trtc.apiexample.MediaService";
        private final String NOTIFICATION_CHANNEL_NAME = "com.tencent.trtc.apiexample.channel_name";
        private final String NOTIFICATION_CHANNEL_DESC = "com.tencent.trtc.apiexample.channel_desc";
    
        public MediaService() {
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            startNotification();
        }
    
        public void startNotification() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                Intent notificationIntent = new Intent(this, MediaService.class);
                PendingIntent pendingIntent;
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
                    pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
                } else {
                    pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT);
                }
                NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground))
                        .setSmallIcon(R.drawable.ic_launcher_foreground)
                        .setContentTitle("Starting Service")
                        .setContentText("Starting monitoring service")
                        .setContentIntent(pendingIntent);
                Notification notification = notificationBuilder.build();
                NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
                channel.setDescription(NOTIFICATION_CHANNEL_DESC);
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.createNotificationChannel(channel);
                startForeground(1, notification); //必须使用此方法显示通知,不能使用notificationManager.notify,否则还是会报上面的错误
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            throw new UnsupportedOperationException("Not yet implemented");
        }
    }
    

    AndroidManifest.xml 文件添加 service

        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    
         <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:requestLegacyExternalStorage="true"
            android:supportsRtl="true">
            
            ...
            
            <service
                android:name=".MediaService"
                android:enabled="true"
                android:exported="true"
                android:foregroundServiceType="mediaProjection" />
        </application>
    

    相关文章

      网友评论

          本文标题:Android 截图最新方案

          本文链接:https://www.haomeiwen.com/subject/beecldtx.html