qq_36048445
qq_36048445
2019-01-18 15:33

MediaRecorder录屏,Socket传输录屏内容报错java.lang.IllegalStateException

  • android-studio
  • android

用模拟器调试可以运行,用真机测试在 mediaRecorder.prepare();抛异常

package www.xjw.com.mymiracast2.screenrecordservice;

import android.app.Notification;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;


import java.net.Socket;



/**
 * Created by dzjin on 2018/1/9.
 */

public class ScreenRecordService extends Service {

    private int resultCode;
    private Intent resultData=null;

    private MediaProjection mediaProjection=null;
    private MediaRecorder mediaRecorder=null;
    private VirtualDisplay virtualDisplay=null;

    private int mScreenWidth;
    private int mScreenHeight;
    private int mScreenDensity;
    private static String filePathName;

    private Socket receiver = null;
    private ParcelFileDescriptor pfd = null;

    private Context context=null;

    private String host = null;
    private int port = 8989;

    @Override
    public void onCreate() {
        super.onCreate();
        //startForeground(2, new Notification());
    }

    /**
     * 每次客户端通过调用startService(Intent)显式启动服务时,系统调用startService(Intent),
      *提供它提供的参数和表示启动请求的唯一整数标记。
     * 不要直接调用这个方法。
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        try{
            resultCode=intent.getIntExtra("resultCode",-1);
            resultData=intent.getParcelableExtra("resultData");
            mScreenWidth=intent.getIntExtra("mScreenWidth",0);
            mScreenHeight=intent.getIntExtra("mScreenHeight",0);
            mScreenDensity=intent.getIntExtra("mScreenDensity",0);
            filePathName=intent.getStringExtra("filePathName");
            host=intent.getStringExtra("host");
            port=intent.getIntExtra("port",8989);

            receiver = new Socket(host, port);
            pfd = ParcelFileDescriptor
                    .fromSocket(receiver);

            mediaProjection=createMediaProjection();
            mediaRecorder=createMediaRecorder();
            virtualDisplay=createVirtualDisplay();
            mediaRecorder.start();

        }catch (Exception e) {
            e.printStackTrace();
        }
        /**
         * START_NOT_STICKY:
         *从onStartCommand返回的常量(Intent, int, int):如果这个服务的进程是
         *在启动时被杀死(从onStartCommand(Intent, int, int)返回后),
         *没有新的start意图交付给它,然后将服务从
         *启动状态,在以后显式调用Context.startService(Intent)之前不要重新创建。
         *服务将不会接收带有空意图的onStartCommand(Intent, int, int)调用
         *因为如果没有等待交付的意图,它将不会重新启动。
         */
        return Service.START_NOT_STICKY;
    }

    public MediaProjection createMediaProjection(){
        /**
         *使用getSystemService(类)检索MediaProjectionManager实例
         *管理媒体放映会议。
         */
        return ((MediaProjectionManager)getSystemService(Context.MEDIA_PROJECTION_SERVICE))
                .getMediaProjection(resultCode,resultData);
        /**
         *检索从成功的屏幕捕获请求中获得的MediaProjection。
         *如果startActivityForResult()的结果不是RESULT_OK,则*将为null。
         */
    }

    private MediaRecorder createMediaRecorder(){

        //用于录制音频和视频。录音控制是基于一个简单的状态机。
        MediaRecorder mediaRecorder=new MediaRecorder();
        //设置要录音的源。
        //mediaRecorder.setAudioSource(MediaRecorder. AudioSource.CAMCORDER);
        //设置要录制的视频源。
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        //设置录制过程中产生的输出的格式。
        //3GPP媒体文件格式
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
        //设置录音格式
        //mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        //设置录像编码比特率。
        //param:以比特/秒为单位的视频编码比特率
        mediaRecorder.setVideoEncodingBitRate(5*mScreenWidth*mScreenHeight);
        //设置录像编码器用于录像。
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        //设置要拍摄的视频的宽度和高度。
        mediaRecorder.setVideoSize(mScreenWidth,mScreenHeight);
        //设置要捕获视频的帧速率。
        mediaRecorder.setVideoFrameRate(60);
        try{
            mediaRecorder.setOutputFile(pfd.getFileDescriptor());
            //mediaRecorder.setOutputFile(filePathName);
                        **此次抛异常**
            //准备记录器开始捕捉和编码数据。
            mediaRecorder.prepare();
        }catch (Exception e){
            e.printStackTrace();
        }
        return mediaRecorder;
    }

    private VirtualDisplay createVirtualDisplay(){
        /**
         *名称字符串:虚拟显示的名称,必须是非空的。这个值不能为空。
         width int:虚拟显示的宽度,以像素为单位。必须大于0。
         高度int:虚拟显示器的高度,以像素为单位。必须大于0。
         dpi int: dpi中虚拟显示的密度。必须大于0。
         标志int:虚拟显示标志的组合。有关标志的完整列表,请参见DisplayManager。
         surface surface:虚拟显示内容应该呈现到的表面,如果一开始没有,则为null。
         回调virtualdisplay。回调:当虚拟显示的状态改变时调用的回调,如果没有,则为空。
         处理程序处理程序:应该在其上调用回调的处理程序,如果应该在调用线程的主循环程序上调用回调,则为null。
         */
        /**
         * DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
         *虚拟显示标志:当没有显示内容时,允许在私有显示上镜像内容。
         */
        return mediaProjection.createVirtualDisplay("mediaProjection",mScreenWidth,mScreenHeight,mScreenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mediaRecorder.getSurface(),null,null);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(virtualDisplay!=null){
            virtualDisplay.release();
            virtualDisplay=null;
        }
        if(mediaRecorder!=null){
            mediaRecorder.stop();
            mediaRecorder=null;
        }
        if(mediaProjection!=null){
            mediaProjection.stop();
            mediaProjection=null;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("===============================");
        return null;
    }

}

