/** * Odoo, Open Source Management Solution * Copyright (C) 2012-today Odoo SA (<http:www.odoo.com>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http:www.gnu.org/licenses/> * * Created on 13/1/15 6:12 PM */ package com.odoo.addons.phonecall.features.receivers; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import com.odoo.addons.phonecall.PhoneCallDetail; import com.odoo.addons.phonecall.features.CallerWindow; import com.odoo.addons.phonecall.features.CustomerFinder; import com.odoo.addons.phonecall.features.IOnCustomerFindListener; import com.odoo.core.orm.ODataRow; import com.odoo.core.support.OUser; import com.odoo.core.utils.OPreferenceManager; import com.odoo.core.utils.OResource; import com.odoo.core.utils.notification.ONotificationBuilder; import com.odoo.R; import java.util.Date; public class PhoneStateReceiver extends BroadcastReceiver implements IOnCustomerFindListener { public static final String TAG = PhoneStateReceiver.class.getSimpleName(); public static final String ACTION_CALL_BACK = "action_call_back"; public static final String ACTION_CALL_SCHEDULE = "action_call_schedule"; public static final Integer REQUEST_CALL_BACK = 5567; public static final Integer REQUEST_CALL_SCHEDULE = 5568; public static final String KEY_RECEIVED = "phone_state_received"; public static final String KEY_RINGING = "phone_state_ringing"; public static final String KEY_OFFHOOK = "phone_state_offhook"; public static final String KEY_DURATION_START = "key_duration_start"; public static final String KEY_DURATION_END = "key_duration_end"; public static final String KEY_ACTIVITY_STARTED = "key_activity_started"; private String callerNumber = null; private TelephonyManager telephonyManager; private OPreferenceManager mPref; private static CallerWindow callerWindow; private CustomerFinder customerFinder; private Context mContext; private Bundle extra = null; @Override public void onReceive(Context context, Intent intent) { mContext = context; if (OUser.current(mContext) != null) { Log.v(TAG, "Phone state received."); mPref = new OPreferenceManager(context); if (callerWindow == null) callerWindow = new CallerWindow(context); customerFinder = new CustomerFinder(context); customerFinder.setOnCustomerFindListener(this); if (mPref.getBoolean(KEY_RECEIVED, true) && !callerWindow.isShowing()) { mPref.setBoolean(KEY_RECEIVED, false); mPref.setBoolean(KEY_RINGING, false); } if (!mPref.getBoolean(KEY_RECEIVED, false)) { telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); Bundle bundle = intent.getExtras(); callerNumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER); if (callerNumber != null) { telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); } mPref.setBoolean(KEY_RECEIVED, true); } } } PhoneStateListener phoneStateListener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: Log.i(TAG, callerNumber + " CALL_STATE_IDLE"); mPref.setBoolean(KEY_RECEIVED, false); mPref.setBoolean(KEY_RINGING, false); if (extra != null) { extra.putBoolean("in_bound", mPref.getBoolean("in_bound", false)); extra.putString(KEY_DURATION_END, new Date().getTime() + ""); } if (!mPref.getBoolean(KEY_OFFHOOK, false)) { showMissCallNotification(extra); } else { startLogCallActivity(extra); } if (callerWindow != null) callerWindow.dismiss(); callerWindow = null; customerFinder = null; extra = null; break; case TelephonyManager.CALL_STATE_OFFHOOK: Log.i(TAG, callerNumber + " CALL_STATE_OFFHOOK"); mPref.setBoolean(KEY_OFFHOOK, true); // Call Started (received or dialed) callStarted(); if (!mPref.getBoolean(KEY_RINGING, false)) { mPref.setBoolean("in_bound", false); if (customerFinder != null) customerFinder.findCustomer(true, callerNumber); } break; case TelephonyManager.CALL_STATE_RINGING: Log.i(TAG, callerNumber + " CALL_STATE_RINGING"); mPref.setBoolean(KEY_RINGING, true); mPref.setBoolean(KEY_OFFHOOK, false); mPref.setBoolean("notified", false); mPref.setBoolean("in_bound", true); if (customerFinder != null) customerFinder.findCustomer(false, callerNumber); break; } } }; private void showMissCallNotification(Bundle data) { mPref.setBoolean(KEY_OFFHOOK, false); if (data != null && !mPref.getBoolean("notified", false)) { mPref.setBoolean("notified", true); int notification_id = 55568; ONotificationBuilder builder = new ONotificationBuilder(mContext, notification_id); data.putInt("notification_id", notification_id); builder.setTitle(_s(R.string.label_missed_call_from_customer)); builder.setIcon(R.drawable.ic_action_user); builder.setText(data.getString("name")); ONotificationBuilder.NotificationAction callBack = new ONotificationBuilder.NotificationAction(R.drawable.ic_action_phone, "Call back", REQUEST_CALL_BACK, ACTION_CALL_BACK, PhoneCallDetail.class, data); builder.addAction(callBack); data.putBoolean(PhoneCallDetail.KEY_LOG_CALL_REQUEST, true); data.putString(PhoneCallDetail.KEY_PHONE_NUMBER, callerNumber); data.putInt(PhoneCallDetail.KEY_OPPORTUNITY_ID, data.getInt("opportunity_id")); ONotificationBuilder.NotificationAction scheduleCall = new ONotificationBuilder.NotificationAction(R.drawable.ic_action_reschedule, "Schedule", REQUEST_CALL_SCHEDULE, ACTION_CALL_SCHEDULE, PhoneCallDetail.class, data); builder.addAction(scheduleCall); builder.allowVibrate(false); builder.build().show(); } } public String _s(int res_id) { return OResource.string(mContext, res_id); } private void startLogCallActivity(Bundle data) { if (data != null && !mPref.getBoolean(KEY_ACTIVITY_STARTED, false)) { mPref.setBoolean(KEY_ACTIVITY_STARTED, true); Intent intent = new Intent(mContext, PhoneCallDetail.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); data.putBoolean(PhoneCallDetail.KEY_LOG_CALL_REQUEST, true); data.putString(PhoneCallDetail.KEY_PHONE_NUMBER, callerNumber); data.putInt(PhoneCallDetail.KEY_OPPORTUNITY_ID, data.getInt("opportunity_id")); intent.putExtras(data); mContext.startActivity(intent); } } private void callStarted() { if (extra != null && !extra.containsKey(KEY_DURATION_START)) { extra.putString(KEY_DURATION_START, new Date().getTime() + ""); } } @Override public void onCustomerFind(Boolean dialed, ODataRow row) { if (row != null) { extra = new Bundle(); extra = row.getPrimaryBundleData(); callStarted(); extra.putString("name", row.getString("name")); int row_id = (row.getString("opportunity_id").equals("false")) ? -1 : row.getInt("opportunity_id"); extra.putInt("opportunity_id", row_id); row.put("caller_contact", callerNumber); if(callerWindow!=null) { callerWindow.show(dialed, row); mPref.setBoolean(KEY_ACTIVITY_STARTED, false); } } } }