У меня есть служба, которая записывает телефонные звонки, когда они запускаются событиями телефонной трансляции.Когда телефон разблокирован, служба прекрасно записывает телефонные звонки, однако, когда телефон заблокирован, служба прекращает запись звонков.Есть ли какие-то соображения, которые мне нужно учитывать, когда телефон заблокирован?Я тестирую и устройство Samsung работает под управлением KitKat.
public class CallRecorderService extends Service {
public static boolean RUNNING = false;
private final static String AUDIO_EXT = ".3gpp";
private MediaRecorder mMediaRecorder;
private boolean mRecording;
private Store mStore;
@Override
public void onCreate() {
super.onCreate();
mStore = new Store(this);
RUNNING = true;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
intentFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
CallBroadcastReceiver cbr = new CallBroadcastReceiver();
registerReceiver(cbr, intentFilter);
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private class CallBroadcastReceiver extends AbstractCallReceiver {
private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMddHHmmss");
private String mOutputFileName;
private void persist(String fileName, String phoneNumber, Date startTime, Date endTime, Call.CallDirection callDirection) {
Call call = new Call();
call.setAudioFileName(mOutputFileName);
call.setPhoneNumber(phoneNumber);
call.setStartDateTime(startTime);
call.setEndDateTime(endTime);
call.setCallDirection(callDirection);
mStore.add(call);
mStore.save();
}
@Override
protected void onIncomingCallStarted(Context context, String phoneNumber, Date startTime) {
startRecording(startTime, phoneNumber);
Intent intent = new Intent(IntentUtil.ACTION_INCOMING_CALL_STARTED);
intent.putExtra(IntentUtil.EXTRA_FILE_NAME, mOutputFileName);
intent.putExtra(IntentUtil.EXTRA_PHONE_NUMBER, phoneNumber);
intent.putExtra(IntentUtil.EXTRA_START_TIME, startTime);
sendBroadcast(intent);
}
@Override
protected void onIncomingCallEnded(Context context, String phoneNumber, Date startTime, Date endTime) {
stopRecording();
persist(mOutputFileName, phoneNumber, startTime, endTime, Call.CallDirection.INCOMING);
Intent intent = new Intent(IntentUtil.ACTION_INCOMING_CALL_ENDED);
intent.putExtra(IntentUtil.EXTRA_FILE_NAME, mOutputFileName);
intent.putExtra(IntentUtil.EXTRA_PHONE_NUMBER, phoneNumber);
intent.putExtra(IntentUtil.EXTRA_START_TIME, startTime);
intent.putExtra(IntentUtil.EXTRA_END_TIME, endTime);
sendBroadcast(intent);
}
@Override
protected void onOutgoingCallStarted(Context context, String phoneNumber, Date startTime) {
startRecording(startTime, phoneNumber);
Intent intent = new Intent(IntentUtil.ACTION_OUTGOING_CALL_STARTED);
intent.putExtra(IntentUtil.EXTRA_FILE_NAME, mOutputFileName);
intent.putExtra(IntentUtil.EXTRA_PHONE_NUMBER, phoneNumber);
intent.putExtra(IntentUtil.EXTRA_START_TIME, startTime);
sendBroadcast(intent);
}
@Override
protected void onOutgoingCallEnded(Context context, String phoneNumber, Date startTime, Date endTime) {
stopRecording();
persist(mOutputFileName, phoneNumber, startTime, endTime, Call.CallDirection.OUTGOING);
Intent intent = new Intent(IntentUtil.ACTION_OUTGOING_CALL_ENDED);
intent.putExtra(IntentUtil.EXTRA_FILE_NAME, mOutputFileName);
intent.putExtra(IntentUtil.EXTRA_PHONE_NUMBER, phoneNumber);
intent.putExtra(IntentUtil.EXTRA_START_TIME, startTime);
intent.putExtra(IntentUtil.EXTRA_END_TIME, endTime);
sendBroadcast(intent);
}
public void startRecording(Date startTime, String phoneNumber) {
if (mRecording) {
return;
}
try {
mMediaRecorder = new MediaRecorder();
//TODO Research Sumsung specific audio source.
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setOutputFile(getRecordingPath(startTime));
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecording = true;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void stopRecording() {
if (!mRecording) {
return;
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder.release();
mRecording = false;
}
public String getRecordingPath(Date startTime) {
mOutputFileName = dateFormatter.format(startTime) + AUDIO_EXT;
return new File(mStore.getAudioDir(), mOutputFileName).getAbsolutePath();
}
}
}
public class AbstractCallReceiver extends BroadcastReceiver {
private String mPhoneNumber;
private Context mContext;
private int mLastState = TelephonyManager.CALL_STATE_IDLE;
private boolean mIsIncoming;
private Date mCallStartTime;
private Date mCallEndTime;
private Store mStore;
@Override
public void onReceive(Context context, Intent intent) {
mContext = context;
/**
* Two broadcast events are sent because we are registered for both READ_PHONE_STATE and
* READ_CALL_LOG. We can ignore one of the events by testing if EXTRA_INCOMING_NUMBER
* is not set in the intent.
*/
if (intent.hasExtra(TelephonyManager.EXTRA_STATE) && !intent.hasExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)) {
return;
}
String action = intent.getAction();
switch (action) {
case Intent.ACTION_NEW_OUTGOING_CALL:
mPhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
break;
case TelephonyManager.ACTION_PHONE_STATE_CHANGED:
int state = 0;
String stateStr = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
mPhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
onCallStateChanged(state);
break;
}
}
private void onCallStateChanged(int state) {
if (state == mLastState) {
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
mIsIncoming = true;
mCallStartTime = new Date();
onIncomingCallStarted(mContext, mPhoneNumber, mCallStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (mLastState != TelephonyManager.CALL_STATE_RINGING) {
mIsIncoming = false;
mCallStartTime = new Date();
onOutgoingCallStarted(mContext, mPhoneNumber, mCallStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (mLastState == TelephonyManager.CALL_STATE_RINGING) {
onMissedCall(mContext, mPhoneNumber, mCallStartTime);
} else if (mIsIncoming) {
mCallEndTime = new Date();
onIncomingCallEnded(mContext, mPhoneNumber, mCallStartTime, mCallEndTime);
} else {
mCallEndTime = new Date();
onOutgoingCallEnded(mContext, mPhoneNumber, mCallStartTime, mCallEndTime);
}
break;
}
mLastState = state;
}
protected void onIncomingCallStarted(Context context, String phoneNumber, Date startTime) {
}
protected void onOutgoingCallStarted(Context context, String phoneNumber, Date startTime) {
}
protected void onIncomingCallEnded(Context context, String phoneNumber, Date startTime, Date endTime) {
}
protected void onOutgoingCallEnded(Context context, String phoneNumber, Date startTime, Date endTime) {
}
protected void onMissedCall(Context context, String phoneNumber, Date startTime) {
}
}