如何使用MediaProjection

如何使用MediaProjection

本文介绍了如何使用MediaProjection API从后台服务类中获取屏幕快照?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在对该主题进行了大量研究之后,尽管我找到了一些答案,但我不明白MediaProjection API的工作原理.

After doing a lot of research on this topic, though I found a few answers, I could not understand how the MediaProjection API works.

我想从后台服务类中获取设备的屏幕截图.有可能做到这一点.我有一个MainActivity.java,它启动serviceIntent到另一个类,该类是服务(不是活动).因此,我想在此服务类中实现此API.请帮助我

I want to take a screenshot of the device from a background Service class. Is it possible to do it. I have one MainActivity.java which starts a serviceIntent to another class which is a service(not an activity). So I want to implement this API in this service class. Please help me

推荐答案

这是实现这一目标的棘手方法.

This is tricky way to achieve this.

首先,您需要创建透明的背景主题.

First of all you need to create transparent background theme like.

    <style name="transparentTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:background">#00000000</item> <!-- Or any transparency or color you need -->
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation</item>
        <item name="android:navigationBarColor" tools:ignore="NewApi">#00000000</item>
        <item name="android:statusBarColor" tools:ignore="NewApi">#00000000</item>
    </style>

现在您需要添加此主题,将此主题应用于清单文件中的ScreenShotActivity.

Now you need to add this apply this theme on your ScreenShotActivity in Manifest file.

  <activity
            android:name=".Activities.ScreenShotActivity"
            android:theme="@style/transparentTheme" />
        <activity

您的ScreenShotActivity类.

Your ScreenShotActivity Class.

public class ScreenShotActivity extends Activity {

    private static final int videoTime = 5000;
    private static final int REQUEST_CODE = 1000;
    private static final int REQUEST_PERMISSION = 1000;
    private static final SparseIntArray ORIENTATION = new SparseIntArray();
    private MediaProjectionManager mediaProjectionManager;
    private MediaProjection mediaProjection;
    private VirtualDisplay virtualDisplay;
    private ScreenShotActivity.MediaProjectionCallback mediaProjectionCallback;
    private MediaRecorder mediaRecorder;
    PostWebAPIData postWebAPIData;
    private int mScreenDensity;
    private static int DISPLAY_WIDTH = 720;
    private static int DISPLAY_HEIGHT = 1280;

    static {
        ORIENTATION.append(Surface.ROTATION_0, 90);
        ORIENTATION.append(Surface.ROTATION_90, 0);
        ORIENTATION.append(Surface.ROTATION_180, 270);
        ORIENTATION.append(Surface.ROTATION_270, 180);
    }

