Служба не получает широковещательные сообщения, когда телефон заблокирован - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть служба, которая записывает телефонные звонки, когда они запускаются событиями телефонной трансляции.Когда телефон разблокирован, служба прекрасно записывает телефонные звонки, однако, когда телефон заблокирован, служба прекращает запись звонков.Есть ли какие-то соображения, которые мне нужно учитывать, когда телефон заблокирован?Я тестирую и устройство 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) {
}
}

Ответы [ 3 ]

0 голосов
/ 03 января 2019

Возможно, вы захотите посмотреть на это. Добавьте разрешения к манифесту:

<uses-permission android:name="android.permission.WAKE_LOCK"/>

Затем ...

PowerManager pm = (PowerManager)getApplicationContext().getSystemService(getApplicationContext().POWER_SERVICE);
WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wl.acquire();

Также снимите блокировку пробуждения

wl.release()
0 голосов
/ 04 января 2019

вы объявили трансляцию в манифесте!

 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
wl.acquire(15000);

попробуйте это

0 голосов
/ 28 декабря 2018

Согласно документации , после API 26 сервисы не вызываются при закрытии приложения.Вместо этого рекомендуется использовать запланированное задание.

...