使用音频源MIC进行呼叫录音始终失败

时间:2014-02-04 11:13:10

标签: android voice-recording

我正在编写使用MIC作为音频源的通话录音功能,因为某些设备不允许使用VOICE_CALL。 以下是我的代码。

但有时这段代码会因Null指针异常而崩溃,有时也不会停止media-recorder我的意思是录音也会在通话结束后继续播放。

广播接收器注册为phone-state听众......

任何帮助将不胜感激。你可以在下面找到我的代码。

import java.io.File;
import java.io.IOException;
import java.util.Calendar;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class TestingCallmonitor extends BroadcastReceiver{
 private MediaRecorder mediaRecorder=null;
 boolean flag=false;  
    @Override
     public void onReceive(Context context, Intent intent) {
         String action = intent.getAction();

         if(action.equalsIgnoreCase("android.intent.action.PHONE_STATE"))
          {
           if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) 
              {

               //Toast.makeText(context, "ringing", Toast.LENGTH_LONG).show(); 

              }         

           if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE)) 
              {
                 if(flag) {   
                           mediaRecorder.stop();
                           mediaRecorder.release();
                           mediaRecorder=null;
                           }
                flag=false;
              }     

           if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) 
            {  
               flag=true;
               Calendar c=Calendar.getInstance();
               int hour=c.get(Calendar.HOUR);
               int min=c.get(Calendar.MINUTE);
               int sec=c.get(Calendar.SECOND);
               //Toast.makeText(context, "started", Toast.LENGTH_LONG).show();
               File folder = new File(Environment.getExternalStorageDirectory() + "/Callrecord");
                if (!folder.exists()) {
                    folder.mkdir();
                }
                String mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
                mFileName += "/Callrecord/call"+hour+"-"+min+"-"+sec+".3gp";
                mediaRecorder=new MediaRecorder();
                mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                //mediaRecorder.setAudioEncoder(MediaRecorder.getAudioSourceMax());
                mediaRecorder.setAudioSamplingRate(44100);
                mediaRecorder.setAudioEncodingBitRate(16);
                mediaRecorder.setOutputFile(mFileName);
                try{mediaRecorder.prepare();}catch(IOException e){Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();}
                mediaRecorder.start();

             }    

         }   

    }

}

1 个答案:

答案 0 :(得分:3)

这里我添加了呼叫记录器示例源代码。请尝试让我知道。

<强> RecordService.java

import java.io.File;
import java.io.IOException;
import java.lang.Exception;
import java.util.Date;
import java.text.SimpleDateFormat;
import android.os.IBinder;
import android.app.Service;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.preference.PreferenceManager;
import android.content.SharedPreferences;
import android.content.Context;
import android.content.Intent;
import android.media.MediaRecorder;
import android.widget.Toast;
import android.util.Log;
import java.io.InputStream;
import java.io.FileInputStream;
import java.util.Iterator;

