MediaRecorder:停止调用无效状态:1

时间:2016-08-17 15:48:15

标签: android

我是android新手。我创建了一个屏幕录像机应用程序。一切都已完成,但问题是当我停止屏幕录像机然后它不会停止并发生此错误。当搜索谷歌有关此错误然后我得到MediaRecorder没有启动,但当我检查我的SD卡然后捕获视频保存。我按照本教程here
当我开始视频录制时,然后在点击然后通知停止消息后弹出一个通知然后使用服务我尝试停止mediaRecorder停止但它没有停止和如果有人可以帮助我,那么请提前感谢。

问题 MediaRecorder.stop()无法正常工作。

MainActivity.java

public class MainActivity extends Activity {

    private static final int REQUEST_CODE = 1000;
    private static final String TAG = "MainActivity";

    private ScreenRecorder mScreenRecorder;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mScreenRecorder = RecorderApplication.getApplication(this).getRecorder();
        shareScreen();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode != REQUEST_CODE) {
            Log.e(TAG, "Unknown request code: " + requestCode);

            return;
        }
        if (resultCode != RESULT_OK) {
            Toast.makeText(this, "Screen Cast Permission Denied", Toast.LENGTH_SHORT).show();
            return;
        }
        mScreenRecorder.initRecorder();
        mScreenRecorder.initShareScreen(resultCode, data);
        finish();
    }

    private void shareScreen() {
        if (mScreenRecorder.getMediaProjection() == null) {
            Log.i("getMediaProjection()..."," is null");
            startActivityForResult(mScreenRecorder.getMediaProjectionManager().createScreenCaptureIntent(), REQUEST_CODE);
            return;
        }
        mScreenRecorder.initRecorder();
        mScreenRecorder.shareScreen();
        finish();
    }
}

ScreenRecorder.java

public class ScreenRecorder {

    private Context mContext;
    private WindowManager mWindowManager;

    private int mScreenDensity;
    private MediaProjectionManager mProjectionManager;
    private MediaProjection mMediaProjection;
    private VirtualDisplay mVirtualDisplay;
    private Surface surface;
    private MediaProjectionCallback mMediaProjectionCallback;
    public MediaRecorder mMediaRecorder;
    private String mTargetRecordFileName;
    private String mTargetRecordFilePath;

    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

    public static final String NOTIFICATION_EXTRA = "Extra";
    public static final int EXTRA_PLAY = 0;
    public static final int EXTRA_PAUSE = 1;
    public static final int EXTRA_STOP = 2;
    public int flag = 0;

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

    public ScreenRecorder(Context context, WindowManager windowManager) {
        mContext = context;
        mWindowManager = windowManager;

        DisplayMetrics metrics = new DisplayMetrics();
        mWindowManager.getDefaultDisplay().getMetrics(metrics);
        mScreenDensity = metrics.densityDpi;

        mMediaRecorder = new MediaRecorder();
        mProjectionManager = (MediaProjectionManager) mContext.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    }

    public MediaProjection  getMediaProjection() {
        return mMediaProjection;
    }

    public MediaProjectionManager getMediaProjectionManager() {
        return mProjectionManager;
    }

    public void initShareScreen(int resultCode, Intent data) {
        mMediaProjectionCallback = new MediaProjectionCallback();
        mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
        mMediaProjection.registerCallback(mMediaProjectionCallback, null);

        shareScreen();
    }

    public void shareScreen() {
        mVirtualDisplay = createVirtualDisplay();
        mMediaRecorder.start();
        flag = 1;
        Log.i("shareScreen()...","mMediaRecorder.start()");
        Log.i("shareScreen()...",".."+flag);
//      showRunningNotification();
        showControlNotification();
    }

    private VirtualDisplay createVirtualDisplay() {
        int screen_width = mContext.getResources().getDisplayMetrics().widthPixels;
        int screen_height = mContext.getResources().getDisplayMetrics().heightPixels;
        surface = mMediaRecorder.getSurface();
        return mMediaProjection.createVirtualDisplay("MainActivity",
                screen_width, screen_height, mScreenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mMediaRecorder.getSurface(), null, null);
    }