I/MediaRecorder: enter in file frameworks/av/media/libmedia/mediarecorder.cpp, function prepare, line 461
I/IMediaRecorder: prepare (BpMediaRecorder client) in file frameworks/av/media/libmedia/IMediaRecorder.cpp, function prepare, line 249
W/com.mymiracast2: type=1400 audit(0.0:104572): avc: denied { read write } for path="socket:[8870267]" dev="sockfs" ino=8870267 scontext=u:r:mediaserver:s0 tcontext=u:r:untrusted_app:s0:c512,c768 tclass=tcp_socket permissive=0
E/MediaRecorder: prepare failed: -38
W/zygote64: Got a deoptimization request on un-deoptimizable method void android.media.MediaRecorder._prepare()
W/System.err: java.lang.IllegalStateException
W/System.err: at android.media.MediaRecorder._prepare(Native Method)
W/System.err: at android.media.MediaRecorder.prepare(MediaRecorder.java:1017)
W/System.err: at www.xjw.com.mymiracast2.screenrecordservice.ScreenRecordService.createMediaRecorder(ScreenRecordService.java:137)
W/System.err: at www.xjw.com.mymiracast2.screenrecordservice.ScreenRecordService.onStartCommand(ScreenRecordService.java:79)
W/System.err: at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4151)
W/System.err: at android.app.ActivityThread.-wrap21(Unknown Source:0)
W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2119)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:108)
W/System.err: at android.os.Looper.loop(Looper.java:166)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7529)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
E/MediaRecorder: SurfaceMediaSource could not be initialized!
W/System.err: java.lang.IllegalStateException: failed to get surface
at android.media.MediaRecorder.getSurface(Native Method)
W/System.err: at www.xjw.com.mymiracast2.screenrecordservice.ScreenRecordService.createVirtualDisplay(ScreenRecordService.java:160)
at www.xjw.com.mymiracast2.screenrecordservice.ScreenRecordService.onStartCommand(ScreenRecordService.java:80)
W/System.err: at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4151)
at android.app.ActivityThread.-wrap21(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2119)
at android.os.Handler.dispatchMessage(Handler.java:108)
W/System.err: at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
D/StrictMode: StrictMode policy violation; ~duration=7334 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=65543 violation=4
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1466)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:356)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:201)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:183)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:356)
at java.net.Socket.connect(Socket.java:616)
at java.net.Socket.connect(Socket.java:565)
at java.net.Socket.(Socket.java:445)
at java.net.Socket.(Socket.java:217)
at www.xjw.com.mymiracast2.screenrecordservice.ScreenRecordService.onStartCommand(ScreenRecordService.java:74)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4151)
at android.app.ActivityThread.-wrap21(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2119)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
D/StrictMode: StrictMode policy violation; ~duration=7332 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=65543 violation=4


  • 点赞
  • 回答
  • 收藏
  • 复制链接分享

0条回答

为你推荐