diff --git a/AndroidManifest.xml b/AndroidManifest.xml index b176dff05..c44111fef 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3,24 +3,88 @@ package="org.linphone" android:versionCode="1103" android:versionName="1.1.3" android:installLocation="auto"> - + + + + - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -128,8 +149,6 @@ - - diff --git a/src/org/linphone/AboutActivity.java b/src/org/linphone/AboutActivity.java index 290d82656..e01c5086e 100644 --- a/src/org/linphone/AboutActivity.java +++ b/src/org/linphone/AboutActivity.java @@ -35,7 +35,7 @@ public class AboutActivity extends Activity { try { aboutText.setText(String.format(getString(R.string.about_text), getPackageManager().getPackageInfo(getPackageName(), 0).versionName)); } catch (NameNotFoundException e) { - Log.e(LinphoneService.TAG, "cannot get version name", e); + Log.e(LinphoneManager.TAG, "cannot get version name", e); } } diff --git a/src/org/linphone/BandwidthManager.java b/src/org/linphone/BandwidthManager.java index 2ebf5d112..9d0bb5bb0 100644 --- a/src/org/linphone/BandwidthManager.java +++ b/src/org/linphone/BandwidthManager.java @@ -65,7 +65,7 @@ public class BandwidthManager { } private void onProfileChanged(int newProfile) { - LinphoneCore lc = LinphoneService.instance().getLinphoneCore(); + LinphoneCore lc = LinphoneManager.getLc(); lc.setUploadBandwidth(bandwidthes[newProfile][0]); lc.setDownloadBandwidth(bandwidthes[newProfile][1]); diff --git a/src/org/linphone/CallManager.java b/src/org/linphone/CallManager.java index 63ce9c88d..a1e9a3feb 100644 --- a/src/org/linphone/CallManager.java +++ b/src/org/linphone/CallManager.java @@ -31,7 +31,7 @@ import org.linphone.core.LinphoneCoreException; * @author Guillaume Beraudo * */ -public class CallManager { +class CallManager { private static CallManager instance; @@ -41,9 +41,6 @@ public class CallManager { return instance; } - private LinphoneCore lc() { - return LinphoneService.instance().getLinphoneCore(); - } private AndroidCameraRecordManager videoManager() { return AndroidCameraRecordManager.getInstance(); } @@ -54,8 +51,8 @@ public class CallManager { - public void inviteAddress(LinphoneAddress lAddress, boolean videoEnabled) throws LinphoneCoreException { - LinphoneCore lc = lc(); + void inviteAddress(LinphoneAddress lAddress, boolean videoEnabled) throws LinphoneCoreException { + LinphoneCore lc = LinphoneManager.getLc(); LinphoneCallParams params = lc.createDefaultCallParameters(); bm().updateWithProfileSettings(lc, params); @@ -79,8 +76,8 @@ public class CallManager { * or if the bandwidth settings are too low. * @return if updateCall called */ - public boolean reinviteWithVideo() { - LinphoneCore lc = lc(); + boolean reinviteWithVideo() { + LinphoneCore lc = LinphoneManager.getLc(); LinphoneCall lCall = lc.getCurrentCall(); LinphoneCallParams params = lCall.getCurrentParamsCopy(); @@ -105,8 +102,8 @@ public class CallManager { /** * Re-invite with parameters updated from profile. */ - public void reinvite() { - LinphoneCore lc = lc(); + void reinvite() { + LinphoneCore lc = LinphoneManager.getLc(); LinphoneCall lCall = lc.getCurrentCall(); LinphoneCallParams params = lCall.getCurrentParamsCopy(); bm().updateWithProfileSettings(lc, params); @@ -117,8 +114,8 @@ public class CallManager { * Update current call, without reinvite. * The camera will be restarted when mediastreamer chain is recreated and setParameters is called. */ - public void updateCall() { - LinphoneCore lc = lc(); + void updateCall() { + LinphoneCore lc = LinphoneManager.getLc(); LinphoneCall lCall = lc.getCurrentCall(); LinphoneCallParams params = lCall.getCurrentParamsCopy(); bm().updateWithProfileSettings(lc, params); diff --git a/src/org/linphone/ContactPickerActivity.java b/src/org/linphone/ContactPickerActivity.java index ad3d0392d..99604ef6c 100644 --- a/src/org/linphone/ContactPickerActivity.java +++ b/src/org/linphone/ContactPickerActivity.java @@ -63,7 +63,7 @@ public class ContactPickerActivity extends Activity { // Get the field values lName = lCur.getString(lCur.getColumnIndex(People.NAME)); lPhoneNo = lCur.getString(lCur.getColumnIndex(People.NUMBER)); - DialerActivity.getDialer().setContactAddress(lPhoneNo, lName); + DialerActivity.instance().setContactAddress(lPhoneNo, lName); } } diff --git a/src/org/linphone/DialerActivity.java b/src/org/linphone/DialerActivity.java index 34097126e..03181ef68 100644 --- a/src/org/linphone/DialerActivity.java +++ b/src/org/linphone/DialerActivity.java @@ -19,16 +19,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package org.linphone; import org.linphone.LinphoneManager.NewOutgoingCallUiListener; +import org.linphone.LinphoneService.LinphoneGuiListener; import org.linphone.core.AndroidCameraRecordManager; -import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneCall; -import org.linphone.core.LinphoneChatRoom; import org.linphone.core.LinphoneCore; -import org.linphone.core.LinphoneCoreListener; -import org.linphone.core.LinphoneFriend; -import org.linphone.core.LinphoneProxyConfig; import org.linphone.core.LinphoneCall.State; -import org.linphone.core.LinphoneCore.EcCalibratorStatus; import org.linphone.ui.AddVideoButton; import org.linphone.ui.AddressText; import org.linphone.ui.CallButton; @@ -37,7 +32,6 @@ import org.linphone.ui.EraseButton; import org.linphone.ui.MuteMicButton; import org.linphone.ui.SpeakerButton; import org.linphone.ui.AddVideoButton.AlreadyInVideoCallListener; -import org.linphone.ui.CallButton.CallButtonListener; import android.app.Activity; import android.app.AlertDialog; @@ -57,7 +51,19 @@ import android.widget.TableRow; import android.widget.TextView; import android.widget.Toast; -public class DialerActivity extends Activity implements LinphoneCoreListener, AlreadyInVideoCallListener, CallButtonListener, NewOutgoingCallUiListener { +/** + * + * Dialer and main activity of Linphone Android. + * + * Roles are:
    + *
  • Display the numpad, call/accept, address buttons
  • + *
  • Define preferences through the menu
  • + *
  • React to bad preference / no account set
  • + *
  • Manage first launch
  • + *
+ * + */ +public class DialerActivity extends Activity implements LinphoneGuiListener, AlreadyInVideoCallListener, NewOutgoingCallUiListener { private AddressText mAddress; private TextView mDisplayNameView; @@ -75,7 +81,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al private View mAddressLayout; private View mInCallAddressLayout; - private static DialerActivity theDialer; + private static DialerActivity instance; private PowerManager.WakeLock mWakeLock; private SharedPreferences mPref; @@ -87,68 +93,68 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al private static String CURRENT_DISPLAYNAME = "org.linphone.current-displayname"; static int VIDEO_VIEW_ACTIVITY = 100; - private static boolean accountCheckingDone; + private static boolean checkAccount = true; /** * @return null if not ready yet */ - public static DialerActivity getDialer() { - return theDialer; + public static DialerActivity instance() { + return instance; } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dialer); - mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - LinphoneManager.getInstance().setUsefullStuff(am, mPref, getWindowManager(), getResources()); + + // Don't use Linphone Manager in the onCreate as it takes time in LinphoneService to initialize it. + + mPref = PreferenceManager.getDefaultSharedPreferences(this); PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone"); + + mAddress = (AddressText) findViewById(R.id.SipUri); + mDisplayNameView = (TextView) findViewById(R.id.DisplayNameView); + ((EraseButton) findViewById(R.id.Erase)).setAddressView(mAddress); + + + mAddVideo = (AddVideoButton) findViewById(R.id.AddVideo); + mAddVideo.setOnAlreadyInVideoCallListener(this); + + + mCall = (CallButton) findViewById(R.id.Call); + mCall.setAddressWidget(mAddress); + + + mDecline= findViewById(R.id.Decline); + mDecline.setEnabled(false); + + + mHangup = findViewById(R.id.HangUp); + + + mCallControlRow = (LinearLayout) findViewById(R.id.CallControlRow); + mAddressLayout = (View) findViewById(R.id.Addresslayout); + + mInCallControlRow = (TableRow) findViewById(R.id.IncallControlRow); + mInCallControlRow.setVisibility(View.GONE); + mInCallAddressLayout = (View) findViewById(R.id.IncallAddressLayout); + mInCallAddressLayout.setVisibility(View.GONE); + mMute = (MuteMicButton)findViewById(R.id.mic_mute_button); + mSpeaker = (SpeakerButton)findViewById(R.id.speaker_button); + + try { - mAddress = (AddressText) findViewById(R.id.SipUri); - mDisplayNameView = (TextView) findViewById(R.id.DisplayNameView); - ((EraseButton) findViewById(R.id.Erase)).setAddressView(mAddress); - - mAddVideo = (AddVideoButton) findViewById(R.id.AddVideo); - mAddVideo.setOnAlreadyInVideoCallListener(this); + outgoingCallIntentReceived(); - - - mCall = (CallButton) findViewById(R.id.Call); - mCall.setCallButtonListerner(this); - mCall.setAddressWidget(mAddress); - - mDecline= findViewById(R.id.Decline); - mDecline.setEnabled(false); - - mHangup = findViewById(R.id.HangUp); - - - mCallControlRow = (LinearLayout) findViewById(R.id.CallControlRow); - mAddressLayout = (View) findViewById(R.id.Addresslayout); - - mInCallControlRow = (TableRow) findViewById(R.id.IncallControlRow); - mInCallControlRow.setVisibility(View.GONE); - mInCallAddressLayout = (View) findViewById(R.id.IncallAddressLayout); - mInCallAddressLayout.setVisibility(View.GONE); - mMute = (MuteMicButton)findViewById(R.id.mic_mute_button); - mSpeaker = (SpeakerButton)findViewById(R.id.speaker_button); - - - if (LinphoneService.isready() && getIntent().getData() != null && !LinphoneService.getLc().isIncall()) { - newOutgoingCall(getIntent().getData().toString().substring("tel://".length())); - getIntent().setData(null); - } - - if (LinphoneService.isready()) { - LinphoneCore lc = LinphoneService.getLc(); + if (LinphoneService.isReady()) { + LinphoneCore lc = LinphoneManager.getLc(); if (lc.isIncall()) { if(lc.isInComingInvitePending()) { callPending(lc.getCurrentCall()); @@ -160,54 +166,47 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al mInCallControlRow.setVisibility(View.VISIBLE); mAddressLayout.setVisibility(View.GONE); mInCallAddressLayout.setVisibility(View.VISIBLE); - - String DisplayName = lc.getRemoteAddress().getDisplayName(); - if (DisplayName!=null) { - mDisplayNameView.setText(DisplayName); - } else { - mDisplayNameView.setText(lc.getRemoteAddress().getUserName()); - } - loadMicAndSpeakerUiStateFromLibrary(); + mDisplayNameView.setText(LinphoneManager.getInstance().extractADisplayName()); + loadMicAndSpeakerUiStateFromManager(); LinphoneActivity.instance().startProxymitySensor(); mWakeLock.acquire(); } } } - - if (findViewById(R.id.Digit00) != null) { // In landscape view, no keyboard - ((Digit) findViewById(R.id.Digit00)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit1)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit2)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit3)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit4)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit5)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit6)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit7)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit8)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.Digit9)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.DigitStar)).setAddressWidget(mAddress); - ((Digit) findViewById(R.id.DigitHash)).setAddressWidget(mAddress); - } - - - mStatus = (TextView) findViewById(R.id.status_label); - theDialer = this; + instance = this; } catch (Exception e) { - Log.e(LinphoneService.TAG,"Cannot start linphone",e); + Log.e(LinphoneManager.TAG,"Cannot start linphone",e); finish(); } - if (!accountCheckingDone) { + if (findViewById(R.id.Digit00) != null) { // In landscape view, no keyboard + ((Digit) findViewById(R.id.Digit00)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit1)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit2)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit3)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit4)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit5)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit6)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit7)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit8)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.Digit9)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.DigitStar)).setAddressWidget(mAddress); + ((Digit) findViewById(R.id.DigitHash)).setAddressWidget(mAddress); + } + mStatus = (TextView) findViewById(R.id.status_label); + + + if (checkAccount) { if (mPref.getBoolean(PREF_FIRST_LAUNCH, true)) { onFirstLaunch(); } else if (!mPref.getBoolean(PREF_CHECK_CONFIG, false) && !checkDefined(R.string.pref_username_key, R.string.pref_passwd_key, R.string.pref_domain_key)) { onBadSettings(); } else { - accountCheckingDone = true; + checkAccount = false; } } } @@ -215,7 +214,20 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al + private void outgoingCallIntentReceived() { + if (getIntent().getData() == null) return; + if (!LinphoneService.isReady() || LinphoneManager.getLc().isIncall()) { + Log.w(LinphoneManager.TAG, "Outgoing call aborted as LinphoneService" + + " is not ready or we are already in call"); + return; + } + + newOutgoingCall(getIntent()); + } + + + /***** Check Account *******/ private boolean checkDefined(int ... keys) { for (int key : keys) { String conf = mPref.getString(getString(key), null); @@ -238,7 +250,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al .setPositiveButton(getString(R.string.cont), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { LinphoneActivity.instance().startprefActivity(); - accountCheckingDone = true; + checkAccount = false; } }); @@ -258,18 +270,18 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { LinphoneActivity.instance().startprefActivity(); - accountCheckingDone = true; + checkAccount = false; } }).setNeutralButton(getString(R.string.no), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); - accountCheckingDone = true; + checkAccount = false; } }).setNegativeButton(getString(R.string.never_remind), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { mPref.edit().putBoolean(PREF_CHECK_CONFIG, true).commit(); dialog.cancel(); - accountCheckingDone = true; + checkAccount = false; } }); @@ -277,22 +289,16 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al } - private void updateIncallVideoCallButton() { - boolean prefVideoEnabled = mPref.getBoolean(getString(R.string.pref_video_enable_key), false); - if (prefVideoEnabled && !mCall.isEnabled()) { - mAddVideo.setVisibility(View.VISIBLE); - mAddVideo.setEnabled(true); - } else { - mAddVideo.setVisibility(View.GONE); - } - } + + + @Override public void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); - savedInstanceState.putString(CURRENT_ADDRESS, mAddress.getText().toString()); + savedInstanceState.putCharSequence(CURRENT_ADDRESS, mAddress.getText()); if (mAddress.getDisplayedName() != null) savedInstanceState.putString(CURRENT_DISPLAYNAME,mAddress.getDisplayedName()); } @@ -300,7 +306,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); - String lAddress = savedInstanceState.getString(CURRENT_ADDRESS); + CharSequence lAddress = savedInstanceState.getCharSequence(CURRENT_ADDRESS); if (lAddress != null && mAddress != null) { mAddress.setText(lAddress); } @@ -312,7 +318,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al protected void onDestroy() { super.onDestroy(); if (mWakeLock.isHeld()) mWakeLock.release(); - theDialer=null; + instance=null; } @Override @@ -321,32 +327,10 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al } - public void authInfoRequested(LinphoneCore lc, String realm, String username) /*nop*/{} - public void byeReceived(LinphoneCore lc, String from) {/*nop*/} - public void displayMessage(LinphoneCore lc, String message) {/*nop*/} - public void displayWarning(LinphoneCore lc, String message) {/*nop*/} - public void displayStatus(LinphoneCore lc, String message) { - mStatus.setText(message); - } - public void globalState(LinphoneCore lc, LinphoneCore.GlobalState state, String message) { - if (state == LinphoneCore.GlobalState.GlobalOn) { - mCall.setEnabled(!lc.isIncall()); - mHangup.setEnabled(!mCall.isEnabled()); - updateIncallVideoCallButton(); - try{ - LinphoneService.instance().initFromConf(); - } catch (Exception e) { - Log.e(LinphoneService.TAG,"Cannot get initial config", e); - } - if (getIntent().getData() != null) { - newOutgoingCall(getIntent().getData().toString().substring("tel://".length())); - getIntent().setData(null); - } - } - } + private void startVideoView(int requestCode) { Intent lIntent = new Intent(); @@ -354,10 +338,132 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al startActivityForResult(lIntent,requestCode); } - public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig cfg,final LinphoneCore.RegistrationState state,final String smessage) {/*nop*/}; + + private void enterIncallMode(LinphoneCore lc) { + LinphoneManager m = LinphoneManager.getInstance(); + mCallControlRow.setVisibility(View.GONE); + mInCallControlRow.setVisibility(View.VISIBLE); + mAddressLayout.setVisibility(View.GONE); + mInCallAddressLayout.setVisibility(View.VISIBLE); + mCall.setEnabled(false); + updateIncallVideoCallButton(); + mHangup.setEnabled(true); + mDisplayNameView.setText(m.extractADisplayName()); + + loadMicAndSpeakerUiStateFromManager(); + setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); + + LinphoneActivity.instance().startProxymitySensor(); + if (!mWakeLock.isHeld()) mWakeLock.acquire(); + + } + + + private void updateIncallVideoCallButton() { + boolean prefVideoEnabled = LinphoneManager.getInstance().isVideoEnabled(); + if (prefVideoEnabled && !mCall.isEnabled()) { + mAddVideo.setVisibility(View.VISIBLE); + mAddVideo.setEnabled(true); + } else { + mAddVideo.setVisibility(View.GONE); + } + } - public void callState(final LinphoneCore lc,final LinphoneCall call, final State state, final String message) { + private void loadMicAndSpeakerUiStateFromManager() { + mMute.setChecked(LinphoneManager.getLc().isMicMuted()); + mSpeaker.setSpeakerOn(LinphoneManager.getInstance().isSpeakerOn()); + } + + + private void exitCallMode() { + mCallControlRow.setVisibility(View.VISIBLE); + mInCallControlRow.setVisibility(View.GONE); + mAddressLayout.setVisibility(View.VISIBLE); + mInCallAddressLayout.setVisibility(View.GONE); + mCall.setEnabled(true); + updateIncallVideoCallButton(); + mHangup.setEnabled(false); + setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); + mDecline.setEnabled(false); + if (LinphoneManager.getLc().isVideoEnabled()) { + finishActivity(VIDEO_VIEW_ACTIVITY); + } + if (mWakeLock.isHeld())mWakeLock.release(); + mSpeaker.setSpeakerOn(false); + + BandwidthManager.getInstance().setUserRestriction(false); + LinphoneManager.getInstance().resetCameraFromPreferences(); + LinphoneActivity.instance().stopProxymitySensor(); + } + + private void callPending(LinphoneCall call) { + mDecline.setEnabled(true); + + // Privacy setting to not share the user camera by default + boolean prefVideoEnable = LinphoneManager.getInstance().isVideoEnabled(); + boolean prefAutomaticallyShareMyCamera = mPref.getBoolean(getString(R.string.pref_video_automatically_share_my_video_key), false); + AndroidCameraRecordManager.getInstance().setMuted(!(prefVideoEnable && prefAutomaticallyShareMyCamera)); + call.enableCamera(prefAutomaticallyShareMyCamera); + } + + + + + + public void newOutgoingCall(Intent intent) { + mAddress.setText(intent.getData().toString().substring("tel:".length())); + mAddress.clearDisplayedName(); + intent.setData(null); + + LinphoneManager.getInstance().newOutgoingCall(mAddress); + } + + + public void setContactAddress(String aContact,String aDisplayName) { + mAddress.setText(aContact); + mAddress.setDisplayedName(aDisplayName); + } + + + + + + + /***** GUI delegates for listener LinphoneServiceListener *************/ + public void onDisplayStatus(String message) { + mStatus.setText(message); + } + + public void onAlreadyInVideoCall() { + startVideoView(VIDEO_VIEW_ACTIVITY); + } + + public void onAlreadyInCall() { + Toast toast = Toast.makeText(this, + getString(R.string.warning_already_incall), Toast.LENGTH_LONG); + toast.show(); + } + + + public void onCannotGetCallParameters() { + Toast toast = Toast.makeText(this + ,String.format(getString(R.string.error_cannot_get_call_parameters),mAddress.getText().toString()) + ,Toast.LENGTH_LONG); + toast.show(); + } + + + public void onWrongDestinationAddress() { + Toast toast = Toast.makeText(this + ,String.format(getResources().getString(R.string.warning_wrong_destination_address),mAddress.getText().toString()) + ,Toast.LENGTH_LONG); + toast.show(); + } + + + public void onCallStateChanged(LinphoneCall call, State state, String message) { + LinphoneCore lc = LinphoneManager.getLc(); if (state == LinphoneCall.State.OutgoingInit) { enterIncallMode(lc); LinphoneManager.getInstance().routeAudioToReceiver(); @@ -376,134 +482,30 @@ public class DialerActivity extends Activity implements LinphoneCoreListener, Al } else if (state == LinphoneCall.State.CallEnd) { exitCallMode(); } else if (state == LinphoneCall.State.StreamsRunning) { - if (LinphoneService.getLc().getCurrentCall().getCurrentParamsCopy().getVideoEnabled()) { + if (LinphoneManager.getLc().getCurrentCall().getCurrentParamsCopy().getVideoEnabled()) { if (!VideoCallActivity.launched) { startVideoView(VIDEO_VIEW_ACTIVITY); } } - } + } } - public void show(LinphoneCore lc) {/*nop*/} - - private void enterIncallMode(LinphoneCore lc) { - mCallControlRow.setVisibility(View.GONE); - mInCallControlRow.setVisibility(View.VISIBLE); - mAddressLayout.setVisibility(View.GONE); - mInCallAddressLayout.setVisibility(View.VISIBLE); - mCall.setEnabled(false); + + public void onGlobalStateChangedToOn(String message) { + mCall.setEnabled(!LinphoneManager.getLc().isIncall()); + mHangup.setEnabled(!mCall.isEnabled()); updateIncallVideoCallButton(); - mHangup.setEnabled(true); - LinphoneAddress remote=lc.getRemoteAddress(); - if (remote!=null){ - String DisplayName = remote.getDisplayName(); - if (DisplayName!=null) { - mDisplayNameView.setText(DisplayName); - } else if (lc.getRemoteAddress().getUserName() != null){ - mDisplayNameView.setText(lc.getRemoteAddress().getUserName()); - } else { - mDisplayNameView.setText(lc.getRemoteAddress().toString()); - } + + try{ + LinphoneManager.getInstance().initFromConf(this); + } catch (LinphoneConfigException e) { + Log.w(LinphoneManager.TAG, "Cannot get initial config : " + e.getMessage()); + } catch (Exception e) { + Log.e(LinphoneManager.TAG, "Cannot get initial config", e); } - loadMicAndSpeakerUiStateFromLibrary(); - - if (mSpeaker.isSpeakerOn()) { - LinphoneManager.getInstance().routeAudioToSpeaker(); - } else { - LinphoneManager.getInstance().routeAudioToReceiver(); + + if (getIntent().getData() != null) { + outgoingCallIntentReceived(); } - setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); - LinphoneActivity.instance().startProxymitySensor(); - if (!mWakeLock.isHeld()) mWakeLock.acquire(); - - } - - private void loadMicAndSpeakerUiStateFromLibrary() { - mMute.setChecked(LinphoneService.getLc().isMicMuted()); - mSpeaker.setSpeakerOn(LinphoneManager.getInstance().isSpeakerOn()); - } - - - private void exitCallMode() { - mCallControlRow.setVisibility(View.VISIBLE); - mInCallControlRow.setVisibility(View.GONE); - mAddressLayout.setVisibility(View.VISIBLE); - mInCallAddressLayout.setVisibility(View.GONE); - mCall.setEnabled(true); - updateIncallVideoCallButton(); - mHangup.setEnabled(false); - setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); - mDecline.setEnabled(false); - if (LinphoneService.getLc().isVideoEnabled()) { - finishActivity(VIDEO_VIEW_ACTIVITY); - } - if (mWakeLock.isHeld())mWakeLock.release(); - mSpeaker.setSpeakerOn(false); - LinphoneManager.getInstance().routeAudioToReceiver(); - BandwidthManager.getInstance().setUserRestriction(false); - LinphoneManager.getInstance().resetCameraFromPreferences(); - LinphoneActivity.instance().stopProxymitySensor(); - } - - private void callPending(LinphoneCall call) { - mDecline.setEnabled(true); - //routeAudioToSpeaker(); - - // Privacy setting to not share the user camera by default - boolean prefVideoEnable = mPref.getBoolean(getString(R.string.pref_video_enable_key), false); - boolean prefAutomaticallyShareMyCamera = mPref.getBoolean(getString(R.string.pref_video_automatically_share_my_video_key), false); - AndroidCameraRecordManager.getInstance().setMuted(!(prefVideoEnable && prefAutomaticallyShareMyCamera)); - call.enableCamera(prefAutomaticallyShareMyCamera); - } - - public void newOutgoingCall(String aTo) { - mAddress.setText(aTo); - mAddress.clearDisplayedName(); - LinphoneManager.getInstance().newOutgoingCall(mAddress); - } - - - - - public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url) {} - public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {} - public void textReceived(LinphoneCore lc, LinphoneChatRoom cr, - LinphoneAddress from, String message) {} - - - public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status, - int delay_ms, Object data) {} - - public void setContactAddress(String aContact,String aDisplayName) { - mAddress.setText(aContact); - mAddress.setDisplayedName(aDisplayName); - } - - - public void onAlreadyInVideoCall() { - startVideoView(VIDEO_VIEW_ACTIVITY); - } - - - public void onWrongDestinationAddress() { - Toast toast = Toast.makeText(DialerActivity.this - ,String.format(getString(R.string.warning_wrong_destination_address),mAddress.getText().toString()) - ,Toast.LENGTH_LONG); - toast.show(); - } - - - public void onAlreadyInCall() { - Toast toast = Toast.makeText(DialerActivity.this, - getString(R.string.warning_already_incall), Toast.LENGTH_LONG); - toast.show(); - } - - - public void onCannotGetCallParameters() { - Toast toast = Toast.makeText(DialerActivity.this - ,String.format(getString(R.string.error_cannot_get_call_parameters),mAddress.getText().toString()) - ,Toast.LENGTH_LONG); - toast.show(); } } diff --git a/src/org/linphone/HistoryActivity.java b/src/org/linphone/HistoryActivity.java index 6b931cd3c..86eb2bc82 100644 --- a/src/org/linphone/HistoryActivity.java +++ b/src/org/linphone/HistoryActivity.java @@ -59,9 +59,9 @@ public class HistoryActivity extends ListActivity { TextView lSecondLineView = (TextView) v.findViewById(R.id.history_cell_second_line); if (lSecondLineView.getVisibility() == View.GONE) { // no display name - DialerActivity.getDialer().setContactAddress(lFirstLineView.getText().toString(), null); + DialerActivity.instance().setContactAddress(lFirstLineView.getText().toString(), null); } else { - DialerActivity.getDialer().setContactAddress(lSecondLineView.getText().toString() + DialerActivity.instance().setContactAddress(lSecondLineView.getText().toString() ,lFirstLineView.getText().toString()); } LinphoneActivity.instance().getTabHost().setCurrentTabByTag(LinphoneActivity.DIALER_TAB); @@ -86,12 +86,12 @@ public class HistoryActivity extends ListActivity { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_clear_history: - LinphoneService.instance().getLinphoneCore().clearCallLogs(); + LinphoneManager.getLc().clearCallLogs(); setListAdapter(new CallHistoryAdapter(this)); break; default: - Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]"); + Log.e(LinphoneManager.TAG, "Unknown menu item ["+item+"]"); break; } @@ -102,7 +102,7 @@ public class HistoryActivity extends ListActivity { class CallHistoryAdapter extends BaseAdapter { final List mLogs; CallHistoryAdapter(Context aContext) { - mLogs = LinphoneService.instance().getLinphoneCore().getCallLogs(); + mLogs = LinphoneManager.getLc().getCallLogs(); } public int getCount() { return mLogs.size(); @@ -142,7 +142,7 @@ public class HistoryActivity extends ListActivity { lDirectionImageIn.setVisibility(View.GONE); lDirectionImageOut.setVisibility(View.VISIBLE); } - LinphoneCore lc = LinphoneService.instance().getLinphoneCore(); + LinphoneCore lc = LinphoneManager.getLc(); LinphoneProxyConfig lProxyConfig = lc.getDefaultProxyConfig(); String lDetailedName=null; String lDisplayName = lAddress.getDisplayName(); diff --git a/src/org/linphone/KeepAliveReceiver.java b/src/org/linphone/KeepAliveReceiver.java index fba931aa3..ff87a3d4b 100644 --- a/src/org/linphone/KeepAliveReceiver.java +++ b/src/org/linphone/KeepAliveReceiver.java @@ -30,14 +30,14 @@ public class KeepAliveReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if (!LinphoneService.isready()) { - Log.i(LinphoneService.TAG, "Linphone service not ready"); + if (!LinphoneService.isReady()) { + Log.i(LinphoneManager.TAG, "Keep alive broadcast received while Linphone service not ready"); return; } else { if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_ON)) { - LinphoneService.getLc().enableKeepAlive(true); + LinphoneManager.getLc().enableKeepAlive(true); } else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_OFF)) { - LinphoneService.getLc().enableKeepAlive(false); + LinphoneManager.getLc().enableKeepAlive(false); } } diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index c21b5c72a..0ebe1dffb 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -19,19 +19,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package org.linphone; +import static android.content.Intent.ACTION_MAIN; +import static android.media.AudioManager.*; import java.util.List; +import org.linphone.core.Version; + import android.app.AlertDialog; import android.app.TabActivity; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.media.AudioManager; -import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -43,92 +47,92 @@ import android.widget.FrameLayout; import android.widget.TabHost; public class LinphoneActivity extends TabActivity { - public static String DIALER_TAB = "dialer"; + public static final String DIALER_TAB = "dialer"; private AudioManager mAudioManager; - private static LinphoneActivity theLinphoneActivity; + private static LinphoneActivity instance; private FrameLayout mMainFrame; private SensorManager mSensorManager; - static private SensorEventListener mSensorEventListener; + private static SensorEventListener mSensorEventListener; - private static String SCREEN_IS_HIDDEN ="screen_is_hidden"; + private static final String SCREEN_IS_HIDDEN ="screen_is_hidden"; - protected static LinphoneActivity instance() - { - if (theLinphoneActivity == null) { - throw new RuntimeException("LinphoneActivity not instanciated yet"); - } else { - return theLinphoneActivity; - } + protected static LinphoneActivity instance() { + if (instance != null) return instance; + + throw new RuntimeException("LinphoneActivity not instantiated yet"); } + protected void onSaveInstanceState (Bundle outState) { super.onSaveInstanceState(outState); - if (mMainFrame.getVisibility() == View.INVISIBLE) { - outState.putBoolean(SCREEN_IS_HIDDEN, true); - } else { - outState.putBoolean(SCREEN_IS_HIDDEN, false); - } - + outState.putBoolean(SCREEN_IS_HIDDEN, mMainFrame.getVisibility() == View.INVISIBLE); } + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + instance = this; setContentView(R.layout.main); - mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); - theLinphoneActivity = this; + // start linphone as background - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setClass(this, LinphoneService.class); - startService(intent); + startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class)); + mMainFrame = (FrameLayout) findViewById(R.id.main_frame); - mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE)); + mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); + TabHost lTabHost = getTabHost(); // The activity TabHost TabHost.TabSpec spec; // Reusable TabSpec for each tab - + Drawable tabDrawable; // Drawable for a tab + Intent tabIntent; // Intent for the a table + CharSequence indicator; //Call History - Intent lHistoryItent = new Intent().setClass(this, HistoryActivity.class); - - spec = lTabHost.newTabSpec("history").setIndicator(getString(R.string.tab_history), - getResources().getDrawable(R.drawable.history_orange)) - .setContent(lHistoryItent); + tabIntent = new Intent().setClass(this, HistoryActivity.class); + tabDrawable = getResources().getDrawable(R.drawable.history_orange); + indicator = getString(R.string.tab_history); + spec = lTabHost.newTabSpec("history") + .setIndicator(indicator, tabDrawable) + .setContent(tabIntent); + lTabHost.addTab(spec); + + // Dialer + tabIntent = new Intent().setClass(this, DialerActivity.class).setData(getIntent().getData()); + tabDrawable = getResources().getDrawable(R.drawable.dialer_orange); + indicator = getString(R.string.tab_dialer); + tabDrawable = getResources().getDrawable(R.drawable.dialer_orange); + spec = lTabHost.newTabSpec(DIALER_TAB) + .setIndicator(indicator, tabDrawable) + .setContent(tabIntent); lTabHost.addTab(spec); - // dialer - Intent lDialerIntent = new Intent().setClass(this, DialerActivity.class); - lDialerIntent.setData(getIntent().getData()); - // Initialize a TabSpec for each tab and add it to the TabHost - spec = lTabHost.newTabSpec("dialer").setIndicator(getString(R.string.tab_dialer), - getResources().getDrawable(R.drawable.dialer_orange)) - .setContent(lDialerIntent); - lTabHost.addTab(spec); - - // contact pick - Intent lContactItent = new Intent().setClass(this, ContactPickerActivity.class); - - spec = lTabHost.newTabSpec("contact").setIndicator(getString(R.string.tab_contact), - getResources().getDrawable(R.drawable.contact_orange)) - .setContent(lContactItent); + // Contact picker + tabIntent = new Intent().setClass(this, ContactPickerActivity.class); + indicator = getString(R.string.tab_contact); + tabDrawable = getResources().getDrawable(R.drawable.contact_orange); + spec = lTabHost.newTabSpec("contact") + .setIndicator(indicator, tabDrawable) + .setContent(tabIntent); lTabHost.addTab(spec); + + lTabHost.setCurrentTabByTag("dialer"); + + if (savedInstanceState !=null && savedInstanceState.getBoolean(SCREEN_IS_HIDDEN,false)) { hideScreen(true); } - - } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (intent.getData() != null) { - DialerActivity.getDialer().newOutgoingCall(intent.getData().toString().substring("tel://".length())); - intent.setData(null); + DialerActivity.instance().newOutgoingCall(intent); } } @@ -136,16 +140,15 @@ public class LinphoneActivity extends TabActivity { protected void onPause() { super.onPause(); if (isFinishing()) { - //restaure audio settings - if (Integer.parseInt(Build.VERSION.SDK) <=4 /* lSensorList = mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY); mSensorEventListener = new SensorEventListener() { public void onSensorChanged(SensorEvent event) { if (event.timestamp == 0) return; //just ignoring for nexus 1 - Log.d(LinphoneService.TAG, "Proximity sensor report ["+event.values[0]+"] , for max range ["+event.sensor.getMaximumRange()+"]"); + Log.d(LinphoneManager.TAG, "Proximity sensor report ["+event.values[0]+"] , for max range ["+event.sensor.getMaximumRange()+"]"); if (event.values[0] != event.sensor.getMaximumRange() ) { instance().hideScreen(true); @@ -250,15 +225,37 @@ public class LinphoneActivity extends TabActivity { }; if (lSensorList.size() >0) { mSensorManager.registerListener(mSensorEventListener,lSensorList.get(0),SensorManager.SENSOR_DELAY_UI); - Log.i(LinphoneService.TAG, "Proximity sensor detected, registering"); + Log.i(LinphoneManager.TAG, "Proximity sensor detected, registering"); } } + protected synchronized void stopProxymitySensor() { if (mSensorManager!=null) { mSensorManager.unregisterListener(mSensorEventListener); mSensorEventListener=null; } hideScreen(false); + } + + + void showPreferenceErrorDialog(String message) { + AlertDialog.Builder builder = new AlertDialog.Builder(this) + .setMessage(String.format(getString(R.string.config_error), message)) + .setCancelable(false) + .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Intent intent = new Intent(ACTION_MAIN); + intent.setClass(getApplicationContext(), LinphonePreferencesActivity.class); + startActivity(intent); + } + }) + .setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + + builder.create().show(); } } diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 467bb63e3..070fa0fd8 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -18,31 +18,115 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Timer; +import java.util.TimerTask; + import org.linphone.core.AndroidCameraRecordManager; import org.linphone.core.LinphoneAddress; +import org.linphone.core.LinphoneAuthInfo; +import org.linphone.core.LinphoneCall; +import org.linphone.core.LinphoneChatRoom; import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCoreException; +import org.linphone.core.LinphoneCoreFactory; +import org.linphone.core.LinphoneCoreListener; +import org.linphone.core.LinphoneFriend; +import org.linphone.core.LinphoneProxyConfig; +import org.linphone.core.PayloadType; +import org.linphone.core.LinphoneCall.State; +import org.linphone.core.LinphoneCore.EcCalibratorStatus; +import org.linphone.core.LinphoneCore.FirewallPolicy; +import org.linphone.core.LinphoneCore.GlobalState; +import org.linphone.core.LinphoneCore.RegistrationState; +import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.media.AudioManager; +import android.media.MediaPlayer; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; import android.os.Build; +import android.os.Vibrator; +import android.preference.PreferenceManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; -import android.view.WindowManager; +import android.util.Log; +import android.view.OrientationEventListener; -public class LinphoneManager { +/** + * + * Manager of the low level LibLinphone stuff.
+ * Including:
    + *
  • Starting C liblinphone
  • + *
  • Reacting to C liblinphone state changes
  • + *
  • Calling Linphone android service listener methods
  • + *
  • Interacting from Android GUI/service with low level SIP stuff/
  • + *
+ * + * Add Service Listener to react to Linphone state changes. + * + * @author Guillaume Beraudo + * + */ +public final class LinphoneManager implements LinphoneCoreListener { private static LinphoneManager instance; private AudioManager mAudioManager; private NewOutgoingCallUiListener newOutgoingCallUiListener; private SharedPreferences mPref; private Resources mR; - private WindowManager mWindowManager; + private LinphoneCore mLc; + private int mPhoneOrientation; - private LinphoneManager() {} + + private LinphoneManager(final Context c) { + mAudioManager = ((AudioManager) c.getSystemService(Context.AUDIO_SERVICE)); + mVibrator = (Vibrator) c.getSystemService(Context.VIBRATOR_SERVICE); + mPref = PreferenceManager.getDefaultSharedPreferences(c); + mPackageManager = c.getPackageManager(); + mR = c.getResources(); + + // Register a sensor to track phoneOrientation for placing new calls. + new OrientationEventListener(c) { + @Override + public void onOrientationChanged(int o) { + if (o == OrientationEventListener.ORIENTATION_UNKNOWN) return; + + o = 90 * (o / 90); + + if (Math.abs(mPhoneOrientation - o) < 90) return; + + mPhoneOrientation = o; + } + }.enable(); + } + + public static final String TAG="Linphone"; + /** Called when the activity is first created. */ + private static final String LINPHONE_FACTORY_RC = "/data/data/org.linphone/files/linphonerc"; + private static final String LINPHONE_RC = "/data/data/org.linphone/files/.linphonerc"; + private static final String RING_SND = "/data/data/org.linphone/files/oldphone_mono.wav"; + private static final String RINGBACK_SND = "/data/data/org.linphone/files/ringback.wav"; + + private Timer mTimer = new Timer("Linphone scheduler"); + + private BroadcastReceiver mKeepAliveReceiver = new KeepAliveReceiver(); + private PackageManager mPackageManager; + + + public void routeAudioToSpeaker() { if (Integer.parseInt(Build.VERSION.SDK) <= 4 /*4 &&mAudioManager.isSpeakerphoneOn(); @@ -105,14 +191,13 @@ public class LinphoneManager { address.setText(to); } - LinphoneCore lLinphoneCore = LinphoneService.instance().getLinphoneCore(); - if (lLinphoneCore.isIncall()) { + if (mLc.isIncall()) { newOutgoingCallUiListener.onAlreadyInCall(); return; } LinphoneAddress lAddress; try { - lAddress = lLinphoneCore.interpretUrl(to); + lAddress = mLc.interpretUrl(to); } catch (LinphoneCoreException e) { newOutgoingCallUiListener.onWrongDestinationAddress(); return; @@ -120,8 +205,7 @@ public class LinphoneManager { lAddress.setDisplayName(address.getDisplayedName()); try { - - boolean prefVideoEnable = mPref.getBoolean(mR.getString(R.string.pref_video_enable_key), false); + boolean prefVideoEnable = isVideoEnabled(); boolean prefInitiateWithVideo = mPref.getBoolean(mR.getString(R.string.pref_video_initiate_call_with_video_key), false); resetCameraFromPreferences(); CallManager.getInstance().inviteAddress(lAddress, prefVideoEnable && prefInitiateWithVideo); @@ -136,8 +220,7 @@ public class LinphoneManager { public void resetCameraFromPreferences() { boolean useFrontCam = mPref.getBoolean(mR.getString(R.string.pref_video_use_front_camera_key), false); AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam); - final int phoneOrientation = 90 * mWindowManager.getDefaultDisplay().getOrientation(); - AndroidCameraRecordManager.getInstance().setPhoneOrientation(phoneOrientation); + AndroidCameraRecordManager.getInstance().setPhoneOrientation(mPhoneOrientation); } public void setNewOutgoingCallUiListener(NewOutgoingCallUiListener l) { @@ -160,41 +243,33 @@ public class LinphoneManager { public void sendStaticImage(boolean send) { - LinphoneCore lc = LinphoneService.getLc(); - if (lc.isIncall()) { - lc.getCurrentCall().enableCamera(!send); + if (mLc.isIncall()) { + mLc.getCurrentCall().enableCamera(!send); } } - public void playDtmf(char dtmf) { - if (getLc().isIncall()) { - // Play if in call as it will not go to speaker - getLc().playDtmf(dtmf, -1); - return; - } - - ContentResolver r = LinphoneService.instance().getContentResolver(); + public void playDtmf(ContentResolver r, char dtmf) { + boolean speaker = true; try { if (Settings.System.getInt(r, Settings.System.DTMF_TONE_WHEN_DIALING) == 0) { - // audible touch disabled: don't play - return; + // audible touch disabled: don't play on speaker, only send in outgoing stream + speaker = false; } } catch (SettingNotFoundException e) {} - getLc().playDtmf(dtmf, -1); + getLc().playDtmf(dtmf, -1, speaker); } public void changeResolution() { BandwidthManager manager = BandwidthManager.getInstance(); manager.setUserRestriction(!manager.isUserRestriction()); - LinphoneManager.getInstance().sendStaticImage(AndroidCameraRecordManager.getInstance().isMuted()); + sendStaticImage(AndroidCameraRecordManager.getInstance().isMuted()); } public void terminateCall() { - LinphoneCore lc = LinphoneService.getLc(); - if (lc.isIncall()) { - lc.terminateCall(lc.getCurrentCall()); + if (mLc.isIncall()) { + mLc.terminateCall(mLc.getCurrentCall()); } } @@ -210,6 +285,419 @@ public class LinphoneManager { public void toggleCameraMuting() { AndroidCameraRecordManager rm = AndroidCameraRecordManager.getInstance(); - LinphoneManager.getInstance().sendStaticImage(rm.toggleMute()); + sendStaticImage(rm.toggleMute()); } + + private synchronized void startLibLinphone(final Context context, final LinphoneServiceListener listener) { + try { + this.serviceListener = listener; + copyAssetsFromPackage(context); + + mLc = LinphoneCoreFactory.instance().createLinphoneCore( + this, LINPHONE_RC, LINPHONE_FACTORY_RC, null); + + mLc.setPlaybackGain(3); + mLc.setRing(null); + + try { + initFromConf(context); + } catch (LinphoneException e) { + Log.w(TAG, "no config ready yet"); + } + TimerTask lTask = new TimerTask() { + @Override + public void run() { + mLc.iterate(); + } + + }; + + mTimer.scheduleAtFixedRate(lTask, 0, 100); + + IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON); + lFilter.addAction(Intent.ACTION_SCREEN_OFF); + context.registerReceiver(mKeepAliveReceiver, lFilter); + } + catch (Exception e) { + Log.e(TAG,"Cannot start linphone",e); + } + } + + private void copyAssetsFromPackage(Context context) throws IOException { + copyIfNotExist(context, R.raw.oldphone_mono,RING_SND); + copyIfNotExist(context, R.raw.ringback,RINGBACK_SND); + copyFromPackage(context, R.raw.linphonerc, new File(LINPHONE_FACTORY_RC).getName()); + } + private void copyIfNotExist(Context context, int ressourceId,String target) throws IOException { + File lFileToCopy = new File(target); + if (!lFileToCopy.exists()) { + copyFromPackage(context, ressourceId,lFileToCopy.getName()); + } + } + private void copyFromPackage(Context context, int ressourceId,String target) throws IOException{ + FileOutputStream lOutputStream = context.openFileOutput (target, 0); + InputStream lInputStream = mR.openRawResource(ressourceId); + int readByte; + byte[] buff = new byte[8048]; + while (( readByte = lInputStream.read(buff))!=-1) { + lOutputStream.write(buff,0, readByte); + } + lOutputStream.flush(); + lOutputStream.close(); + lInputStream.close(); + } + + + + public void initFromConf(Context context) throws LinphoneConfigException { + //traces + boolean lIsDebug = mPref.getBoolean(getString(R.string.pref_debug_key), false); + LinphoneCoreFactory.instance().setDebugMode(lIsDebug); + + try { + // Configure audio codecs + enableDisableAudioCodec("speex", 32000, R.string.pref_codec_speex32_key); + enableDisableAudioCodec("speex", 16000, R.string.pref_codec_speex16_key); + enableDisableAudioCodec("speex", 8000, R.string.pref_codec_speex8_key); + enableDisableAudioCodec("iLBC", 8000, R.string.pref_codec_ilbc_key); + enableDisableAudioCodec("GSM", 8000, R.string.pref_codec_gsm_key); + enableDisableAudioCodec("PCMU", 8000, R.string.pref_codec_pcmu_key); + enableDisableAudioCodec("PCMA", 8000, R.string.pref_codec_pcma_key); + + // Configure video codecs + for (PayloadType videoCodec : mLc.listVideoCodecs()) { + enableDisableVideoCodecs(videoCodec); + } + + + String sOutcalls = mPref.getString(getString(R.string.pref_handle_outcall_key), OutgoingCallReceiver.key_on_demand); + boolean handleOutcalls = !sOutcalls.equalsIgnoreCase(OutgoingCallReceiver.key_off); + +/* Now useless, see enablePkgComponent + * if (handleOutcalls){ + IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON); + lFilter.setPriority(0); + lFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL); + if (mOutgoingCallReceiver == null) { + mOutgoingCallReceiver = new OutgoingCallReceiver(); + } + context.registerReceiver(mOutgoingCallReceiver,lFilter); + } else if (mOutgoingCallReceiver!=null) { + context.unregisterReceiver(mOutgoingCallReceiver); + mOutgoingCallReceiver=null; + }*/ + + // Enable/disable outgoing call receiver according to user wishes + // Could be done already once when the preference is changed in UI. + enablePkgComponent(context, OutgoingCallReceiver.class, handleOutcalls); + + + mLc.enableEchoCancellation(mPref.getBoolean(getString(R.string.pref_echo_cancellation_key),false)); + } catch (LinphoneCoreException e) { + throw new LinphoneConfigException(getString(R.string.wrong_settings),e); + } + boolean isVideoEnabled = isVideoEnabled(); + mLc.enableVideo(isVideoEnabled, isVideoEnabled); + //1 read proxy config from preferences + String lUserName = mPref.getString(getString(R.string.pref_username_key), null); + if (lUserName == null || lUserName.length()==0) { + throw new LinphoneConfigException(getString(R.string.wrong_username)); + } + + String lPasswd = mPref.getString(getString(R.string.pref_passwd_key), null); + if (lPasswd == null || lPasswd.length()==0) { + throw new LinphoneConfigException(getString(R.string.wrong_passwd)); + } + + String lDomain = mPref.getString(getString(R.string.pref_domain_key), null); + if (lDomain == null || lDomain.length()==0) { + throw new LinphoneConfigException(getString(R.string.wrong_domain)); + } + + String lStun = mPref.getString(getString(R.string.pref_stun_server_key), null); + + //stun server + mLc.setStunServer(lStun); + mLc.setFirewallPolicy((lStun!=null && lStun.length()>0) ? FirewallPolicy.UseStun : FirewallPolicy.NoFirewall); + + //auth + mLc.clearAuthInfos(); + LinphoneAuthInfo lAuthInfo = LinphoneCoreFactory.instance().createAuthInfo(lUserName, lPasswd,null); + mLc.addAuthInfo(lAuthInfo); + + + //proxy + mLc.clearProxyConfigs(); + String lProxy = mPref.getString(getString(R.string.pref_proxy_key),null); + if (lProxy == null || lProxy.length() == 0) { + lProxy = "sip:"+lDomain; + } + if (!lProxy.startsWith("sip:")) { + lProxy = "sip:"+lProxy; + } + //get Default proxy if any + LinphoneProxyConfig lDefaultProxyConfig = mLc.getDefaultProxyConfig(); + String lIdentity = "sip:"+lUserName+"@"+lDomain; + try { + if (lDefaultProxyConfig == null) { + lDefaultProxyConfig = LinphoneCoreFactory.instance().createProxyConfig(lIdentity, lProxy, null,true); + mLc.addProxyConfig(lDefaultProxyConfig); + mLc.setDefaultProxyConfig(lDefaultProxyConfig); + + } else { + lDefaultProxyConfig.edit(); + lDefaultProxyConfig.setIdentity(lIdentity); + lDefaultProxyConfig.setProxy(lProxy); + lDefaultProxyConfig.enableRegister(true); + lDefaultProxyConfig.done(); + } + lDefaultProxyConfig = mLc.getDefaultProxyConfig(); + + if (lDefaultProxyConfig !=null) { + //prefix + String lPrefix = mPref.getString(getString(R.string.pref_prefix_key), null); + if (lPrefix != null) { + lDefaultProxyConfig.setDialPrefix(lPrefix); + } + //escape + + lDefaultProxyConfig.setDialEscapePlus(mPref.getBoolean(getString(R.string.pref_escape_plus_key),false)); + //outbound proxy + if (mPref.getBoolean(getString(R.string.pref_enable_outbound_proxy_key), false)) { + lDefaultProxyConfig.setRoute(lProxy); + } else { + lDefaultProxyConfig.setRoute(null); + } + + } + //init network state + ConnectivityManager lConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo lInfo = lConnectivityManager.getActiveNetworkInfo(); + mLc.setNetworkReachable( lInfo !=null? lConnectivityManager.getActiveNetworkInfo().getState() ==NetworkInfo.State.CONNECTED:false); + + } catch (LinphoneCoreException e) { + throw new LinphoneConfigException(getString(R.string.wrong_settings),e); + } + } + + + private void enablePkgComponent(Context context, Class clazz, boolean state) { + mPackageManager.setComponentEnabledSetting( + new ComponentName(context, clazz), + state ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + 0); + } + + private void enableDisableAudioCodec(String codec, int rate, int key) throws LinphoneCoreException { + PayloadType pt = mLc.findPayloadType(codec, rate); + if (pt !=null) { + boolean enable= mPref.getBoolean(getString(key),false); + mLc.enablePayloadType(pt, enable); + } + } + + private void enableDisableVideoCodecs(PayloadType videoCodec) throws LinphoneCoreException { + String mime = videoCodec.getMime(); + int key; + + if ("MP4V-ES".equals(mime)) { + key = R.string.pref_video_codec_mpeg4_key; + } else if ("H264".equals(mime)) { + key = R.string.pref_video_codec_h264_key; + } else if ("H263-1998".equals(mime)) { + key = R.string.pref_video_codec_h263_key; + } else { + Log.e(TAG, "Unhandled video codec " + mime); + mLc.enablePayloadType(videoCodec, false); + return; + } + + boolean enable= mPref.getBoolean(getString(key),false); + mLc.enablePayloadType(videoCodec, enable); + } + + public boolean hasCamera() { + return mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA); + } + + public static synchronized void destroy(Context context) { + if (instance == null) return; + + try { + instance.mTimer.cancel(); + instance.mLc.destroy(); + context.unregisterReceiver(instance.mKeepAliveReceiver); + } finally { + instance.mLc = null; + instance = null; + } + } + + private String getString(int key) { + return mR.getString(key); + } + + + + + + + + + + + + + + + + + + public interface LinphoneServiceListener { + void onGlobalStateChanged(GlobalState state, String message); + void onRegistrationStateChanged(RegistrationState state, String message); + void onCallStateChanged(LinphoneCall call, State state, String message); + void onEcCalibrationStatus(EcCalibratorStatus status, Object data, + int delayMs); + void onRingerPlayerCreated(MediaPlayer mRingerPlayer); + void onDisplayStatus(String message); + } + + + private LinphoneServiceListener serviceListener; + private LinphoneCall.State mCurrentCallState; + + private MediaPlayer mRingerPlayer; + private Vibrator mVibrator; + + + + public void displayWarning(LinphoneCore lc, String message) {} + public void authInfoRequested(LinphoneCore lc, String realm, String username) {} + public void byeReceived(LinphoneCore lc, String from) {} + public void displayMessage(LinphoneCore lc, String message) {} + public void show(LinphoneCore lc) {} + public void newSubscriptionRequest(LinphoneCore lc,LinphoneFriend lf,String url) {} + public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {} + public void textReceived(LinphoneCore lc, LinphoneChatRoom cr, + LinphoneAddress from, String message) {} + + + + public void displayStatus(final LinphoneCore lc, final String message) { + Log.i(TAG, message); + serviceListener.onDisplayStatus(message); + } + + + public void globalState(final LinphoneCore lc, final LinphoneCore.GlobalState state, final String message) { + Log.i(TAG, "new state ["+state+"]"); + serviceListener.onGlobalStateChanged(state, message); + } + + + + public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig cfg,final LinphoneCore.RegistrationState state,final String message) { + Log.i(TAG, "new state ["+state+"]"); + serviceListener.onRegistrationStateChanged(state, message); + } + + + public void callState(final LinphoneCore lc,final LinphoneCall call, final State state, final String message) { + Log.i(TAG, "new state ["+state+"]"); + if (state == LinphoneCall.State.IncomingReceived && !call.equals(lc.getCurrentCall())) { + if (call.getReplacedCall()==null){ + //no multicall support, just decline + lc.terminateCall(call); + }//otherwise it will be accepted automatically. + + return; + } + serviceListener.onCallStateChanged(call, state, message); + + if (state == LinphoneCall.State.IncomingReceived) { + startRinging(); + } + + if (mCurrentCallState == LinphoneCall.State.IncomingReceived) { + //previous state was ringing, so stop ringing + stopRinging(); + //routeAudioToReceiver(); + } + mCurrentCallState=state; + } + + + public void ecCalibrationStatus(final LinphoneCore lc,final EcCalibratorStatus status, final int delay_ms, + final Object data) { + serviceListener.onEcCalibrationStatus(status, data, delay_ms); + } + + + + + + + + + + + + + private synchronized void startRinging() { + try { + if (mAudioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER) && mVibrator !=null) { + long[] patern = {0,1000,1000}; + mVibrator.vibrate(patern, 1); + } + if (mRingerPlayer == null) { + mRingerPlayer = new MediaPlayer(); + mRingerPlayer.setAudioStreamType(AudioManager.STREAM_RING); + serviceListener.onRingerPlayerCreated(mRingerPlayer); + mRingerPlayer.prepare(); + mRingerPlayer.setLooping(true); + mRingerPlayer.start(); + } else { + Log.w(LinphoneManager.TAG,"already ringing"); + } + } catch (Exception e) { + Log.e(LinphoneManager.TAG, "cannot handle incoming call",e); + } + + } + + private synchronized void stopRinging() { + if (mRingerPlayer !=null) { + mRingerPlayer.stop(); + mRingerPlayer.release(); + mRingerPlayer=null; + } + if (mVibrator!=null) { + mVibrator.cancel(); + } + } + + public String extractADisplayName() { + final LinphoneAddress remote = mLc.getRemoteAddress(); + if (remote == null) return null; + + final String displayName = remote.getDisplayName(); + if (displayName!=null) { + return displayName; + } else if (remote.getUserName() != null){ + return remote.getUserName(); + } else { + return remote.toString(); + } + } + + public static boolean reinviteWithVideo() { + return CallManager.getInstance().reinviteWithVideo(); + } + + public boolean isVideoEnabled() { + return mPref.getBoolean(getString(R.string.pref_video_enable_key), false); + } + + } diff --git a/src/org/linphone/LinphonePreferencesActivity.java b/src/org/linphone/LinphonePreferencesActivity.java index 69077ba62..9e0e8bdc3 100644 --- a/src/org/linphone/LinphonePreferencesActivity.java +++ b/src/org/linphone/LinphonePreferencesActivity.java @@ -21,24 +21,25 @@ package org.linphone; +import static android.media.AudioManager.STREAM_VOICE_CALL; + import org.linphone.core.LinphoneCoreException; +import org.linphone.core.Version; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.media.AudioManager; -import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; +import android.preference.Preference.OnPreferenceClickListener; import android.util.Log; public class LinphonePreferencesActivity extends PreferenceActivity { - private static final int version = Integer.parseInt(Build.VERSION.SDK); - boolean mIsLowEndCpu = true; + private boolean mIsLowEndCpu = true; private AudioManager mAudioManager; @Override @@ -46,9 +47,9 @@ public class LinphonePreferencesActivity extends PreferenceActivity { super.onCreate(savedInstanceState); mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE)); boolean enableIlbc=false; - if (LinphoneService.isready()) { + if (LinphoneService.isReady()) { // if not ilbc, we are on low end cpu. - enableIlbc = LinphoneService.instance().getLinphoneCore().findPayloadType("iLBC", 8000)!=null?true:false; + enableIlbc = LinphoneManager.getLc().findPayloadType("iLBC", 8000)!=null?true:false; mIsLowEndCpu=!enableIlbc; if (!mIsLowEndCpu && !getPreferenceManager().getSharedPreferences().contains(getString(R.string.pref_echo_cancellation_key))) { getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(R.string.pref_echo_cancellation_key), true).commit(); @@ -68,7 +69,8 @@ public class LinphonePreferencesActivity extends PreferenceActivity { getPreferenceScreen().findPreference(getString(R.string.pref_codec_speex16_key)).setEnabled(enableIlbc); //getPreferenceScreen().findPreference(getString(R.string.pref_codec_speex32_key)).setEnabled(enableIlbc); } - getPreferenceScreen().findPreference(getString(R.string.pref_echo_canceller_calibration_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() { + getPreferenceScreen().findPreference(getString(R.string.pref_echo_canceller_calibration_key)) + .setOnPreferenceClickListener(new OnPreferenceClickListener() { public boolean onPreferenceClick(Preference preference) { startEcCalibration(preference); return false; @@ -76,7 +78,7 @@ public class LinphonePreferencesActivity extends PreferenceActivity { }); // Force disable video - if (version < 5 || !enableIlbc) { + if (Version.sdkStrictlyBelow(5) || !enableIlbc || !LinphoneManager.getInstance().hasCamera()) { disableCheckbox(R.string.pref_video_enable_key); } if (getPreferenceManager().getSharedPreferences().getBoolean(DialerActivity.PREF_FIRST_LAUNCH,true)) { @@ -93,18 +95,23 @@ public class LinphonePreferencesActivity extends PreferenceActivity { } } - private void startEcCalibration(Preference preference) { + private synchronized void startEcCalibration(Preference preference) { try { - while (mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL) != mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL)) { - mAudioManager.adjustStreamVolume(AudioManager.STREAM_VOICE_CALL, AudioManager.ADJUST_RAISE, 0); - } - LinphoneService.getLc().startEchoCalibration(preference); + int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL); + int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL); + mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0); + + LinphoneManager.getLc().startEchoCalibration(preference); + + mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0); + preference.setSummary(R.string.ec_calibrating); preference.getEditor().putBoolean(getString(R.string.pref_echo_canceller_calibration_key), false).commit(); } catch (LinphoneCoreException e) { - Log.w(LinphoneService.TAG, "Cannot calibrate EC",e); + Log.w(LinphoneManager.TAG, "Cannot calibrate EC",e); } } + private void disableCheckbox(int key) { getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(key), false).commit(); CheckBoxPreference box = (CheckBoxPreference) getPreferenceScreen().findPreference(getString(key)); @@ -116,12 +123,20 @@ public class LinphonePreferencesActivity extends PreferenceActivity { @Override protected void onPause() { super.onPause(); - if (isFinishing()) { - try { - LinphoneActivity.instance().initFromConf(); - } catch (LinphoneException e) { - Log.e(LinphoneService.TAG, "cannot update config",e); + + if (!isFinishing()) return; + + + try { + LinphoneManager.getInstance().initFromConf(getApplicationContext()); + } catch (LinphoneException e) { + + if (! (e instanceof LinphoneConfigException)) { + Log.e(LinphoneManager.TAG, "Cannot update config",e); + return; } + + LinphoneActivity.instance().showPreferenceErrorDialog(e.getMessage()); } } diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java index c4baeb37b..6993df5bc 100644 --- a/src/org/linphone/LinphoneService.java +++ b/src/org/linphone/LinphoneService.java @@ -18,446 +18,128 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.util.Timer; -import java.util.TimerTask; -import org.linphone.core.LinphoneAddress; -import org.linphone.core.LinphoneAuthInfo; +import org.linphone.LinphoneManager.LinphoneServiceListener; import org.linphone.core.LinphoneCall; -import org.linphone.core.LinphoneChatRoom; import org.linphone.core.LinphoneCore; -import org.linphone.core.LinphoneCoreException; -import org.linphone.core.LinphoneCoreFactory; -import org.linphone.core.LinphoneCoreListener; -import org.linphone.core.LinphoneFriend; -import org.linphone.core.LinphoneProxyConfig; -import org.linphone.core.PayloadType; import org.linphone.core.LinphoneCall.State; import org.linphone.core.LinphoneCore.EcCalibratorStatus; -import org.linphone.core.LinphoneCore.FirewallPolicy; import org.linphone.core.LinphoneCore.GlobalState; +import org.linphone.core.LinphoneCore.RegistrationState; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.media.AudioManager; import android.media.MediaPlayer; import android.media.RingtoneManager; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; +import android.net.Uri; import android.os.Handler; import android.os.IBinder; -import android.os.Vibrator; import android.preference.CheckBoxPreference; -import android.preference.PreferenceManager; import android.util.Log; -public class LinphoneService extends Service implements LinphoneCoreListener { - static final public String TAG="Linphone"; - /** Called when the activity is first created. */ - private static String LINPHONE_FACTORY_RC = "/data/data/org.linphone/files/linphonerc"; - private static String LINPHONE_RC = "/data/data/org.linphone/files/.linphonerc"; - private static String RING_SND = "/data/data/org.linphone/files/oldphone_mono.wav"; - private static String RINGBACK_SND = "/data/data/org.linphone/files/ringback.wav"; +/*** + * + * Linphone service, reacting to Incoming calls, ...
+ * + * Roles include:
    + *
  • Initializing LinphoneManager
  • + *
  • Starting C libLinphone through LinphoneManager
  • + *
  • Reacting to LinphoneManager state changes
  • + *
  • Delegating GUI state change actions to GUI listener
  • + * + * + * @author Guillaume Beraudo + * + */ +public final class LinphoneService extends Service implements LinphoneServiceListener { + /* Listener needs to be implemented in the Service as it calls + * setLatestEventInfo and startActivity() which needs a context. + */ + + private Handler mHandler = new Handler(); + private static LinphoneService instance; - private static LinphoneService theLinphone; - private LinphoneCore mLinphoneCore; - private SharedPreferences mPref; - Timer mTimer = new Timer("Linphone scheduler"); - - NotificationManager mNotificationManager; - Notification mNotification; - PendingIntent mNofificationContentIntent; - final static int NOTIFICATION_ID=1; - final String NOTIFICATION_TITLE = "Linphone"; - - final int IC_LEVEL_OFFLINE=3; - final int IC_LEVEL_ORANGE=0; - final int IC_LEVEL_GREEN=1; - final int IC_LEVEL_RED=2; + static boolean isReady() { return (instance!=null); } - MediaPlayer mRingerPlayer; - LinphoneCall.State mCurrentCallState; - Vibrator mVibrator; - private AudioManager mAudioManager; - private BroadcastReceiver mKeepAliveMgrReceiver = new KeepAliveReceiver(); - private BroadcastReceiver mOutgoingCallReceiver = null; - - private Handler mHandler = new Handler() ; - static boolean isready() { - return (theLinphone!=null); - } + /** + * @throws RuntimeException service not instantiated + */ static LinphoneService instance() { - if (theLinphone == null) { - throw new RuntimeException("LinphoneActivity not instanciated yet"); - } else { - return theLinphone; - } + if (isReady()) return instance; + + throw new RuntimeException("LinphoneService not instantiated yet"); } + + private NotificationManager mNotificationMgr; + private final static int NOTIF_ID=1; + + private Notification mNotif; + private PendingIntent mNotifContentIntent; + private static final String NOTIF_TITLE = "Linphone"; + + + private static final int IC_LEVEL_ORANGE=0; + private static final int IC_LEVEL_GREEN=1; + private static final int IC_LEVEL_RED=2; + private static final int IC_LEVEL_OFFLINE=3; + + + + + @Override public void onCreate() { super.onCreate(); - theLinphone = this; - + instance = this; + // Dump some debugging information to the logs Hacks.dumpDeviceInformation(); - mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - mNotification = new Notification(R.drawable.status_level - , "" - , System.currentTimeMillis()); - mNotification.iconLevel=IC_LEVEL_ORANGE; - mNotification.flags |= Notification.FLAG_ONGOING_EVENT; - Intent notificationIntent = new Intent(this, LinphoneActivity.class); - mNofificationContentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); - mNotification.setLatestEventInfo(this, NOTIFICATION_TITLE,"", mNofificationContentIntent); - mNotificationManager.notify(NOTIFICATION_ID, mNotification); - mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE)); - mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); - try { - copyAssetsFromPackage(); - - mLinphoneCore = LinphoneCoreFactory.instance().createLinphoneCore( this - , LINPHONE_RC - , LINPHONE_FACTORY_RC - , null); - - mLinphoneCore.setPlaybackGain(3); - mLinphoneCore.setRing(null); - - try { - initFromConf(); - } catch (LinphoneException e) { - Log.w(TAG, "no config ready yet"); - } - TimerTask lTask = new TimerTask() { - @Override - public void run() { - mLinphoneCore.iterate(); - } - - }; - - mTimer.scheduleAtFixedRate(lTask, 0, 100); - IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON); - lFilter.addAction(Intent.ACTION_SCREEN_OFF); - registerReceiver(mKeepAliveMgrReceiver, lFilter); - - - - } - catch (Exception e) { - Log.e(TAG,"Cannot start linphone",e); - } - + mNotificationMgr = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); + mNotif = new Notification(R.drawable.status_level, "", System.currentTimeMillis()); + mNotif.iconLevel=IC_LEVEL_ORANGE; + mNotif.flags |= Notification.FLAG_ONGOING_EVENT; + Intent notifIntent = new Intent(this, LinphoneActivity.class); + mNotifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, 0); + mNotif.setLatestEventInfo(this, NOTIF_TITLE,"", mNotifContentIntent); + mNotificationMgr.notify(NOTIF_ID, mNotif); + + + LinphoneManager.createAndStart(this, this); } - private void copyAssetsFromPackage() throws IOException { - copyIfNotExist(R.raw.oldphone_mono,RING_SND); - copyIfNotExist(R.raw.ringback,RINGBACK_SND); - copyFromPackage(R.raw.linphonerc, new File(LINPHONE_FACTORY_RC).getName()); - } - private void copyIfNotExist(int ressourceId,String target) throws IOException { - File lFileToCopy = new File(target); - if (!lFileToCopy.exists()) { - copyFromPackage(ressourceId,lFileToCopy.getName()); - } - } - private void copyFromPackage(int ressourceId,String target) throws IOException{ - FileOutputStream lOutputStream = openFileOutput (target, 0); - InputStream lInputStream = getResources().openRawResource(ressourceId); - int readByte; - byte[] buff = new byte[8048]; - while (( readByte = lInputStream.read(buff))!=-1) { - lOutputStream.write(buff,0, readByte); - } - lOutputStream.flush(); - lOutputStream.close(); - lInputStream.close(); - - } - public void authInfoRequested(LinphoneCore lc, String realm, String username) { - - } - public void byeReceived(LinphoneCore lc, String from) { - // TODO Auto-generated method stub - - } - public void displayMessage(LinphoneCore lc, String message) { - // TODO Auto-generated method stub - - } - public void displayStatus(final LinphoneCore lc, final String message) { - Log.i(TAG, message); - if (DialerActivity.getDialer()!=null) { - mHandler.post(new Runnable() { - public void run() { - if (DialerActivity.getDialer()!=null) - DialerActivity.getDialer().displayStatus(lc,message); - } - - }); - - } - } - public void displayWarning(LinphoneCore lc, String message) { - // TODO Auto-generated method stub - - } - public void globalState(final LinphoneCore lc, final LinphoneCore.GlobalState state, final String message) { - Log.i(TAG, "new state ["+state+"]"); - if (state == GlobalState.GlobalOn) { - mNotification.iconLevel=IC_LEVEL_OFFLINE; - mNotification.when=System.currentTimeMillis(); - mNotification.setLatestEventInfo(this - , NOTIFICATION_TITLE - ,getString(R.string.notification_started) - , mNofificationContentIntent); - mNotificationManager.notify(NOTIFICATION_ID, mNotification); - if (DialerActivity.getDialer()!=null) { - mHandler.post(new Runnable() { - public void run() { - DialerActivity.getDialer().globalState(lc,state,message); - } - }); - } - - } - } - public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig cfg,final LinphoneCore.RegistrationState state,final String smessage) { - Log.i(TAG, "new state ["+state+"]"); - if (state == LinphoneCore.RegistrationState.RegistrationOk && lc.getDefaultProxyConfig().isRegistered()) { - mNotification.iconLevel=IC_LEVEL_ORANGE; - mNotification.when=System.currentTimeMillis(); - mNotification.setLatestEventInfo(this - , NOTIFICATION_TITLE - ,String.format(getString(R.string.notification_registered),lc.getDefaultProxyConfig().getIdentity()) - , mNofificationContentIntent); - mNotificationManager.notify(NOTIFICATION_ID, mNotification); - } - if (state == LinphoneCore.RegistrationState.RegistrationFailed ) { - mNotification.iconLevel=IC_LEVEL_OFFLINE; - mNotification.when=System.currentTimeMillis(); - mNotification.setLatestEventInfo(this - , NOTIFICATION_TITLE - ,String.format(getString(R.string.notification_register_failure),lc.getDefaultProxyConfig().getIdentity()) - , mNofificationContentIntent); - mNotificationManager.notify(NOTIFICATION_ID, mNotification); - } - mHandler.post(new Runnable() { - public void run() { - if (DialerActivity.getDialer()!=null) DialerActivity.getDialer().registrationState(lc,cfg,state,smessage); - } - }); - } - public void callState(final LinphoneCore lc,final LinphoneCall call, final State state, final String message) { - Log.i(TAG, "new state ["+state+"]"); - if (state == LinphoneCall.State.IncomingReceived && !call.equals(mLinphoneCore.getCurrentCall())) { - if (call.getReplacedCall()==null){ - //no multicall support, just decline - mLinphoneCore.terminateCall(call); - }//otherwise it will be accepted automatically. - - return; - } - mHandler.post(new Runnable() { - public void run() { - if (DialerActivity.getDialer()!=null) DialerActivity.getDialer().callState(lc,call,state,message); - } - }); - if (state == LinphoneCall.State.IncomingReceived) { - //wakeup linphone - Intent lIntent = new Intent(); - lIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - lIntent.setClass(this, LinphoneActivity.class); - startActivity(lIntent); - startRinging(); - } - if (mCurrentCallState == LinphoneCall.State.IncomingReceived) { - //previous state was ringing, so stop ringing - stopRinging(); - //routeAudioToReceiver(); - } - mCurrentCallState=state; - } - public void show(LinphoneCore lc) { - // TODO Auto-generated method stub - - } - - - private void enableDisableAudioCodec(String codec, int rate, int key) throws LinphoneCoreException { - PayloadType pt = mLinphoneCore.findPayloadType(codec, rate); - if (pt !=null) { - boolean enable= mPref.getBoolean(getString(key),false); - mLinphoneCore.enablePayloadType(pt, enable); - } - } - - private void enableDisableVideoCodecs(PayloadType videoCodec) throws LinphoneCoreException { - String mime = videoCodec.getMime(); - int key; - - if ("MP4V-ES".equals(mime)) { - key = R.string.pref_video_codec_mpeg4_key; - } else if ("H264".equals(mime)) { - key = R.string.pref_video_codec_h264_key; - } else if ("H263-1998".equals(mime)) { - key = R.string.pref_video_codec_h263_key; - } else { - Log.e(TAG, "Unhandled video codec " + mime); - mLinphoneCore.enablePayloadType(videoCodec, false); - return; - } - - boolean enable= mPref.getBoolean(getString(key),false); - mLinphoneCore.enablePayloadType(videoCodec, enable); - } - - public void initFromConf() throws LinphoneConfigException, LinphoneException { - //traces - boolean lIsDebug = mPref.getBoolean(getString(R.string.pref_debug_key), false); - LinphoneCoreFactory.instance().setDebugMode(lIsDebug); - - try { - // Configure audio codecs - enableDisableAudioCodec("speex", 32000, R.string.pref_codec_speex32_key); - enableDisableAudioCodec("speex", 16000, R.string.pref_codec_speex16_key); - enableDisableAudioCodec("speex", 8000, R.string.pref_codec_speex8_key); - enableDisableAudioCodec("iLBC", 8000, R.string.pref_codec_ilbc_key); - enableDisableAudioCodec("GSM", 8000, R.string.pref_codec_gsm_key); - enableDisableAudioCodec("PCMU", 8000, R.string.pref_codec_pcmu_key); - enableDisableAudioCodec("PCMA", 8000, R.string.pref_codec_pcma_key); - - // Configure video codecs - for (PayloadType videoCodec : mLinphoneCore.listVideoCodecs()) { - enableDisableVideoCodecs(videoCodec); - } - if (!mPref.getString(getString(R.string.pref_handle_outcall_key), OutgoingCallReceiver.key_on_demand).equalsIgnoreCase(OutgoingCallReceiver.key_off)){ - IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON); - lFilter.setPriority(0); - lFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL); - if (mOutgoingCallReceiver == null) { - mOutgoingCallReceiver = new OutgoingCallReceiver(); - } - registerReceiver(mOutgoingCallReceiver,lFilter); - } else if (mOutgoingCallReceiver!=null) { - unregisterReceiver(mOutgoingCallReceiver); - mOutgoingCallReceiver=null; - } - - mLinphoneCore.enableEchoCancellation(mPref.getBoolean(getString(R.string.pref_echo_cancellation_key),false)); - } catch (LinphoneCoreException e) { - throw new LinphoneConfigException(getString(R.string.wrong_settings),e); - } - boolean isVideoEnabled = mPref.getBoolean(getString(R.string.pref_video_enable_key),false); - mLinphoneCore.enableVideo(isVideoEnabled, isVideoEnabled); - //1 read proxy config from preferences - String lUserName = mPref.getString(getString(R.string.pref_username_key), null); - if (lUserName == null || lUserName.length()==0) { - throw new LinphoneConfigException(getString(R.string.wrong_username)); - } - - String lPasswd = mPref.getString(getString(R.string.pref_passwd_key), null); - if (lPasswd == null || lPasswd.length()==0) { - throw new LinphoneConfigException(getString(R.string.wrong_passwd)); - } - - String lDomain = mPref.getString(getString(R.string.pref_domain_key), null); - if (lDomain == null || lDomain.length()==0) { - throw new LinphoneConfigException(getString(R.string.wrong_domain)); - } - - String lStun = mPref.getString(getString(R.string.pref_stun_server_key), null); - - //stun server - mLinphoneCore.setStunServer(lStun); - mLinphoneCore.setFirewallPolicy((lStun!=null && lStun.length()>0) ? FirewallPolicy.UseStun : FirewallPolicy.NoFirewall); - - //auth - mLinphoneCore.clearAuthInfos(); - LinphoneAuthInfo lAuthInfo = LinphoneCoreFactory.instance().createAuthInfo(lUserName, lPasswd,null); - mLinphoneCore.addAuthInfo(lAuthInfo); - - - //proxy - mLinphoneCore.clearProxyConfigs(); - String lProxy = mPref.getString(getString(R.string.pref_proxy_key),null); - if (lProxy == null || lProxy.length() == 0) { - lProxy = "sip:"+lDomain; - } - if (!lProxy.startsWith("sip:")) { - lProxy = "sip:"+lProxy; - } - //get Default proxy if any - LinphoneProxyConfig lDefaultProxyConfig = mLinphoneCore.getDefaultProxyConfig(); - String lIdentity = "sip:"+lUserName+"@"+lDomain; - try { - if (lDefaultProxyConfig == null) { - lDefaultProxyConfig = LinphoneCoreFactory.instance().createProxyConfig(lIdentity, lProxy, null,true); - mLinphoneCore.addProxyConfig(lDefaultProxyConfig); - mLinphoneCore.setDefaultProxyConfig(lDefaultProxyConfig); - - } else { - lDefaultProxyConfig.edit(); - lDefaultProxyConfig.setIdentity(lIdentity); - lDefaultProxyConfig.setProxy(lProxy); - lDefaultProxyConfig.enableRegister(true); - lDefaultProxyConfig.done(); - } - lDefaultProxyConfig = mLinphoneCore.getDefaultProxyConfig(); - - if (lDefaultProxyConfig !=null) { - //prefix - String lPrefix = mPref.getString(getString(R.string.pref_prefix_key), null); - if (lPrefix != null) { - lDefaultProxyConfig.setDialPrefix(lPrefix); - } - //escape + - lDefaultProxyConfig.setDialEscapePlus(mPref.getBoolean(getString(R.string.pref_escape_plus_key),false)); - //outbound proxy - if (mPref.getBoolean(getString(R.string.pref_enable_outbound_proxy_key), false)) { - lDefaultProxyConfig.setRoute(lProxy); - } else { - lDefaultProxyConfig.setRoute(null); - } - - } - //init network state - ConnectivityManager lConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo lInfo = lConnectivityManager.getActiveNetworkInfo(); - mLinphoneCore.setNetworkReachable( lInfo !=null? lConnectivityManager.getActiveNetworkInfo().getState() ==NetworkInfo.State.CONNECTED:false); - - } catch (LinphoneCoreException e) { - throw new LinphoneConfigException(getString(R.string.wrong_settings),e); - } + private void sendNotification(int level, int text) { + mNotif.iconLevel = level; + mNotif.when=System.currentTimeMillis(); + mNotif.setLatestEventInfo(this, NOTIF_TITLE,getString(text), mNotifContentIntent); + mNotificationMgr.notify(NOTIF_ID, mNotif); } - - - - protected LinphoneCore getLinphoneCore() { - return mLinphoneCore; + private void sendNotificationWithId(int level, int text) { + mNotif.iconLevel = level; + mNotif.when=System.currentTimeMillis(); + String id = LinphoneManager.getLc().getDefaultProxyConfig().getIdentity(); + mNotif.setLatestEventInfo(this, NOTIF_TITLE, + String.format(getString(text), id), + mNotifContentIntent); + mNotificationMgr.notify(NOTIF_ID, mNotif); } + + + @Override public IBinder onBind(Intent intent) { return null; @@ -466,66 +148,77 @@ public class LinphoneService extends Service implements LinphoneCoreListener { @Override public void onDestroy() { super.onDestroy(); - mTimer.cancel(); - mLinphoneCore.destroy(); - theLinphone=null; - mNotificationManager.cancel(NOTIFICATION_ID); - unregisterReceiver(mKeepAliveMgrReceiver); - if (mOutgoingCallReceiver != null) unregisterReceiver(mOutgoingCallReceiver); - } - public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, - String url) { - // TODO Auto-generated method stub - - } - public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) { - // TODO Auto-generated method stub - - } - public void textReceived(LinphoneCore lc, LinphoneChatRoom cr, - LinphoneAddress from, String message) { - // TODO Auto-generated method stub - + LinphoneManager.destroy(this); + + mNotificationMgr.cancel(NOTIF_ID); + + instance=null; } - public static LinphoneCore getLc() { - return instance().getLinphoneCore(); + + private static final LinphoneGuiListener guiListener() { + return DialerActivity.instance(); } - private synchronized void startRinging() { - try { - if (mAudioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER) && mVibrator !=null) { - long[] patern = {0,1000,1000}; - mVibrator.vibrate(patern, 1); + + + + + + public void onDisplayStatus(final String message) { + mHandler.post(new Runnable() { + public void run() { + if (guiListener() != null) guiListener().onDisplayStatus(message); } - if (mRingerPlayer == null) { - mRingerPlayer = new MediaPlayer(); - mRingerPlayer.setAudioStreamType(AudioManager.STREAM_RING); - mRingerPlayer.setDataSource(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)); - mRingerPlayer.prepare(); - mRingerPlayer.setLooping(true); - mRingerPlayer.start(); - } else { - Log.w(LinphoneService.TAG,"already ringing"); - } - } catch (Exception e) { - Log.e(LinphoneService.TAG, "cannot handle incoming call",e); + }); + } + + public void onGlobalStateChanged(final GlobalState state, final String message) { + if (state == GlobalState.GlobalOn) { + sendNotification(IC_LEVEL_OFFLINE, R.string.notification_started); + + mHandler.post(new Runnable() { + public void run() { + if (guiListener() != null) + guiListener().onGlobalStateChangedToOn(message); + } + }); + } + } + + + public void onRegistrationStateChanged(RegistrationState state, + String message) { + if (state == LinphoneCore.RegistrationState.RegistrationOk && LinphoneManager.getLc().getDefaultProxyConfig().isRegistered()) { + sendNotificationWithId(IC_LEVEL_ORANGE, R.string.notification_registered); + } + if (state == LinphoneCore.RegistrationState.RegistrationFailed ) { + sendNotificationWithId(IC_LEVEL_OFFLINE, R.string.notification_register_failure); + } + } + + + public void onCallStateChanged(final LinphoneCall call, final State state, final String message) { + if (state == LinphoneCall.State.IncomingReceived) { + //wakeup linphone + startActivity(new Intent() + .setClass(this, LinphoneActivity.class) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } + mHandler.post(new Runnable() { + public void run() { + if (guiListener() != null) + guiListener().onCallStateChanged(call, state, message); + } + }); } - private synchronized void stopRinging() { - if (mRingerPlayer !=null) { - mRingerPlayer.stop(); - mRingerPlayer.release(); - mRingerPlayer=null; - } - if (mVibrator!=null) { - mVibrator.cancel(); - } - } - public void ecCalibrationStatus(final LinphoneCore lc,final EcCalibratorStatus status, final int delay_ms, - final Object data) { + + + public void onEcCalibrationStatus(final EcCalibratorStatus status, Object data, + final int delay_ms) { final CheckBoxPreference pref = (CheckBoxPreference) data; + mHandler.post(new Runnable() { public void run() { if (status == EcCalibratorStatus.Done) { @@ -537,9 +230,25 @@ public class LinphoneService extends Service implements LinphoneCoreListener { pref.setChecked(false); } } - }); + }); } + - + public interface LinphoneGuiListener { + void onDisplayStatus(String message); + void onGlobalStateChangedToOn(String message); +// void onRegistrationStateChanged(RegistrationState state, String message); + void onCallStateChanged(LinphoneCall call, State state, String message); + } + + + public void onRingerPlayerCreated(MediaPlayer mRingerPlayer) { + final Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); + try { + mRingerPlayer.setDataSource(getApplicationContext(), ringtoneUri); + } catch (IOException e) { + Log.e(LinphoneManager.TAG, "cannot set ringtone", e); + } + } } diff --git a/src/org/linphone/NetworkManager.java b/src/org/linphone/NetworkManager.java index b5b598c75..877fa72be 100644 --- a/src/org/linphone/NetworkManager.java +++ b/src/org/linphone/NetworkManager.java @@ -27,27 +27,34 @@ import android.util.Log; +/** + * + * Intercept network state changes and update linphone core through LinphoneManager. + * + */ public class NetworkManager extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - NetworkInfo lNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); - Log.i(LinphoneService.TAG, "Network info ["+lNetworkInfo+"]"); + NetworkInfo lNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); + Log.i(LinphoneManager.TAG, "Network info ["+lNetworkInfo+"]"); Boolean lNoConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,false); - if (!LinphoneService.isready()) { - Log.i(LinphoneService.TAG, "Linphone service not ready"); + + + if (!LinphoneService.isReady()) { + Log.i(LinphoneManager.TAG, "Network broadcast received while Linphone service not ready"); return; } - if (lNoConnectivity| ((lNetworkInfo.getState() == NetworkInfo.State.DISCONNECTED) /*&& !lIsFailOver*/)) { - LinphoneService.instance().getLinphoneCore().setNetworkReachable(false); + + + if (lNoConnectivity | ((lNetworkInfo.getState() == NetworkInfo.State.DISCONNECTED) /*&& !lIsFailOver*/)) { + LinphoneManager.getLc().setNetworkReachable(false); } else if (lNetworkInfo.getState() == NetworkInfo.State.CONNECTED){ - LinphoneService.instance().getLinphoneCore().setNetworkReachable(true); + LinphoneManager.getLc().setNetworkReachable(true); } else { - //unhandled event + // Other unhandled events } - - } } diff --git a/src/org/linphone/OutgoingCallReceiver.java b/src/org/linphone/OutgoingCallReceiver.java index eab2e8db4..a26867f90 100644 --- a/src/org/linphone/OutgoingCallReceiver.java +++ b/src/org/linphone/OutgoingCallReceiver.java @@ -24,20 +24,30 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; import android.preference.PreferenceManager; +import android.util.Log; +/** + * Intercept outgoing calls dialed through Android dialer. + * Redirect the calls through Linphone according to user preferences. + * + */ public class OutgoingCallReceiver extends BroadcastReceiver { - public static String TAG = ";0000000"; - public static String key_off="off"; - public static String key_on_demand="ask_for_outcall_interception"; - public static String key_always="alway_intercept_out_call"; + public static final String TAG = ";0000000"; + public static final String key_off="off"; + public static final String key_on_demand="ask_for_outcall_interception"; + public static final String key_always="alway_intercept_out_call"; + + @Override public void onReceive(Context context, Intent intent) { String to = intent.getStringExtra("android.intent.extra.PHONE_NUMBER"); + //do not catch ussd codes if (to==null || to.contains("#")) return; + if (!to.contains(TAG)) { - if (LinphoneService.isready() && LinphoneService.instance().getLinphoneCore().getDefaultProxyConfig()==null) { + if (LinphoneService.isReady() && LinphoneManager.getLc().getDefaultProxyConfig()==null) { //just return return; } @@ -52,7 +62,7 @@ public class OutgoingCallReceiver extends BroadcastReceiver { lIntent.setAction(Intent.ACTION_CALL); } - lIntent.setData(Uri.parse("tel://"+to+TAG)); + lIntent.setData(Uri.parse("tel:"+to+TAG)); lIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(lIntent); diff --git a/src/org/linphone/VideoCallActivity.java b/src/org/linphone/VideoCallActivity.java index 6e85ba90d..8023b2064 100644 --- a/src/org/linphone/VideoCallActivity.java +++ b/src/org/linphone/VideoCallActivity.java @@ -56,7 +56,7 @@ public class VideoCallActivity extends Activity { setContentView(R.layout.videocall); mVideoView = (SurfaceView) findViewById(R.id.video_surface); - LinphoneCore lc = LinphoneService.getLc(); + LinphoneCore lc = LinphoneManager.getLc(); lc.setVideoWindow(mVideoView); mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface); @@ -72,7 +72,7 @@ public class VideoCallActivity extends Activity { mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone"); mWakeLock.acquire(); - if (Version.sdkBelow(8)) { + if (Version.sdkStrictlyBelow(8)) { // Force to display in portrait orientation for old devices // as they do not support surfaceView rotation setRequestedOrientation(recordManager.isCameraOrientationPortrait() ? @@ -87,7 +87,7 @@ public class VideoCallActivity extends Activity { @Override protected void onResume() { // Update call if orientation changed - if (Version.sdkAbove(8) && previousPhoneOrientation != phoneOrientation) { + if (Version.sdkAboveOrEqual(8) && previousPhoneOrientation != phoneOrientation) { CallManager.getInstance().updateCall(); resizeCapturePreview(mVideoCaptureView); } @@ -137,7 +137,7 @@ public class VideoCallActivity extends Activity { */ private void resizeCapturePreview(SurfaceView sv) { LayoutParams lp = sv.getLayoutParams(); - VideoSize vs = LinphoneService.getLc().getPreferredVideoSize(); + VideoSize vs = LinphoneManager.getLc().getPreferredVideoSize(); float newRatio = (float) vs.width / vs.height; @@ -180,11 +180,11 @@ public class VideoCallActivity extends Activity { resizeCapturePreview(mVideoCaptureView); break; default: - Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]"); + Log.e(LinphoneManager.TAG, "Unknown menu item ["+item+"]"); break; } - return false; + return true; } diff --git a/src/org/linphone/core/AndroidCameraRecordManager.java b/src/org/linphone/core/AndroidCameraRecordManager.java index 2ca3d70aa..ecf12c597 100644 --- a/src/org/linphone/core/AndroidCameraRecordManager.java +++ b/src/org/linphone/core/AndroidCameraRecordManager.java @@ -67,7 +67,7 @@ public class AndroidCameraRecordManager { // singleton private AndroidCameraRecordManager() { - cc = Version.sdkAbove(9) ? new AndroidCameraConf9() : new AndroidCameraConf(); + cc = Version.sdkAboveOrEqual(9) ? new AndroidCameraConf9() : new AndroidCameraConf(); int[] fId = {-1};int[] rId = {-1};int[] cId = {-1}; cc.findFrontAndRearCameraIds(fId, rId, cId); @@ -172,11 +172,11 @@ public class AndroidCameraRecordManager { parameters.rotation = bufferRotationForCorrectImageOrientation(); parameters.surfaceView = surfaceView; - if (Version.sdkAbove(9)) { + if (Version.sdkAboveOrEqual(9)) { recorder = new AndroidCameraRecord9Impl(parameters); - } else if (Version.sdkAbove(8)) { + } else if (Version.sdkAboveOrEqual(8)) { recorder = new AndroidCameraRecord8Impl(parameters); - } else if (Version.sdkAbove(5)) { + } else if (Version.sdkAboveOrEqual(5)) { recorder = new AndroidCameraRecord5Impl(parameters); } else { recorder = new AndroidCameraRecordImpl(parameters); @@ -208,7 +208,7 @@ public class AndroidCameraRecordManager { if (supportedVideoSizes != null) return supportedVideoSizes; } - if (Version.sdkAbove(5)) { + if (Version.sdkAboveOrEqual(5)) { supportedVideoSizes = AndroidCameraRecord5Impl.oneShotSupportedVideoSizes(); } @@ -253,7 +253,7 @@ public class AndroidCameraRecordManager { private int bufferRotationForCorrectImageOrientation() { final int cameraOrientation = cc.getCameraOrientation(cameraId); - final int rotation = Version.sdkAbove(8) ? + final int rotation = Version.sdkAboveOrEqual(8) ? (360 - cameraOrientation + 90 - phoneOrientation) % 360 : 0; Log.d(tag, "Capture video buffer will need a rotation of " + rotation diff --git a/src/org/linphone/core/LinphoneCoreImpl.java b/src/org/linphone/core/LinphoneCoreImpl.java index 1a9fc67a7..533ee8b97 100644 --- a/src/org/linphone/core/LinphoneCoreImpl.java +++ b/src/org/linphone/core/LinphoneCoreImpl.java @@ -64,7 +64,7 @@ class LinphoneCoreImpl implements LinphoneCore { private native void enableEchoCancellation(long nativePtr,boolean enable); private native boolean isEchoCancellationEnabled(long nativePtr); private native long getCurrentCall(long nativePtr) ; - private native void playDtmf(long nativePtr,char dtmf,int duration); + private native void playDtmf(long nativePtr,char dtmf,int duration, boolean speaker); private native void stopDtmf(long nativePtr); private native void setVideoWindowId(long nativePtr, Object wid); private native void setPreviewWindowId(long nativePtr, Object wid); @@ -298,8 +298,8 @@ class LinphoneCoreImpl implements LinphoneCore { // TODO Auto-generated method stub return false; } - public void playDtmf(char number, int duration) { - playDtmf(nativePtr,number, duration); + public void playDtmf(char number, int duration, boolean speaker) { + playDtmf(nativePtr,number, duration, speaker); } public void stopDtmf() { diff --git a/src/org/linphone/core/Version.java b/src/org/linphone/core/Version.java index 2b938dbea..057fb53a3 100644 --- a/src/org/linphone/core/Version.java +++ b/src/org/linphone/core/Version.java @@ -30,11 +30,11 @@ public class Version { 8 : Integer.parseInt(Build.VERSION.SDK); // Force versions above 9 to 8 // 7; // 2.1 - public static final boolean sdkAbove(int value) { + public static final boolean sdkAboveOrEqual(int value) { return buildVersion >= value; } - public static final boolean sdkBelow(int value) { + public static final boolean sdkStrictlyBelow(int value) { return buildVersion < value; } diff --git a/src/org/linphone/ui/AddVideoButton.java b/src/org/linphone/ui/AddVideoButton.java index 115fc7cfc..1d519d2ff 100644 --- a/src/org/linphone/ui/AddVideoButton.java +++ b/src/org/linphone/ui/AddVideoButton.java @@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone.ui; -import org.linphone.CallManager; +import org.linphone.LinphoneManager; import android.content.Context; import android.util.AttributeSet; @@ -37,7 +37,7 @@ public class AddVideoButton extends ImageButton implements OnClickListener { public void onClick(View v) { // If no in video call; try to reinvite with video - boolean alreadyInVideoCall = !CallManager.getInstance().reinviteWithVideo(); + boolean alreadyInVideoCall = !LinphoneManager.reinviteWithVideo(); if (alreadyInVideoCall && alreadyInVideoCallListener != null) { // In video call; going back to video call activity alreadyInVideoCallListener.onAlreadyInVideoCall(); diff --git a/src/org/linphone/ui/CallButton.java b/src/org/linphone/ui/CallButton.java index e00f3da8a..05a54f2b7 100644 --- a/src/org/linphone/ui/CallButton.java +++ b/src/org/linphone/ui/CallButton.java @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package org.linphone.ui; import org.linphone.LinphoneManager; +import org.linphone.R; import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCoreException; @@ -27,10 +28,10 @@ import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; +import android.widget.Toast; public class CallButton extends ImageButton implements OnClickListener, AddressAwareWidget { - private CallButtonListener callButtonListener; private AddressText mAddress; public CallButton(Context context, AttributeSet attrs) { @@ -45,7 +46,7 @@ public class CallButton extends ImageButton implements OnClickListener, AddressA lc.acceptCall(lc.getCurrentCall()); } catch (LinphoneCoreException e) { lc.terminateCall(lc.getCurrentCall()); - callButtonListener.onWrongDestinationAddress(); + onWrongDestinationAddress(); } return; } @@ -55,16 +56,14 @@ public class CallButton extends ImageButton implements OnClickListener, AddressA } - - public static interface CallButtonListener { - void onWrongDestinationAddress(); + protected void onWrongDestinationAddress() { + Toast toast = Toast.makeText(getContext() + ,String.format(getResources().getString(R.string.warning_wrong_destination_address),mAddress.getText().toString()) + ,Toast.LENGTH_LONG); + toast.show(); } - public void setCallButtonListerner(CallButtonListener listener) { - callButtonListener = listener; - } - public void setAddressWidget(AddressText address) { mAddress = address; } diff --git a/src/org/linphone/ui/Digit.java b/src/org/linphone/ui/Digit.java index 8d4547150..89a52ceb0 100644 --- a/src/org/linphone/ui/Digit.java +++ b/src/org/linphone/ui/Digit.java @@ -108,7 +108,7 @@ public class Digit extends Button implements OnLongClickListener, AddressAwareWi public boolean onTouch(View v, MotionEvent event) { LinphoneCore lc = LinphoneManager.getLc(); if (event.getAction() == MotionEvent.ACTION_DOWN && mIsDtmfStarted ==false) { - LinphoneManager.getInstance().playDtmf(mKeyCode.charAt(0)); + LinphoneManager.getInstance().playDtmf(getContext().getContentResolver(), mKeyCode.charAt(0)); mIsDtmfStarted=true; } else { if (event.getAction() == MotionEvent.ACTION_UP)