>我测试代码方法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?
检查上面 – 我猜是的