    public void initRecorder() {
        SharedPreferences mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        int screen_width = mContext.getResources().getDisplayMetrics().widthPixels;
        int screen_height = mContext.getResources().getDisplayMetrics().heightPixels;


        Log.i("initRecorder()...", " Initialization is Completed");

        try {

            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            mMediaRecorder.setVideoSize(screen_width, screen_height);
            mMediaRecorder.setVideoFrameRate(30);
            mMediaRecorder.setOutputFile(getSaveVideoFolder());
            mMediaRecorder.setVideoEncodingBitRate(512 * 1000);


            mMediaRecorder.prepare();
            System.out.println("..........Media Recorder is Ready for Recording......");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getSaveVideoFolder() {
        File folder = new File(Environment.getExternalStorageDirectory()
                + "/ScreenRecorder");
        if (!folder.exists()) {
            folder.mkdirs();
        }
        mTargetRecordFileName = Utils.convertDateToString(new Date()) + ".mp4";
        mTargetRecordFilePath = folder.getAbsolutePath() + "/"
                + mTargetRecordFileName;
        return mTargetRecordFilePath;
    }

    private class MediaProjectionCallback extends MediaProjection.Callback {
        @Override
        public void onStop() {

            mMediaRecorder.stop();
            mMediaRecorder.reset();
            Log.v("ScreenRecorder...", "Recording Stopped");

            mMediaProjection = null;
            stopScreenSharing();
        }
    }

    private void stopScreenSharing() {
        if (mVirtualDisplay == null) {
            return;
        }
        mVirtualDisplay.release();
        // mMediaRecorder.release(); //If used: mMediaRecorder object cannot
        // be reused again
        destroyMediaProjection();
    }

    private void destroyMediaProjection() {

        Log.i("destroyMediaProjection()...","called");
        if (mMediaProjection != null) {
            mMediaProjection.unregisterCallback(mMediaProjectionCallback);
            mMediaProjection.stop();
//          mMediaProjection = null;
            Log.i("destroyMediaProjection()...","not null");
        }
    }

    private static int NOTIFICATION_RUNNING = 109;
    private static int NOTIFICATION_CONTROL = 110;
    private static int NOTIFICATION_DONE = 111;


    private void showControlNotification() {
        Intent intentPause = new Intent(mContext, FloatingViewService.class);
        intentPause.setAction("PAUSE");

        PendingIntent pIntentPause = PendingIntent.getService(mContext, 0,
                intentPause, 0);



        Intent intentStop = new Intent(mContext, FloatingViewService.class);
        intentStop.setAction("STOP");

        PendingIntent pIntentStop = PendingIntent.getService(mContext, 0, intentStop, 0);

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                mContext);
        mBuilder.setSmallIcon(R.drawable.ic_notification);
        mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
        mBuilder.setContentTitle("Recording controls");
        mBuilder.setPriority(Notification.PRIORITY_MAX);
        mBuilder.setOngoing(true);
        mBuilder.setWhen(0);
        // if (!isPauseRecorder) {
        // mBuilder.addAction(R.drawable.ic_action_pause, "PAUSE",
        // pIntentPause);
        // } else {
        // mBuilder.addAction(R.drawable.ic_action_video, "RESUME",
        // pIntentPause);
        // }
        mBuilder.addAction(R.drawable.ic_action_stop, "STOP", pIntentStop);

        Notification notification = mBuilder.build();
        notification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;

        NotificationManager mNotificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(NOTIFICATION_CONTROL, notification);
    }

    public void stopRecorder() {
        try {
            if (mMediaRecorder != null){

                Log.i("flag...","..."+flag);
                mMediaRecorder.stop();
                mMediaRecorder.reset();
//              mMediaProjection.stop();

                stopScreenSharing();

            }else{

                Log.i("mMediaRecorder...in stopRecorder()"," is null");
            }


        }catch (Exception e){
            Log.e("Error to stop media recorder in stopRecorder() method... :- "," "+e.getMessage());
            e.printStackTrace();
        }

        NotificationManager mNotificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.cancel(NOTIFICATION_CONTROL);
        mNotificationManager.cancel(NOTIFICATION_RUNNING);

//      showDoneNotification();
        // TODO save info to database
        DatabaseHelper mDatabaseHelper = new DatabaseHelper(mContext);
        mDatabaseHelper.addVideo(mTargetRecordFilePath);

        // appendToFile(mTargetRecordFileName, getTemporaryFileName());
    }

    private String getTemporaryFileName() {
        return mContext.getExternalCacheDir().getAbsolutePath()
                + File.separator + "tmprecord.mp4";
    }

    private void appendToFile(@NonNull final String targetFileName,
                              @NonNull final String newFileName) {
        Mp4ParserWrapper.append(targetFileName, newFileName);
    }
}

FloatingViewService.java

public class FloatingViewService extends Service {

