通话结束后如何停止媒体记录器?

How do i stop the Media Recorder when the Call has ended?

如何停止() 媒体记录器? 我尝试实例化

MediaRecorder r;

但在全球范围内,

r.stop()

不起作用,因为 r 没有实例化。

如果可以保存此 MediaRecorder 实例的状态,并在稍后将其与停止方法一起使用,我该怎么做?

public class nCallRecorder extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
            //start recording
            String CallNo = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
            MediaRecorder r = new MediaRecorder();
            r.setAudioSource(MediaRecorder.AudioSource.MIC);
            r.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            r.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            r.setOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+CallNo+".mp4");
            try { r.prepare(); } catch(IOException e) { e.printStackTrace(); }
            r.start();

        } else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE)) {
            //stop recording
            Toast.makeText(context,"Call Ends",Toast.LENGTH_LONG).show();
        }
    }
}

编辑 2:

服务启动,但Recorder不工作,BroadcastReceiver不工作

AndroidManifest.xml

<service android:name=".RecordService">
  <intent-filter>
    <action android:name="android.intent.action.PHONE_STATE" />
  </intent-filter>
</service>

RecordService.java

public class RecordService extends Service {
private MediaRecorder r = null;
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
private final BroadcastReceiver receiver = new BroadcastReceiver () {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
            String CallNo = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
            onCreate();
            r = new MediaRecorder();
            r.setAudioSource(MediaRecorder.AudioSource.MIC);
            r.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            r.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            r.setOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/l"+CallNo+".mp4");
            try { r.prepare(); } catch(IOException e) { e.printStackTrace(); }
            r.start();
            Toast.makeText(context,"Recording Started",Toast.LENGTH_LONG).show();
        } else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE)) {
            cleanUp();
            Toast.makeText(context,"Call Ends",Toast.LENGTH_LONG).show();
        }
    }
};
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
        return START_STICKY;
    }
    private void cleanUp() {
        if(r != null) {
            try {
                r.stop();
            } catch (Exception ex) {
            } finally {
                r.release();
                r = null;
            }
        }
    }
    public void onCreate() {
        super.onCreate();
        IntentFilter filter = new IntentFilter();
        filter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        registerReceiver(receiver,filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
        cleanUp();
        Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
    }
}

错误Logcat:

 Process: com.alivezoned.callrecorder, PID: 2864
    java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } in com.alivezoned.callrecorder.RecordService@355ef143
            at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:871)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.RuntimeException: start failed.
            at android.media.MediaRecorder.start(Native Method)
            at com.alivezoned.callrecorder.RecordService.onReceive(RecordService.java:34)
            at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:861)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

在您当前的代码中,一旦程序执行退出它在其中声明的块,您对 MediaRecorder 的引用就会丢失。

存储引用的一种简单方法是在服务内部进行录制(推荐)或使用负责处理所有 MediaRecording 事物的单例。

关于单例,唯一要记住的是,当您的应用程序被销毁时,您可能需要做一些清理工作,以免泄漏资源。

http://developer.android.com/guide/components/services.html

在服务的onCreate中注册你的广播接收器,在onDestroy中取消注册。

类似这样的东西(然后只需从您的 activity 或其他广播接收器启动它)。警告您可能需要修复一些编译错误:

public class MyService extends Service {
    private MediaRecorder mMediaRecorder;
    private final BroadcastReceiver mTelephonyReceiver = new BroadcastReceiver () {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Changed order of equals to avoid extra null check.
            if (mMediaRecorder == null && TelephonyManager.EXTRA_STATE_RINGING.equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE)) {
                //start recording
                String CallNo = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                mMediaRecorder  = new MediaRecorder();
                mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                mMediaRecorder.setOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+CallNo+".mp4");
                try { mMediaRecorder.prepare(); } catch(IOException e) { e.printStackTrace(); }
                mMediaRecorder.start();
            } else if (TelephonyManager.EXTRA_STATE_IDLE.equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE)) {
                //stop recording
                cleanUp();
                Toast.makeText(context,"Call Ends",Toast.LENGTH_LONG).show();
             }
        }
    }

    private void cleanUp() {
        if(mMediaRecorder != null) {
            try {
                mMediaRecorder.stop();
            } catch (IOException ex) {
                 // Add your handling here.
            } finally {
                mMediaRecorder.release();
                mMediaRecorder = null;
            }
        }
    }

    public void onCreate () {
        super.onCreate();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_YOUR_ACTION);
        registerReceiver(mTelephonyReceiver, filter);
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mTelephonyReceiver);
        cleanUp();
    }
}

如果您想在设备启动时启动您的服务,请考虑这个堆栈溢出问题: BroadcastReceiver not receiving BOOT_COMPLETED

请在例外情况下插入您的代码,然后尝试。

    MediaRecorder mRecorder = new MediaRecorder();
File mFile = new File("The output file's absolutePath");

... //config the mRecorder
mRecorder.setOutputFile(mFile.getAbsolutePath());

... //prepare() ...
mRecorder.start();

try {
    mRecorder.stop();
} catch(RuntimeException e) {
    mFile.delete();  //you must delete the outputfile when the recorder stop failed.
} finally {
    mRecorder.release();
    mRecorder = null;
}