package com.lingju.assistant.service.process; import android.app.Service; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; import android.provider.ContactsContract; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import com.lingju.assistant.AppConfig; import com.lingju.assistant.R; import com.lingju.assistant.activity.event.CallAndSmsEvent; import com.lingju.assistant.activity.event.ChatMsgEvent; import com.lingju.assistant.activity.event.SynthesizeEvent; import com.lingju.assistant.player.audio.LingjuAudioPlayer; import com.lingju.assistant.service.AssistantService; import com.lingju.assistant.service.process.base.BaseProcessor; import com.lingju.audio.SystemVoiceMediator; import com.lingju.audio.engine.base.SpeechMsg; import com.lingju.audio.engine.base.SpeechMsgBuilder; import com.lingju.audio.engine.base.SynthesizerBase; import com.lingju.common.log.Log; import com.lingju.context.entity.Command; import com.lingju.context.entity.ContactNum; import com.lingju.model.Contact; import com.lingju.model.SmsInfo; import com.lingju.model.dao.CallAndSmsDao; import com.lingju.model.temp.speech.ResponseMsg; import com.lingju.util.PhoneContactUtils; import org.greenrobot.eventbus.EventBus; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import io.reactivex.Observable; import io.reactivex.Single; import io.reactivex.functions.Action; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; /** * Created by Administrator on 2016/11/5. */ public class MobileCommProcessor extends BaseProcessor { private static final String TAG = "LingJu"; /** * 显示联系人详细信息的对话框 */ public final static int CallDialogType = 0; /** * 显示短信内容的对话框 */ public final static int SmsDialogType = 1; /** * 选择多个联系人或者号码的对话框 */ public final static int CheckListDialogType = 2; //CallDialogType的子类 public final static int WaittingForCall = 00; public final static int ConfirmNameCall = 01; public final static int ConfirmNameSms = 02; public final static int ConfirmLastCall = 03; public final static int CompletedCall = 04; public final static int FailedCall = 05; //SmsDialogType的子类 public final static int WaittingForSend = 010; public final static int ConfirmForSend = 011; public final static int ConfirmLastMsg = 012; public final static int CompletedSend = 013; public final static int FailedSend = 014; //CheckListDialogType的子类 public final static int CheckForNameCall = 020; public final static int CheckForNumCall = 021; public final static int CheckForNameSms = 022; public final static int CheckForNumSms = 023; private AppConfig mAppConfig; private ThreadPoolExecutor tPools; //线程池 private int mobileState; //通话状态 private int current_volume; //当前音量 private Handler mHandler; private int inMsgTipsFlow; private boolean isSmsReceiverValid; public MobileCommProcessor(Context mContext, SystemVoiceMediator mediator, Handler handler) { super(mContext, mediator); this.mHandler = handler; mAppConfig = (AppConfig) ((Service) mContext).getApplication(); tPools = new ThreadPoolExecutor(10, 20, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); phoneCallListener(); // 注册收件箱内容观察者 mContext.getContentResolver().registerContentObserver(Uri.parse(PhoneContactUtils.SMS_URI_INBOX), true, new SmsObserver(handler)); // 注册联系人内容观察者 mContext.getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, new ContactObserver(handler)); } @Override public int aimCmd() { return CMD_CALL; } @Override public void handle(Command cmd, String text, int inputType) { super.handle(cmd, text, inputType); EventBus.getDefault().post(new CallAndSmsEvent(cmd, text, inputType)); } /** * 合成并在聊天视图中显示回复文本 * * @param text 回复文本 * @param inputType 用户输入类型。只有语音录入才会合成回复文本 * @param msgBuilder 合成信息对象 **/ private void speakAndShowResp(String text, int inputType, SpeechMsgBuilder msgBuilder) { /* 发送回复文本到聊天视图 */ EventBus.getDefault().post(new ChatMsgEvent(new ResponseMsg(text), null, null, null)); if (inputType == AssistantService.INPUT_VOICE) { msgBuilder.setText(text); SynthesizerBase.get().startSpeakAbsolute(msgBuilder.build()) /* 合成是在Observable的subscribe()开始的,所以要在这之前通知动画播放。 * doOnSubscribe 执行在离它最近的 subscribeOn() 所指定的线程。*/ .doOnNext(new Consumer<SpeechMsg>() { @Override public void accept(SpeechMsg speechMsg) throws Exception { if (speechMsg.state() == SpeechMsg.State.OnBegin) EventBus.getDefault().post(new SynthesizeEvent(SynthesizeEvent.SYNTH_START)); } }) .doOnComplete(new Action() { @Override public void run() throws Exception { EventBus.getDefault().post(new SynthesizeEvent(SynthesizeEvent.SYNTH_END)); } }) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) .subscribe(); } } /** * 检测未接来电、未读短信 **/ public boolean missedContact() { int size; SpeechMsgBuilder msgBuilder = SpeechMsgBuilder.create(null); if ((size = mAppConfig.missedCallContacts.size()) > 0) { StringBuilder sb = new StringBuilder(); if (size == 1) { Contact c = mAppConfig.missedCallContacts.poll(); sb.append("刚才有来自").append(c.getName()).append("的未接来电!"); } else { mAppConfig.missedCallContacts.clear(); sb.append("在您刚才通话的时候,有").append(size).append("个未接来电!"); } speakAndShowResp(sb.toString(), AssistantService.INPUT_VOICE, msgBuilder); return true; } else if ((size = mAppConfig.missedMsgs.size()) > 0) { if (size == 1) { /* 记录最新一条未查看短信 */ SmsInfo sms = mAppConfig.missedMsgs.poll(); mAppConfig.lastSms.setTime(sms.getTime()); mAppConfig.lastSms.setContent(sms.getContent()); mAppConfig.lastSms.setNumber(sms.getNumber()); mAppConfig.lastSms.setName(sms.getName()); mAppConfig.lastSms.setType(sms.getType()); mAppConfig.lastSms.setContact(sms.getContact()); mHandler.sendEmptyMessage(1); } else { SmsInfo sms = null, temp; while ((temp = mAppConfig.missedMsgs.poll()) != null) { sms = temp; } /* 记录最新一条未查看短信 */ mAppConfig.lastSms.setTime(sms.getTime()); mAppConfig.lastSms.setContent(sms.getContent()); mAppConfig.lastSms.setNumber(sms.getNumber()); mAppConfig.lastSms.setName(sms.getName()); mAppConfig.lastSms.setType(sms.getType()); mAppConfig.lastSms.setContact(sms.getContact()); Intent smsIntent = new Intent(mContext, AssistantService.class); smsIntent.putExtra(AssistantService.CMD, AssistantService.ServiceCmd.PUSH_ROUTE_CACULATE); smsIntent.putExtra(AssistantService.TEXT, "是否依次朗读短信3"); String text = "你有多条未读短信,需要依次朗读吗?"; msgBuilder.setContextMode(SpeechMsg.CONTEXT_KEEP_RECOGNIZE); speakAndShowResp(text, AssistantService.INPUT_VOICE, msgBuilder); } return true; } return false; } @Override public void smsMsgHandle() { Contact c = mAppConfig.lastSms.getContact(); if (mAppConfig.notInDND(c) && mAppConfig.inmsg_tips) { AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, true); tPools.execute(new NumberMsg(mAppConfig.lastSms.getName(), false)); } else { inMsgTipsFlow = 0; } } @Override public void receiveSms(SmsInfo sms, StringBuilder number) { isSmsReceiverValid = true; Contact c = AppConfig.mContactUtils.getContactByNum(number); if (c == null) { c = new Contact(); c.setName(number.toString()); List<ContactNum> codes = new ArrayList<>(); ContactNum contactNum = new ContactNum(); contactNum.setNumber(c.getName()); codes.add(contactNum); c.setCodes(codes); sms.setName(AssistantService.UNKOWN_NAME); } else { sms.setName(c.getName()); } sms.setNumber(number.toString()); sms.setType(1); sms.setContact(c); if (voiceMediator.mobileRing() || voiceMediator.isCalling() || inMsgTipsFlow > 0) {//通话中,响铃中,来信提示中,均不允许新来的短信打断 mAppConfig.missedMsgs.offer(sms); } else { inMsgTipsFlow = 1; mAppConfig.lastSms.setTime(sms.getTime()); mAppConfig.lastSms.setContent(sms.getContent()); mAppConfig.lastSms.setNumber(sms.getNumber()); mAppConfig.lastSms.setName(sms.getName()); mAppConfig.lastSms.setType(sms.getType()); mAppConfig.lastSms.setContact(sms.getContact()); if (mAppConfig.notInDND(c) /*&& mAppConfig.CardMode*/ && mAppConfig.inmsg_tips) { AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, true); tPools.execute(new NumberMsg(mAppConfig.lastSms.getName(), false)); } else { inMsgTipsFlow = 0; } } Single.just(0) .delay(1, TimeUnit.SECONDS) .doOnSuccess(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { CallAndSmsDao.getInstance(mContext).sync(CallAndSmsDao.getInstance(mContext).getSyncDao(CallAndSmsDao.MessageDao.class)); } }) .subscribeOn(Schedulers.io()) .subscribe(); } /** * 手机短信数据库变化观察者(与内容观察者配合,动态响应数据变化) **/ class SmsObserver extends ContentObserver { public SmsObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { Log.e(TAG, "SmsObserver>>>>onChange>>" + Boolean.toString(selfChange)); if (isSmsReceiverValid) { //若已被短信广播接收者拦截则不需要再处理 isSmsReceiverValid = false; return; } CallAndSmsDao.getInstance(mContext).sync(CallAndSmsDao.getInstance(mContext).getSyncDao(CallAndSmsDao.MessageDao.class)); super.onChange(selfChange); if (!selfChange) { long t = mAppConfig.lastSms.getTime(); SmsInfo sms = new SmsInfo(); if (t == AppConfig.mContactUtils.getLastMessage(t, sms)) { Log.e(TAG, "SmsObserver>>>>onChange>>重复触发"); return; } if (voiceMediator.mobileRing() || voiceMediator.isCalling() || inMsgTipsFlow > 0) {//通话中,响铃中,来信提示中,均不允许新来的短信打断 mAppConfig.missedMsgs.offer(sms); } else { inMsgTipsFlow = 1; mAppConfig.lastSms.setTime(sms.getTime()); mAppConfig.lastSms.setContent(sms.getContent()); mAppConfig.lastSms.setNumber(sms.getNumber()); mAppConfig.lastSms.setName(sms.getName()); mAppConfig.lastSms.setType(sms.getType()); mAppConfig.lastSms.setContact(sms.getContact()); mHandler.sendEmptyMessage(1); } } } } private class ContactObserver extends ContentObserver { public ContactObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.i("LingJu", "ContactObserver onChange()>> " + selfChange); if (!selfChange) CallAndSmsDao.getInstance(mContext).sync(CallAndSmsDao.getInstance(mContext).getSyncDao(CallAndSmsDao.ContactsDao.class)); } } /** * 监听电话的接听和结束事件 */ private void phoneCallListener() { //电话状态监听 TelephonyManager telManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); telManager.listen(new MobliePhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE); } /** * 监听电话的接听和结束事件的具体实现 * * @author Administrator */ class MobliePhoneStateListener extends PhoneStateListener { private boolean playing = false; private boolean preCall = false; private int ringMode; @Override public void onCallStateChanged(int state, String incomingNumber) { AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mobileState = state; if (mAppConfig == null) return; switch (mobileState) { case TelephonyManager.CALL_STATE_IDLE: //无任何状态时 Log.e("MobliePhoneStateListener", "电话空闲的时候>> " + preCall); voiceMediator.setMobileRing(false); voiceMediator.setCalling(false); if (!preCall) { //通话前空闲 return; } /* 通话后空闲 */ preCall = false; mAppConfig.speaker_on_one = false; //closeSpeaker(); if (ringMode == AudioManager.RINGER_MODE_NORMAL) { if (mAppConfig.incoming_tips) { //电话铃声静音 mAudioManager.setStreamMute(AudioManager.STREAM_RING, false); } } if ((mAppConfig.incoming_speaker_on || voiceMediator.isWakeUpMode()) && !voiceMediator.isHeadset() && ringMode == AudioManager.RINGER_MODE_NORMAL) { mAudioManager.setSpeakerphoneOn(false); } if (playing) { playing = false; LingjuAudioPlayer.get().play(); } else if (SynthesizerBase.get() != null) { Intent intent = new Intent(mContext, AssistantService.class); intent.putExtra(AssistantService.CMD, AssistantService.ServiceCmd.SEND_TO_ROBOT_FOR_END_TASK); intent.putExtra(AssistantService.END_TASK, false); mContext.startService(intent); } //同步通话记录 CallAndSmsDao.getInstance(mContext).sync(CallAndSmsDao.getInstance(mContext).getSyncDao(CallAndSmsDao.CallLogDao.class)); missedContact(); break; case TelephonyManager.CALL_STATE_OFFHOOK: Log.e("MobliePhoneStateListener", "电话接通的时候"); voiceMediator.setMobileRing(true); voiceMediator.setCalling(false); if (mAppConfig.missedCallContacts.size() == 1) mAppConfig.missedCallContacts.clear(); voiceMediator.stopRecognize(); voiceMediator.stopSynthesize(); //mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); if (mAppConfig.speaker_on_one || ((mAppConfig.incoming_speaker_on || voiceMediator.isWakeUpMode()) && ringMode == AudioManager.RINGER_MODE_NORMAL && !voiceMediator.isHeadset())) { tPools.execute(new Runnable() { @Override public void run() { try { Log.e(TAG, "CALL_STATE_OFFHOOK openSpeaker"); if (voiceMediator.openSpeaker()) return; int i = 3; while (i-- > 0) { Log.e(TAG, "sleep 500ms to openSpeaker"); Thread.sleep(500); if (voiceMediator.openSpeaker()) break; } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } preCall = true; if (LingjuAudioPlayer.get().isPlaying()) { playing = true; LingjuAudioPlayer.get().pause(); } break; case TelephonyManager.CALL_STATE_RINGING: Log.e("MobliePhoneStateListener", "电话忙的时候"); //mobileRing=true; voiceMediator.setCalling(true); preCall = true; if (LingjuAudioPlayer.get().isPlaying()) { playing = true; LingjuAudioPlayer.get().pause(); } voiceMediator.stopRecognize(); voiceMediator.stopSynthesize(); voiceMediator.stopWakenup(); StringBuilder number = new StringBuilder(incomingNumber); if (incomingNumber.startsWith("+86")) number.delete(0, 3); Contact c = AppConfig.mContactUtils.getContactByNum(number); String name = number.toString(); if (c != null) { name = c.getName(); Log.e(TAG, "name=" + name + ",number=" + number); AppConfig.mContactUtils.reSortList(c, number.toString(), System.currentTimeMillis()); } else { c = new Contact(); c.setName(number.toString()); List<ContactNum> codes = new ArrayList<>(); ContactNum contactNum = new ContactNum(); contactNum.setNumber(number.toString()); codes.add(contactNum); c.setCodes(codes); } if (voiceMediator.mobileRing()) { Log.w(TAG, "当前正在通话中,此时又来了电话"); mAppConfig.missedCallContacts.offer(c); } else { voiceMediator.setMobileRing(true); ringMode = mAudioManager.getRingerMode(); if (mAppConfig.notInDND(c) && ringMode == AudioManager.RINGER_MODE_NORMAL) { if (mAppConfig.incoming_tips) { //静音 mAudioManager.setStreamMute(AudioManager.STREAM_RING, true); tPools.execute(new NumberMsg(name, true)); } } if (mAppConfig.incoming_speaker_on || (!mAudioManager.isSpeakerphoneOn() && (mAppConfig.incoming_speaker_on || voiceMediator.isWakeUpMode()) && !voiceMediator.isHeadset() && ringMode == AudioManager.RINGER_MODE_NORMAL)) { mAudioManager.setSpeakerphoneOn(true); } } break; default: break; } Log.e("MobliePhoneStateListener", "Incoming number " + incomingNumber); //incomingNumber就是来电号码 } } /** * 来电、接收短信通知播报 **/ class NumberMsg implements Runnable { private String name; private boolean isCall; public NumberMsg(String name, boolean call) { this.name = name; this.isCall = call; } @Override public void run() { voiceMediator.stopWakenup(); String text; SpeechMsgBuilder msgBuilder = SpeechMsgBuilder.create(null); if (isCall) { try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (mobileState != TelephonyManager.CALL_STATE_RINGING) { return; } text = "您有电话来自" + name + ",请点击屏幕接通电话!"; /* 获取来电播报次数 */ int times = AppConfig.dPreferences.getInt(AppConfig.INCOMING_TIPS_TIMES, 0); switch (times) { case R.id.aitt_button1: times = 1; break; case R.id.aitt_button2: times = 2; break; case R.id.aitt_button3: times = 3; break; case R.id.aitt_button4: times = 6; break; default: times = 2; break; } StringBuilder sb = new StringBuilder(); while (times-- > 0) { sb.append(text); } text = sb.toString(); msgBuilder.setForceLocalEngine(true); msgBuilder.setContextMode(SpeechMsg.CONTEXT_AUTO); } else { Intent smsIntent = new Intent(mContext, AssistantService.class); smsIntent.putExtra(AssistantService.CMD, AssistantService.ServiceCmd.PUSH_ROUTE_CACULATE); smsIntent.putExtra(AssistantService.TEXT, "有短信发来3"); text = "您有短信来自" + name + ",如果需要朗读,请对我说朗读短信!"; msgBuilder.setContextMode(SpeechMsg.CONTEXT_KEEP_RECOGNIZE); msgBuilder.setForceLocalEngine(true); } // final AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); // current_volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); // if (!voiceMediator.isHeadset()) { // mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, current_volume, 0); // } msgBuilder.setText(text); Observable<SpeechMsg> msgObservable = SynthesizerBase.get().addMessageWaitSpeak(msgBuilder.build()); if (msgObservable != null) { msgObservable.doOnComplete(new Action() { @Override public void run() throws Exception { // if (!voiceMediator.isHeadset()) // mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, current_volume, 0); } }) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) .subscribe(); } } } }