http://blog.csdn.net/wds1181977/article/details/52174840
Mediaprojection Introduction
The mediaprojection can be used to capture the screen, specifically capturing the current screen and recording the screen video. Mediaprojection is managed and acquired by Mediaprojectionmanager.
Use steps
First get the Mediaprojectionmanager, and the same as the other manager through Context.getsystemservice () incoming parameters Media_projection_service get the instance.
The call to Mediaprojectionmanager.createscreencaptureintent () pops up dialog asks the user whether to authorize the capture screen and overwrite Onactivityresult () to obtain the authorization result.
If the authorization succeeds, obtain the Mediaprojection instance through mediaprojectionmanager.getmediaprojection (int resultcode, Intent resultdata), Via Mediaprojection.createvirtualdisplay (String name, int width, int height, int dpi, int flags, surface surface, Virtualdis Play. Callback Callback, Handler Handler) creates a Virtualdisplay instance. In fact, the surface parameters passed in the above method are really used for screen capture or screen recording.
Screen Cutting
The ImageReader class is used here, and the Getsurface () method of this class gets to the surface directly into the Mediaprojection.createvirtualdisplay () method, where the interception can be performed. The Imagereader.acquirelatestimage () method allows you to get an image of the current screen, which can be saved as bitmap after simple processing.
private void Startcapture () {mimagename = System.currenttimemillis () + ". png"; LOG.E (TAG, "image name is:" + mimagename); Image image = Mimagereader.acquirelatestimage (); 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 (); if (bitmap! = null) {LOG.E (TAG, "Bitmap create success"); try {File Filefolder = newFile (Mimagepath); if (!filefolder.exists ()) filefolder.mkdirs (); File File = new file (Mimagepath, mimagename); if (!file.exists ()) {LOG.E (TAG, "File Create success"); File.createnewfile (); } FileOutputStream out = new FileOutputStream (file); Bitmap.compress (Bitmap.CompressFormat.PNG, N, out); Out.flush (); Out.close (); LOG.E (TAG, "File Save Success"); Toast.maketext (This.getapplicationcontext (), "Success", Toast.length_short). Show (); } catch (IOException e) {log.e (TAG, e.tostring ()); E.printstacktrace (); } } }
Recording screen
The recording screen needs to use the Mediacadec in the previous blog post, which encodes the original screen data and saves it in MP4 format via Mediamuxer. Mediacodec.createinputsurface () Gets a surface object that speaks of incoming mediaprojection.createvirtualdisplay () to get the screen's original multimedia data, After reading the MEDIACODEC encoded output data through the Mediamuxer package processing for MP4 can play, realize the recording screen.
private void Recordvirtualdisplay () {//loop multi-codec output data processed and saved as MP4 while (!misquit.get ()) {int index = Mmediacodec.dequeueoutputbuffer (Mbufferinfo, 10000); LOG.I (TAG, "dequeue output buffer index=" + index); if (index = = mediacodec.info_output_format_changed) {//Subsequent output format changes Resetoutputformat (); } else if (index = = mediacodec.info_try_again_later) {//Request timed out LOG.D (TAG, "Retrieving Buffers Time out!"); try {//wait 10ms thread.sleep (10); } catch (Interruptedexception e) {}} else if (index >= 0) {//valid output if (!mmuxe rstarted) {throw new IllegalStateException ("Mediamuxer Dose not call Addtrack (format)"); } encodetovideotrack (index); Mmediacodec.releaseoutputbuffer (index, false); }}} private void EncodetovideoTrack (int index) {//output data is mp4 file Bytebuffer encodeddata = Mmediacodec.getoutputbuffer (index); if ((Mbufferinfo.flags & mediacodec.buffer_flag_codec_config)! = 0) {//IS configuration data such as specific format information, not media data//The CODEC con Fig data is pulled out and fed to the muxer when we got//the info_output_format_changed status. Ignore it. LOG.D (TAG, "ignoring buffer_flag_codec_config"); mbufferinfo.size = 0; } if (mbufferinfo.size = = 0) {log.d (TAG, "info.size = = 0, drop it."); Encodeddata = null; } else {log.d (TAG, "Got buffer, info:size=" + Mbufferinfo.size + ", presentationtimeus=" + Mbufferinfo.presentationtimeus + ", offset=" + mbufferinfo.offset); } if (Encodeddata! = null) {//EXISTS encoded data encodeddata.position (Mbufferinfo.offset); Encodeddata.limit (Mbufferinfo.offset + mbufferinfo.size); Mmuxer.writesampLedata (Mvideotrackindex, Encodeddata, mbufferinfo);//write LOG.I (TAG, "sent" + mbufferinfo.size + "bytes to Muxe R ... "); }} private void Resetoutputformat () {//should happen before receiving buffers, and should only happen Once if (mmuxerstarted) {throw new IllegalStateException ("output format already changed!"); } Mediaformat Newformat = Mmediacodec.getoutputformat (); LOG.I (TAG, "output format changed.\n new format:" + newformat.tostring ()); Mvideotrackindex = Mmuxer.addtrack (Newformat); Mmuxer.start (); Mmuxerstarted = true; LOG.I (TAG, "Started media muxer, videoindex=" + mvideotrackindex); }
Appendix Reference
Official documents
Android Video Recording
Android 5.0 screenshot
Android recording Screen code
This article demo
Android5.0-Free root screenshot, recording screen