    private WindowManager windowManager;
    private View floatingView;
    private TextView mTextCoolDown;
    private WindowManager.LayoutParams params;
    private WindowManager.LayoutParams paramsCoolDown;

    private ImageView btnCamera;
    private ImageView btnSettings;
    private ImageView btnAlbum;
    private ImageView btnExit;

    public static final String NOTIFICATION = "com.example.screenrecorder";

    private ScreenRecorder mScreenRecorder ;
    private ScreenRecorder mScreenRecorder1 ;
    private int cooldown = 3;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        windowManager = (WindowManager)this.getSystemService(Context.WINDOW_SERVICE);
        mScreenRecorder = new ScreenRecorder(getApplicationContext(), windowManager);

        if (intent != null) {

            if (intent.getAction() != null) {

                Log.i("intent Action...",intent.getAction());

                if (intent.getAction().equals("PAUSE")) {

                } else if (intent.getAction().equals("STOP")) {
                    mScreenRecorder.stopRecorder();
                    try{
                        showFloatingView();

                    }catch (RuntimeException e){

                    }
                } 
            }
        }

        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        initView();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (floatingView != null)
            windowManager.removeView(floatingView);
    }

    private void initView() {
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        int screen_height = getResources().getDisplayMetrics().heightPixels;

        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        floatingView = inflater.inflate(R.layout.floating_view, null);

        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 100;

        btnCamera = (ImageView) floatingView.findViewById(R.id.btn_camera);
        btnSettings = (ImageView) floatingView.findViewById(R.id.btn_settings);
        btnAlbum = (ImageView) floatingView.findViewById(R.id.btn_album);
        btnExit = (ImageView) floatingView.findViewById(R.id.btn_close);

        btnCamera.setOnTouchListener(new OnItemTouchListener(0));
        btnSettings.setOnTouchListener(new OnItemTouchListener(1));
        btnAlbum.setOnTouchListener(new OnItemTouchListener(2));

        btnExit.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                stopSelf();

            }
        });

        setFloatingViewMove();

    }

    private void showFloatingView() {
        windowManager.addView(floatingView, params);
    }

    private void hideFloatingView() {
        windowManager.removeView(floatingView);
    }

    private int mAction = -1;
    long onTouchTime = -1;
    long TIME_CLICK = 200;

    private class OnItemTouchListener implements OnTouchListener {

        private int action;

        public OnItemTouchListener(int action) {
            this.action = action;
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mAction = action;
                v.setBackgroundResource(R.drawable.bg_item_selected);
                onTouchTime = System.currentTimeMillis();
                break;
            }
            return false;
        }
    }

    private void setFloatingViewMove() {
        floatingView.setOnTouchListener(new OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    initialX = params.x;
                    initialY = params.y;
                    initialTouchX = event.getRawX();
                    initialTouchY = event.getRawY();
                    break;
                case MotionEvent.ACTION_UP:
                    Log.d("phucdl", "start recorder " + (System.currentTimeMillis() - onTouchTime));

                    if (System.currentTimeMillis() - onTouchTime < TIME_CLICK) {
                        Intent intent;

                        switch (mAction) {
                        case 0:
                            if (RecorderApplication.getApplication(FloatingViewService.this).getRecorder() == null) {
                                mScreenRecorder = new ScreenRecorder(FloatingViewService.this, windowManager);
                                RecorderApplication.getApplication(FloatingViewService.this).setRecorder(mScreenRecorder);
                            }
                            intent = new Intent(FloatingViewService.this, MainActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                            hideFloatingView();
                            break;
                        case 1:
                            intent = new Intent(FloatingViewService.this, PreferencesActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                            hideFloatingView();
                            break;
                        case 2:
                            intent = new Intent(FloatingViewService.this, AlbumActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                            hideFloatingView();
                            break;

                        default:
                            break;
                        }
                    }

                    btnCamera.setBackgroundDrawable(null);
                    btnSettings.setBackgroundDrawable(null);
                    btnAlbum.setBackgroundDrawable(null);
                    btnExit.setBackgroundDrawable(null);
                    break;
                case MotionEvent.ACTION_MOVE:
                    params.x = initialX
                            + (int) (event.getRawX() - initialTouchX);
                    params.y = initialY
                            + (int) (event.getRawY() - initialTouchY);
                    windowManager.updateViewLayout(floatingView, params);
                    break;
                }
                return false;
            }
        });
    }
}