    private String screenShotUri = "";

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_shot);
        init();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void init() {
        //Screen tracking Code Started here..............................
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        mScreenDensity = metrics.densityDpi;
        postWebAPIData = new PostWebAPIData();
        DISPLAY_HEIGHT = metrics.heightPixels;
        DISPLAY_WIDTH = metrics.widthPixels;

        mediaRecorder = new MediaRecorder();
        mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        if (ContextCompat.checkSelfPermission(ScreenShotActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                + ContextCompat.checkSelfPermission(ScreenShotActivity.this, Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(ScreenShotActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
                    ActivityCompat.shouldShowRequestPermissionRationale(ScreenShotActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            } else {
                ActivityCompat.requestPermissions(ScreenShotActivity.this, new String[]{
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.RECORD_AUDIO
                }, REQUEST_PERMISSION);
            }
        } else {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    toogleScreenShare();
                }
            }, 500);
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void toogleScreenShare() {
        initRecorder();
        recordScreen();
    }


    public void getPathScreenShot(String filePath) {
        FFmpegMediaMetadataRetriever med = new FFmpegMediaMetadataRetriever();

        med.setDataSource(filePath);
        Bitmap bmp = med.getFrameAtTime(2 * 1000000, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
        String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + new StringBuilder("/screenshot").append(".bmp").toString();

        File myDir = new File(myPath);
        myDir.mkdirs();
        Random generator = new Random();
        int n = 10000;
        n = generator.nextInt(n);
        String fname = "Image-" + n + ".jpg";
        File file = new File(myDir, fname);
        Log.i(TAG, "" + myDir);
        if (myDir.exists())
            myDir.delete();
        try {
            FileOutputStream out = new FileOutputStream(myDir);
            bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        postScreenShot(myPath);
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void recordScreen() {
        if (mediaProjection == null) {
            startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
        } else {
            virtualDisplay = createVirtualDisplay();
            mediaRecorder.start();
            onBackPressed();
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mediaRecorder.stop();
                    mediaRecorder.reset();
                    stopRecordScreen();
                    destroyMediaProjection();
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            getPathScreenShot(screenShotUri);
                        }
                    }, 2000);
                }
            }, videoTime);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private VirtualDisplay createVirtualDisplay() {
        return mediaProjection.createVirtualDisplay("MainActivity", DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mediaRecorder.getSurface(), null, null);
    }

    private void initRecorder() {
        try {
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);

            screenShotUri = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + new StringBuilder("/screenshot").append(".mp4").toString();

            mediaRecorder.setOutputFile(screenShotUri);
            mediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mediaRecorder.setVideoEncodingBitRate(512 * 1000);
            mediaRecorder.setVideoFrameRate(5);

            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            int orientation = ORIENTATION.get(rotation + 90);
            mediaRecorder.setOrientationHint(orientation);
            mediaRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
            Log.d("ExceptionOccured", "" + e.getMessage());
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode != REQUEST_CODE) {
            stopService(new Intent(this, BackgroundService.class));
            startService(new Intent(this, BackgroundService.class));
            Toast.makeText(ScreenShotActivity.this, "Unknown Error", Toast.LENGTH_SHORT).show();
            Log.d("Livetracking", "ScreenShot" + requestCode + "  " + resultCode + " " + data);
            return;
        }
        if (resultCode != RESULT_OK) {
            stopService(new Intent(this, BackgroundService.class));
            startService(new Intent(this, BackgroundService.class));
            Toast.makeText(ScreenShotActivity.this, "Permission denied" + requestCode, Toast.LENGTH_SHORT).show();
            Log.d("Livetracking", "Screenshot" + requestCode + "  " + resultCode + " " + data);
            return;
        }
        Log.d("Livetracking", "Screenshot" + requestCode + "  " + resultCode + " " + data);

        mediaProjectionCallback = new ScreenShotActivity.MediaProjectionCallback();
        mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
        mediaProjection.registerCallback(mediaProjectionCallback, null);
        virtualDisplay = createVirtualDisplay();
        mediaRecorder.start();
        onBackPressed();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mediaRecorder.stop();
                mediaRecorder.reset();
                stopRecordScreen();
                destroyMediaProjection();
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        getPathScreenShot(screenShotUri);
                    }
                }, 2000);
            }
        }, videoTime);
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        if (am != null) {
            List<ActivityManager.AppTask> tasks = am.getAppTasks();
            if (tasks != null && tasks.size() > 0) {
                Log.d("RemovingApp", "recent");
                tasks.get(0).setExcludeFromRecents(true);
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private class MediaProjectionCallback extends MediaProjection.Callback {
        @Override
        public void onStop() {
            mediaRecorder.stop();
            mediaRecorder.reset();
            mediaProjection = null;
            stopRecordScreen();
            destroyMediaProjection();
            if (mediaProjection != null) {
                destroyMediaProjection();
            }
            super.onStop();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void stopRecordScreen() {
        if (virtualDisplay == null) {
            virtualDisplay.release();
            if (mediaProjection != null) {
                destroyMediaProjection();
            }
            return;

        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void destroyMediaProjection() {
        if (mediaProjection != null) {
            mediaProjection.unregisterCallback(mediaProjectionCallback);
            mediaProjection.stop();
            mediaProjection = null;
        }
    }
}

在您的清单文件中添加这些权限.

add these permissions in your Manifest file.

   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

现在神奇的开始是,您需要像这样从服务调用ScreenShotActivity.

Now the magic start here you need to call your ScreenShotActivity from your service like this.

      Intent dialogIntent = new Intent(BackgroundService.this, ScreenShotActivity.class);
      dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      startActivity(dialogIntent);

这篇关于如何使用MediaProjection API从后台服务类中获取屏幕快照?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 22:09