android – 为什么MediaRecorder函数不会导致ANR错误?

我在 Android 5.1中使用MediaRecorder和MediaProjection函数启动服务来重新调整屏幕,我认为代码方法1会导致应用程序无响应错误,因为它在主线程中有效.

>我测试代码方法1重新编码屏幕很长时间,它不会发生“应用程序无响应错误”,为什么?这是否意味着MediaRecorder和MediaProjection函数在分离的线程中工作?
>在代码方法2中,我创建了一个运行mRecordHelper.StartRecord的线程(mRecordArg,resultCode,mIntent);但我得到错误java.lang.RuntimeException:无法在没有调用Looper.prepare()的线程内创建处理程序,为什么?

谢谢你的帮助.

电话代码

mpublicPar.RecordArg mRecordArg =new mpublicPar().new RecordArg(mContext);
Intent intent = new Intent(mContext,bll.RecordService.class);
intent.putExtra("resultCode",resultCode);
intent.putExtra("dataIntent",data);
intent.putExtra("mRecordArg",mRecordArg);

startService(intent);

方法1

public class RecordService extends Service { 

    private RecordHelper mRecordHelper;
    private Context mContext;

    @Override
    public void onCreate(){  
        mContext=this;

        mRecordHelper=new RecordHelper(mContext);
    }

    @Override
    public void onDestroy(){
        mRecordHelper.StopRecord();
    }


    @Override
    public int onStartCommand(Intent intent,int flags,int startId) {

       final int resultCode=intent.getIntExtra("resultCode",0);
       final Intent mIntent=(Intent)intent.getParcelableExtra("dataIntent");
       final mpublicPar.RecordArg mRecordArg=(mpublicPar.RecordArg)intent.getSerializableExtra("mRecordArg");

        mRecordHelper.StartRecord(mRecordArg,mIntent);
        return super.onStartCommand(intent,flags,startId);
    }

}

方法2

public class RecordService extends Service { 

    private RecordHelper mRecordHelper;
    private Context mContext;

    @Override
    public void onCreate(){  
        mContext=this;

        mRecordHelper=new RecordHelper(mContext);
    }

    @Override
    public void onDestroy(){
        mRecordHelper.StopRecord();
    }


    @Override
    public int onStartCommand(Intent intent,0);
       final Intent mIntent=(Intent)intent.getParcelableExtra("dataIntent");
       final mpublicPar.RecordArg mRecordArg=(mpublicPar.RecordArg)intent.getSerializableExtra("mRecordArg");    

       new Thread(new Runnable() {
            public void run() {    
                mRecordHelper.StartRecord(mRecordArg,mIntent);           
            }
        }).start();
        return super.onStartCommand(intent,startId);
    }

}

RecordHelper.cs

public class RecordHelper {

    private  MediaRecorder mMediaRecorder;
    private  MediaProjection mMediaProjection;
    private  Virtualdisplay mVirtualdisplay;
    private  mediaprojectionmanager mProjectionManager;

    private Context mContext;
    private Toast mToastText;

    public RecordHelper(Context mContext){
        this.mContext=mContext;
        mProjectionManager = (mediaprojectionmanager) mContext.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        mMediaRecorder = new MediaRecorder();
    }

    public void StartRecord(RecordArg mRecordArg,int resultCode,Intent data){

        initRecorder(mRecordArg);
        prepareRecorder();

        mMediaProjection = mProjectionManager.getMediaProjection(resultCode,data);
        MediaProjectionCallback mMediaProjectionCallback = new MediaProjectionCallback();
        mMediaProjection.registerCallback(mMediaProjectionCallback,null);

        mVirtualdisplay=createVirtualdisplay(mRecordArg);

        DelayStartRecord(mRecordArg);
    }


    public void StopRecord(){
        try {
            mMediaRecorder.stop();
            mMediaRecorder.reset();

            mVirtualdisplay.release();
            mMediaRecorder.release();

            mMediaProjection.stop();
            mMediaProjection = null;

        }catch (Exception e){
            Utility.LogError("StopRecord Error " + e.getMessage() + "  " + e.toString());
        }
    }

    private void DelayStartRecord(RecordArg mRecordArg){
        mMediaRecorder.start();
    }


    private void initRecorder(RecordArg mRecordArg) {
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mMediaRecorder.setoutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
        mMediaRecorder.setVideoFrameRate(30);
        mMediaRecorder.setVideoSize(mRecordArg.screenWidth,mRecordArg.screenHeight);
        mMediaRecorder.setoutputFile(mRecordArg.videoFilename);
    }


    private void prepareRecorder() {
        try {
            mMediaRecorder.prepare();
        } catch (IllegalStateException e) {
            e.printstacktrace();
            Utility.LogError(e.getMessage());

        } catch (IOException e) {
            e.printstacktrace();
            Utility.LogError(e.getMessage());
        }
    }


    private Virtualdisplay createVirtualdisplay(RecordArg mRecordArg) {
          return mMediaProjection.createVirtualdisplay("ScreenRecord",mRecordArg.screenWidth,mRecordArg.screenHeight,mRecordArg.mScreenDensity,displayManager.VIRTUAL_disPLAY_FLAG_AUTO_MIRROR,mMediaRecorder.getSurface(),null /*Callbacks*/,null /*Handler*/);
    }


    //Called when the MediaProjection session is no longer valid.
    private  class MediaProjectionCallback extends MediaProjection.Callback {
        @Override
        public void onStop() {

        }
    }

}

解决方法

but I get the error java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare(),why?

我想你知道你的第二个问题.事实上,如果你调用mRecordHelper.StartRecord(mRecordArg,mIntent);在主线程上,并不意味着所有代码函数都在该线程上运行,它所做的只是更新调用Thread上的UI信息 – 这是主线程,以及后台线程上的辛勤工作.如果你从另一个线程中明确地调用你指示它从该线程更改一个UI对象,那么你得到的异常 – 图片一个使用异步任务的类,或者SurfaceView,不要混淆先生,你可以随时去查看源代码并看看它是如何工作的.

这不是什么大不了的事 – (我谦卑地说)

why? Does it mean that the function MediaRecorder and MediaProjection worked in separated thread?

检查上面 – 我猜是的

相关文章

这篇“android轻量级无侵入式管理数据库自动升级组件怎么实现...
今天小编给大家分享一下Android实现自定义圆形进度条的常用方...
这篇文章主要讲解了“Android如何解决字符对齐问题”,文中的...
这篇文章主要介绍“Android岛屿数量算法怎么使用”的相关知识...
本篇内容主要讲解“Android如何开发MQTT协议的模型及通信”,...
本文小编为大家详细介绍“Android数据压缩的方法是什么”,内...