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)