日志

08-17 20:43:07.537 13733-13733/com.example.screenrecorder E/MediaRecorder: stop called in an invalid state: 1
08-17 20:43:07.537 13733-13733/com.example.screenrecorder E/Error to stop media recorder in stopRecorder() method... :-:  null
08-17 20:43:07.537 13733-13733/com.example.screenrecorder W/System.err: java.lang.IllegalStateException
08-17 20:43:07.537 13733-13733/com.example.screenrecorder W/System.err:     at android.media.MediaRecorder.stop(Native Method)
08-17 20:43:07.537 13733-13733/com.example.screenrecorder W/System.err:     at com.gameapp.screenrecorder.ScreenRecorder.stopRecorder(ScreenRecorder.java:371)
08-17 20:43:07.537 13733-13733/com.example.screenrecorder W/System.err:     at com.gameapp.screenrecorder.FloatingViewService.onStartCommand(FloatingViewService.java:59)
08-17 20:43:07.537 13733-13733/com.example.screenrecorder W/System.err:     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3010)
08-17 20:43:07.537 13733-13733/com.example.screenrecorder W/System.err:     at android.app.ActivityThread.-wrap17(ActivityThread.java)
08-17 20:43:07.537 13733-13733/com.example.screenrecorder W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1442)
08-17 20:43:07.538 13733-13733/com.example.screenrecorder W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
08-17 20:43:07.538 13733-13733/com.example.screenrecorder W/System.err:     at android.os.Looper.loop(Looper.java:148)
08-17 20:43:07.538 13733-13733/com.example.screenrecorder W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
08-17 20:43:07.538 13733-13733/com.example.screenrecorder W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
08-17 20:43:07.538 13733-13733/com.example.screenrecorder W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
08-17 20:43:07.538 13733-13733/com.example.screenrecorder W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
08-17 20:43:07.732 13733-13750/com.example.screenrecorder W/EGL_emulation: eglSurfaceAttrib not implemented
08-17 20:43:07.732 13733-13750/com.example.screenrecorder W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xed6bf5a0, error=EGL_SUCCESS
08-17 20:43:09.433 13733-13750/com.example.screenrecorder E/Surface: getSlotFromBufferLocked: unknown buffer: 0xee9722a0

1 个答案:

答案 0 :(得分:1)

你创建一个 ScreenRecorder 类的对象第一次在 setFloatingViewMove()方法中的 FloatingViewService 类中,但是当你单击Stop然后再次创建 ScreenRecorder 类对象然后调用它的构造函数并且您的先前MediaRacoder对象是新初始化的,然后在调用stop方法之后但是mediarecoder start方法不会被调用new initialized mediarecorder实例,了解发生此异常的原因。只需在 onStartCommand()方法中的 FloatingViewService 类中命名或删除一行。我希望这样将解决您的问题。

 @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        windowManager = (WindowManager)this.getSystemService(Context.WINDOW_SERVICE);
       // mScreenRecorder = new ScreenRecorder(getApplicationContext(), windowManager);
}