Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/220.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 手机锁定时服务未接收广播消息_Java_Android_Android Service_Android Broadcast - Fatal编程技术网

Java 手机锁定时服务未接收广播消息

Java 手机锁定时服务未接收广播消息,java,android,android-service,android-broadcast,Java,Android,Android Service,Android Broadcast,我有一项服务,当电话广播事件触发时记录电话呼叫。当手机处于解锁状态时,服务会完美地录制通话,但当手机处于锁定状态时,服务会停止录制通话。当手机锁定时,我需要考虑哪些因素?我正在测试一台运行KitKat的三星设备 public class CallRecorderService extends Service { public static boolean RUNNING = false; private final static String AUDIO_EXT = ".3gpp"; pri

我有一项服务,当电话广播事件触发时记录电话呼叫。当手机处于解锁状态时,服务会完美地录制通话,但当手机处于锁定状态时,服务会停止录制通话。当手机锁定时,我需要考虑哪些因素?我正在测试一台运行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) {
}
}

根据API 26,当应用程序关闭时,不会调用after API 26服务。建议改为使用计划作业。

您可能希望对此进行研究。向清单添加权限:

<uses-permission android:name="android.permission.WAKE_LOCK"/>
同时释放尾流锁

wl.release()

你在舱单上宣布了广播

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

试试这个

你在哪个android版本上测试这个?请添加您尝试过的代码。是否在安卓8+版本上?我正在安卓5.1上测试。您需要前台服务使其正常工作。在上面放置一个带有按钮的通知以停止录制。
 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
wl.acquire(15000);