package net.chrislehmann.sipservice.service;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import net.chrislehmann.common.util.PreferencesUtilities;
import net.chrislehmann.linphone.R;
import net.chrislehmann.sipservice.SipServiceContants;
import org.linphone.LinphoneManager;
import org.linphone.LinphonePreferenceManager;
import org.linphone.core.Hacks;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
import roboguice.service.RoboService;
import roboguice.util.Ln;
public class SipService extends RoboService implements LinphoneManager.LinphoneServiceListener {
private final static String LOGTAG = SipService.class.getSimpleName();
private LinphoneManager linphoneManager;
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
Intent intent = (Intent) msg.obj;
handleIntent(intent);
}
};
Looper.loop();
}
public void stopLooping() {
mHandler.getLooper().quit();
}
}
LooperThread messageLoop = new LooperThread();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Ln.d("Got start command");
Message message = new Message();
message.obj = intent;
messageLoop.mHandler.sendMessage(message);
return START_STICKY;
}
private LinphoneManager getLinphoneManager() {
startLinphoneManager();
return linphoneManager;
}
private LinphoneCore getLinphoneCore() {
startLinphoneManager();
return LinphoneManager.getLc();
}
private void startLinphoneManager() {
if (linphoneManager == null) {
Ln.d("Startiing linphone service...");
LinphonePreferenceManager.getInstance(this);
linphoneManager = LinphoneManager.createAndStart(this, this);
try {
LinphoneManager.getInstance().initFromConf(getApplicationContext());
} catch (Throwable e) {
final String errorMessage = "Error while initializing sip config";
org.linphone.core.Log.e(e, errorMessage);
Intent i = new Intent(SipServiceContants.Actions.ERROR_REGISTERING);
i.putExtra(SipServiceContants.Extras.ERROR_MESSAGE, errorMessage);
sendBroadcast(i);
// toast(R.string.error);;
}
LinphoneManager.getLc().setNetworkReachable(true);
}
}
private void dumpInstalledLinphoneInformation() {
PackageInfo info = null;
try {
info = getPackageManager().getPackageInfo(getPackageName(), 0);
} catch (PackageManager.NameNotFoundException nnfe) {
}
if (info != null) {
org.linphone.core.Log.i("Linphone version is ", info.versionCode);
} else {
org.linphone.core.Log.i("Linphone version is unknown");
}
}
private void stopLinphoneManager() {
// stopSelf();
if (linphoneManager != null) {
Ln.d("Stopping linphone service...");
linphoneManager = null;
LinphoneManager.destroy(this);
}
}
@Override
public void onCreate() {
messageLoop.start();
// Set default preferences
PreferenceManager.setDefaultValues(this, R.xml.linphone_preferences, true);
// Dump some debugging information to the logs
Hacks.dumpDeviceInformation();
dumpInstalledLinphoneInformation();
super.onCreate();
}
@Override
public void onDestroy() {
messageLoop.stopLooping();
super.onDestroy();
}
//Intent-only api - No Binding for now.
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void onGlobalStateChanged(LinphoneCore.GlobalState state, String message) {
Log.d(LOGTAG, "Global state changed: " + state + " : " + message);
//To change body of implemented methods use File | Settings | File Templates.
}
public void tryingNewOutgoingCallButCannotGetCallParameters() {
//To change body of implemented methods use File | Settings | File Templates.
}
public void tryingNewOutgoingCallButWrongDestinationAddress() {
//To change body of implemented methods use File | Settings | File Templates.
}
public void tryingNewOutgoingCallButAlreadyInCall() {
//To change body of implemented methods use File | Settings | File Templates.
}
public void onRegistrationStateChanged(LinphoneCore.RegistrationState state, String message) {
if (state.equals(LinphoneCore.RegistrationState.RegistrationOk)) {
sendBroadcast(new Intent(SipServiceContants.Actions.REGISTRATION_SUCCESS));
} else if (state.equals(LinphoneCore.RegistrationState.RegistrationFailed)) {
Intent i = new Intent(SipServiceContants.Actions.ERROR_REGISTERING);
i.putExtra(SipServiceContants.Extras.ERROR_MESSAGE, message);
sendBroadcast(i);
}
Log.d(LOGTAG, "Registration state changed: " + state + " : " + message);
}
public void onCallStateChanged(LinphoneCall call, LinphoneCall.State state, String message) {
Log.d(LOGTAG, "Call state changed: " + state + " : " + message);
try {
if (state.equals(LinphoneCall.State.IncomingReceived)) {
LinphoneManager.getInstance().acceptCallIfIncomingPending();
} else if (state.equals(LinphoneCall.State.Connected)) {
sendBroadcast(new Intent(SipServiceContants.Actions.CALL_ANSWERED));
} else if (state.equals(LinphoneCall.State.CallEnd) || state.equals(LinphoneCall.State.CallReleased)) {
sendBroadcast(new Intent(SipServiceContants.Actions.CALL_ENDED));
} else if (state.equals(LinphoneCall.State.Error)) {
Intent i = new Intent(SipServiceContants.Actions.ERROR_REGISTERING);
i.putExtra(SipServiceContants.Extras.ERROR_MESSAGE, message);
sendBroadcast(i);
}
} catch (LinphoneCoreException e) {
throw new RuntimeException(e);
}
}
public void onRingerPlayerCreated(MediaPlayer mRingerPlayer) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void onDisplayStatus(String message) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void onAlreadyInVideoCall() {
//To change body of implemented methods use File | Settings | File Templates.
}
public void onCallEncryptionChanged(LinphoneCall call, boolean encrypted, String authenticationToken) {
//To change body of implemented methods use File | Settings | File Templates.
}
private void handleIntent(Intent intent) {
String action = intent != null ? intent.getAction() : null;
Ln.d("Processing action: " + action);
if (SipServiceContants.Actions.STOP_SERVICE.equals(action)) {
stopLinphoneManager();
stopSelf();
} else if (SipServiceContants.Actions.HANG_UP.equals(action)) {
getLinphoneManager().terminateCall();
} else if (SipServiceContants.Actions.ENABLE_SPEAKERPHONE.equals(action)) {
getLinphoneManager().routeAudioToSpeaker();
} else if (SipServiceContants.Actions.DISABLE_SPEAKERPHONE.equals(action)) {
getLinphoneManager().routeAudioToReceiver();
} else if (SipServiceContants.Actions.MUTE_MIC.equals(action)) {
getLinphoneCore().muteMic(true);
} else if (SipServiceContants.Actions.UNMUTE_MIC.equals(action)) {
getLinphoneCore().muteMic(false);
} else if (SipServiceContants.Actions.SET_SERVER_INFO.equals(action)) {
Ln.d("Setting server info");
PreferencesUtilities.savePreference(SipService.this, R.string.pref_username_key, intent.getStringExtra(SipServiceContants.Extras.USERNAME_KEY));
PreferencesUtilities.savePreference(SipService.this, R.string.pref_passwd_key, intent.getStringExtra(SipServiceContants.Extras.PASSWORD));
PreferencesUtilities.savePreference(SipService.this, R.string.pref_domain_key, intent.getStringExtra(SipServiceContants.Extras.DOMAIN));
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_pcma_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_echo_cancellation_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_echo_canceller_calibration_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_video_enable_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_transport_udp_key, false);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_audio_use_specific_mode_key, "0");
PreferencesUtilities.savePreference(SipService.this, R.string.pref_video_codec_mpeg4_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_amr_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_pcmu_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_speex32_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_gsm_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_speex16_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_speex8_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_video_codec_vp8_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_codec_ilbc_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_video_initiate_call_with_video_key, true);
PreferencesUtilities.savePreference(SipService.this, R.string.pref_video_automatically_share_my_video_key, true);
stopLinphoneManager();
startLinphoneManager();
}
}
}