/** * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr) * This file is part of CSipSimple. * * CSipSimple is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * If you own a pjsip commercial license you can also redistribute it * and/or modify it under the terms of the GNU Lesser General Public License * as an android library. * * CSipSimple 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CSipSimple. If not, see <http://www.gnu.org/licenses/>. */ package com.csipsimple.ui.outgoingcall; import android.annotation.TargetApi; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.text.TextUtils; import android.view.KeyEvent; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.csipsimple.R; import com.csipsimple.api.ISipService; import com.csipsimple.api.SipManager; import com.csipsimple.api.SipProfile; import com.csipsimple.utils.Compatibility; import com.csipsimple.utils.Log; import com.csipsimple.utils.PreferencesProviderWrapper; import com.csipsimple.utils.UriUtils; public class OutgoingCallChooser extends SherlockFragmentActivity { private static final String THIS_FILE = "OutgoingCallChooser"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); resetInternals(); // Sanity check if (TextUtils.isEmpty(getPhoneNumber())) { Log.e(THIS_FILE, "No number detected for : " + getIntent().getAction()); finish(); return; } setContentView(R.layout.outgoing_call_view); connectService(); } private String phoneNumber = null; private boolean ignoreRewritingRules = false; private Long accountToCallTo = null; private Boolean callAutomatically = null; @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); resetInternals(); } private final static String SCHEME_CSIP = SipManager.PROTOCOL_CSIP; /** * Get the phone number that raised this activity. * @return The phone number we are trying to call with this activity */ public String getPhoneNumber() { if(phoneNumber == null) { Intent it = getIntent(); // Use utility function to extract number phoneNumber = UriUtils.extractNumberFromIntent(it, this); // Additional check to know if a csip uri (so that no rewriting rules applies) if (phoneNumber != null) { String action = it.getAction(); Uri data = it.getData(); if(!Intent.ACTION_SENDTO.equalsIgnoreCase(action) && data != null) { String scheme = data.getScheme(); if(scheme != null) { scheme = scheme.toLowerCase(); } if(SCHEME_CSIP.equals(scheme)) { ignoreRewritingRules = true; } } } // Still null ... well make it empty. if(phoneNumber == null) { phoneNumber = ""; } return phoneNumber; } return phoneNumber; } /** * Should we ignore rewriting rules * @return True if rewriting rules are not taken into account for this outgoing call. */ public boolean shouldIgnoreRewritingRules() { // Ignore rewriting rule is get once phone number is retrieved getPhoneNumber(); return ignoreRewritingRules; } /** * Get the account to force use for outgoing. * @return The account id to use for outgoing. {@link SipProfile#INVALID_ID} if no account should be used. */ public long getAccountToCallTo() { if(accountToCallTo == null) { accountToCallTo = getIntent().getLongExtra(SipProfile.FIELD_ACC_ID, SipProfile.INVALID_ID); } return accountToCallTo; } /** * Should we allow automatic calls of others accounts * @return True if we can call automatically some accounts. */ public boolean canCallAutomatically() { if(callAutomatically == null) { if(getAccountToCallTo() == SipProfile.INVALID_ID) { // No account specified, we can call automatically callAutomatically = true; }else { int fallbackBehavior = getIntent().getIntExtra(SipManager.EXTRA_FALLBACK_BEHAVIOR, SipManager.FALLBACK_ASK); if(fallbackBehavior == SipManager.FALLBACK_AUTO_CALL_OTHER) { // The other app explicitely asked to fallback to other callAutomatically = true; }else { callAutomatically = false; } } } return callAutomatically; } /* Service connection */ /** * Connect to sip service by flagging itself as the component to consider as outgoing activity */ private void connectService() { PreferencesProviderWrapper prefsWrapper = new PreferencesProviderWrapper(this); Intent sipService = new Intent(SipManager.INTENT_SIP_SERVICE); // Optional, but here we bundle so just ensure we are using csipsimple package sipService.setPackage(getPackageName()); if (prefsWrapper.isValidConnectionForOutgoing()) { sipService.putExtra(SipManager.EXTRA_OUTGOING_ACTIVITY, getComponentName()); startService(sipService); } bindService(sipService, connection, Context.BIND_AUTO_CREATE); } /** * Get connected sip service. * @return connected sip service from the activity if already connected. Null else. */ public ISipService getConnectedService() { return service; } private ISipService service = null; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName component, IBinder binder) { service = ISipService.Stub.asInterface(binder); } @Override public void onServiceDisconnected(ComponentName arg0) { service = null; } }; @TargetApi(5) public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 && !Compatibility.isCompatible(5)) { onBackPressed(); } return super.onKeyDown(keyCode, event); } public void onBackPressed() { finishServiceIfNeeded(false); } /** * Finish the activity and send unregistration to service as outgoing activity. * @param defer If true the activity will ask sip service to remain active until end of next call (because it will initiate a call). * If false, ask sip service to consider outgoing mode as not anymore valid right now. Usually cause call will be managed another way than a sip way. */ public void finishServiceIfNeeded(boolean defer) { Intent intent = new Intent(defer ? SipManager.ACTION_DEFER_OUTGOING_UNREGISTER : SipManager.ACTION_OUTGOING_UNREGISTER); intent.putExtra(SipManager.EXTRA_OUTGOING_ACTIVITY, getComponentName()); sendBroadcast(intent); finish(); } @Override protected void onDestroy() { super.onDestroy(); resetInternals(); try { unbindService(connection); } catch (Exception e) { } } private void resetInternals() { phoneNumber = null; accountToCallTo = null; ignoreRewritingRules = false; callAutomatically = null; } }