public class RecordService 
    extends Service
    implements MediaRecorder.OnInfoListener, MediaRecorder.OnErrorListener
{
    private static final String TAG = "CallRecorder";

    public static final String DEFAULT_STORAGE_LOCATION = "/sdcard/callrecorder";
    private static final int RECORDING_NOTIFICATION_ID = 1;
    private MediaRecorder recorder = null;
    private boolean isRecording = false;
    private File recording = null;;
    private final int audioformat = 3;


    private File makeOutputFile (SharedPreferences prefs)
    {
    File dir = new File(DEFAULT_STORAGE_LOCATION);

    // test dir for existence and writeability
    if (!dir.exists()) {
        try {
            dir.mkdirs();
        } catch (Exception e) {
            Log.e("CallRecorder", "RecordService::makeOutputFile unable to create directory " + dir + ": " + e);
            Toast t = Toast.makeText(getApplicationContext(), "CallRecorder was unable to create the directory " + dir + " to store recordings: " + e, Toast.LENGTH_LONG);
            t.show();
            return null;
        }
    } else {
        if (!dir.canWrite()) {
            Log.e(TAG, "RecordService::makeOutputFile does not have write permission for directory: " + dir);
            Toast t = Toast.makeText(getApplicationContext(), "CallRecorder does not have write permission for the directory directory " + dir + " to store recordings", Toast.LENGTH_LONG);
            t.show();
            return null;
        }
    }

    // test size

    // create filename based on call data
    String prefix = "call";
    //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd_HH:MM:SS");
    //prefix = sdf.format(new Date()) + "-callrecording";

    // add info to file name about what audio channel we were recording
    prefix += "-channel" + 1 + "-";

    // create suffix based on format
    String suffix = "";
    switch (audioformat) {
    case MediaRecorder.OutputFormat.THREE_GPP:
        suffix = ".3gpp";
        break;
    case MediaRecorder.OutputFormat.MPEG_4:
        suffix = ".mpg";
        break;
    case MediaRecorder.OutputFormat.RAW_AMR:
        suffix = ".amr";
        break;
    }

    try {
        return File.createTempFile(prefix, suffix, dir);
    } catch (IOException e) {
        Log.e("CallRecorder", "RecordService::makeOutputFile unable to create temp file in " + dir + ": " + e);
        Toast t = Toast.makeText(getApplicationContext(), "CallRecorder was unable to create temp file in " + dir + ": " + e, Toast.LENGTH_LONG);
        t.show();
        return null;
    }
    }

    public void onCreate()
    {
    super.onCreate();
    recorder = new MediaRecorder();
    Log.i("CallRecorder", "onCreate created MediaRecorder object");
    }

    public void onStart(Intent intent, int startId) {
    Log.i("CallRecorder", "RecordService::onStartCommand called while isRecording:" + isRecording);

    if (isRecording) return;

    Context c = getApplicationContext();
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);

    Boolean shouldRecord = prefs.getBoolean(Preferences.PREF_RECORD_CALLS, false);
    if (!shouldRecord) {
        Log.i("CallRecord", "RecordService::onStartCommand with PREF_RECORD_CALLS false, not recording");
        //return START_STICKY;
        return;
    }
    recording = makeOutputFile(prefs);
    if (recording == null) {
        recorder = null;
        return; //return 0;
    }

       try {
        // These calls will throw exceptions unless you set the 
        // android.permission.RECORD_AUDIO permission for your app
        recorder.reset();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(audioformat);
        Log.d("CallRecorder", "set output " + audioformat);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
        Log.d("CallRecorder", "set encoder default");
        recorder.setOutputFile(recording.getAbsolutePath());
        Log.d("CallRecorder", "set file: " + recording);
        //recorder.setMaxDuration(msDuration); //1000); // 1 seconds
        //recorder.setMaxFileSize(bytesMax); //1024*1024); // 1KB

        recorder.setOnInfoListener(this);
        recorder.setOnErrorListener(this);

        try {
            recorder.prepare();
        } catch (java.io.IOException e) {
            Log.e("CallRecorder", "RecordService::onStart() IOException attempting recorder.prepare()\n");
            Toast t = Toast.makeText(getApplicationContext(), "CallRecorder was unable to start recording: " + e, Toast.LENGTH_LONG);
            t.show();
            recorder = null;
            return; //return 0; //START_STICKY;
        }
        Log.d("CallRecorder", "recorder.prepare() returned");

        recorder.start();
        isRecording = true;
        Log.i("CallRecorder", "recorder.start() returned");
        updateNotification(true);
    } catch (java.lang.Exception e) {
        Toast t = Toast.makeText(getApplicationContext(), "CallRecorder was unable to start recording: " + e, Toast.LENGTH_LONG);
        t.show();

        Log.e("CallRecorder", "RecordService::onStart caught unexpected exception", e);
        recorder = null;
    }

    return; //return 0; //return START_STICKY;
    }

    public void onDestroy()
    {
    super.onDestroy();

    if (null != recorder) {
        Log.i("CallRecorder", "RecordService::onDestroy calling recorder.release()");
        isRecording = false;
        recorder.release();
        Toast t = Toast.makeText(getApplicationContext(), "CallRecorder finished recording call to " + recording, Toast.LENGTH_LONG);
        t.show();
    }

    updateNotification(false);
    }


    // methods to handle binding the service

    public IBinder onBind(Intent intent)
    {
    return null;
    }

    public boolean onUnbind(Intent intent)
    {
    return false;
    }

    public void onRebind(Intent intent)
    {
    }


    private void updateNotification(Boolean status)
    {
    Context c = getApplicationContext();
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);

    String ns = Context.NOTIFICATION_SERVICE;
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);

    if (status) {
        int icon = R.drawable.rec;
        CharSequence tickerText = "Recording call from channel " + prefs.getString(Preferences.PREF_AUDIO_SOURCE, "1");
        long when = System.currentTimeMillis();

        Notification notification = new Notification(icon, tickerText, when);

        Context context = getApplicationContext();
        CharSequence contentTitle = "CallRecorder Status";
        CharSequence contentText = "Recording call from channel...";
        Intent notificationIntent = new Intent(this, RecordService.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

        notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
        mNotificationManager.notify(RECORDING_NOTIFICATION_ID, notification);
    } else {
        mNotificationManager.cancel(RECORDING_NOTIFICATION_ID);
    }
    }

    // MediaRecorder.OnInfoListener
    public void onInfo(MediaRecorder mr, int what, int extra)
    {
    Log.i("CallRecorder", "RecordService got MediaRecorder onInfo callback with what: " + what + " extra: " + extra);
    isRecording = false;
    }

    // MediaRecorder.OnErrorListener
    public void onError(MediaRecorder mr, int what, int extra) 
    {
    Log.e("CallRecorder", "RecordService got MediaRecorder onError callback with what: " + what + " extra: " + extra);
    isRecording = false;
    mr.release();
    }
}

PhoneListener.java

import android.content.Intent;
import android.content.Context;
import android.content.ComponentName;
import android.telephony.TelephonyManager;
import android.telephony.PhoneStateListener;
import android.util.Log;

public class PhoneListener extends PhoneStateListener
{
    private Context context;

    public PhoneListener(Context c) {
    Log.i("CallRecorder", "PhoneListener constructor");
    context = c;
    }

    public void onCallStateChanged (int state, String incomingNumber)
    {
    Log.d("CallRecorder", "PhoneListener::onCallStateChanged state:" + state + " incomingNumber:" + incomingNumber);

    switch (state) {
    case TelephonyManager.CALL_STATE_IDLE:
        Log.d("CallRecorder", "CALL_STATE_IDLE, stoping recording");
        Boolean stopped = context.stopService(new Intent(context, RecordService.class));
        Log.i("CallRecorder", "stopService for RecordService returned " + stopped);
        break;
    case TelephonyManager.CALL_STATE_RINGING:
        Log.d("CallRecorder", "CALL_STATE_RINGING");
        break;
    case TelephonyManager.CALL_STATE_OFFHOOK:
        Log.d("CallRecorder", "CALL_STATE_OFFHOOK starting recording");
        Intent callIntent = new Intent(context, RecordService.class);
        ComponentName name = context.startService(callIntent);
        if (null == name) {
            Log.e("CallRecorder", "startService for RecordService returned null ComponentName");
        } else {
            Log.i("CallRecorder", "startService returned " + name.flattenToString());
        }
        break;
    }
    }
}

希望它对你有用。它对我来说很好。请尝试让我知道。 欲了解更多信息,请下载示例代码表

Call Recorder