-create LinphoneService

-fix landscape ui
-create History tab view
This commit is contained in:
Jehan Monnier 2010-02-18 18:29:40 +01:00
parent 652c2e53f0
commit b372bdca49
20 changed files with 718 additions and 186 deletions

View file

@ -4,7 +4,7 @@
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/linphone2" android:label="@string/app_name" android:debuggable = "true">
<activity android:name=".Linphone"
<activity android:name=".LinphoneActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar">
<intent-filter>
@ -27,6 +27,13 @@
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".HistoryActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<service android:name=".LinphoneService">
</service>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

BIN
res/drawable/in_call.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
res/drawable/out_call.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText android:id="@+id/SipUri" android:layout_height="wrap_content"
android:hint="sip:" android:layout_width="fill_parent"
android:singleLine="true"></EditText>
<TableLayout android:layout_width="fill_parent" android:id="@+id/Dialer" android:layout_height="fill_parent">
<TableRow android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="1" android:id="@+id/DialerRow05">
<ImageButton android:id="@+id/Call"
android:layout_height="fill_parent" android:src="@drawable/green"
android:layout_width="fill_parent" android:layout_weight="0.25">
</ImageButton>
<ImageButton android:id="@+id/HangUp" android:src="@drawable/red"
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:layout_weight="0.25"></ImageButton>
</TableRow><TableRow android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/DialerRow06"></TableRow>
<EditText android:layout_width="fill_parent" android:id="@+id/status_label" android:clickable="false" android:focusable="false" android:cursorVisible="false" android:textSize="12sp" android:height="15sp" android:layout_height="wrap_content"></EditText></TableLayout>
</LinearLayout>

View file

@ -1,39 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText android:id="@+id/SipUri" android:layout_height="wrap_content" android:hint="sip:" android:layout_width="fill_parent" android:singleLine="true"></EditText>
<EditText android:id="@+id/SipUri" android:layout_height="wrap_content"
android:hint="sip:" android:layout_width="fill_parent"
android:singleLine="true"></EditText>
<TableLayout android:layout_width="fill_parent" android:id="@+id/Dialer" android:layout_height="280dip">
<TableRow android:layout_height="fill_parent" android:layout_weight="1" android:id="@+id/DialerRow01" android:layout_width="fill_parent">
<Button android:id="@+id/Button01" android:text="1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button02" android:text="2" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button03" android:text="3" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.5"></Button>
</TableRow><TableRow android:layout_height="fill_parent" android:layout_weight="1" android:id="@+id/DialerRow02" android:layout_width="fill_parent"><Button android:id="@+id/Button04" android:text="4" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"></Button>
<Button android:text="5" android:id="@+id/Button05" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button06" android:text="6" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.5"></Button>
</TableRow><TableRow android:layout_weight="1" android:layout_height="fill_parent" android:id="@+id/DialerRow03" android:layout_width="fill_parent"><Button android:text="7" android:id="@+id/Button07" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button08" android:text="8" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"></Button>
<Button android:text="9" android:id="@+id/Button09" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.5"></Button>
</TableRow><TableRow android:layout_weight="1" android:layout_height="fill_parent" android:id="@+id/DialerRow04" android:layout_width="fill_parent"><Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="*" android:layout_weight="0.25" android:id="@+id/ButtonStar"></Button>
<Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="0+" android:id="@+id/Button00" android:layout_weight="0.25"></Button>
<Button android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/ButtonHash" android:text="#" android:layout_weight="0.5"></Button>
</TableRow><TableRow android:layout_height="fill_parent" android:id="@+id/DialerRow00" android:layout_width="fill_parent" android:layout_weight="1">
<TableLayout android:layout_width="fill_parent" android:id="@+id/Dialer"
android:layout_height="fill_parent">
<TableRow android:layout_height="fill_parent"
android:layout_weight="1" android:id="@+id/DialerRow01"
android:layout_width="fill_parent">
<Button android:id="@+id/Button01" android:text="1"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button02" android:text="2"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button03" android:text="3"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.5"></Button>
</TableRow>
<TableRow android:layout_height="fill_parent"
android:layout_weight="1" android:id="@+id/DialerRow02"
android:layout_width="fill_parent">
<Button android:id="@+id/Button04" android:text="4"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.25"></Button>
<Button android:text="5" android:id="@+id/Button05"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button06" android:text="6"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.5"></Button>
</TableRow>
<TableRow android:layout_weight="1" android:layout_height="fill_parent"
android:id="@+id/DialerRow03" android:layout_width="fill_parent">
<Button android:text="7" android:id="@+id/Button07"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.25"></Button>
<Button android:id="@+id/Button08" android:text="8"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.25"></Button>
<Button android:text="9" android:id="@+id/Button09"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="0.5"></Button>
</TableRow>
<TableRow android:layout_weight="1" android:layout_height="fill_parent"
android:id="@+id/DialerRow04" android:layout_width="fill_parent">
<Button android:layout_width="fill_parent"
android:layout_height="fill_parent" android:text="*"
android:layout_weight="0.25" android:id="@+id/ButtonStar"></Button>
<Button android:layout_width="fill_parent"
android:layout_height="fill_parent" android:text="0+" android:id="@+id/Button00"
android:layout_weight="0.25"></Button>
<Button android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="@+id/ButtonHash"
android:text="#" android:layout_weight="0.5"></Button>
</TableRow>
<TableRow android:layout_height="fill_parent"
android:layout_width="fill_parent" android:layout_weight="1"
android:id="@+id/DialerRow05">
<ImageButton android:id="@+id/Call" android:layout_height="fill_parent" android:src="@drawable/green" android:layout_width="fill_parent" android:layout_weight="0.25">
</ImageButton>
<ImageButton android:id="@+id/Call"
android:layout_height="fill_parent" android:src="@drawable/green"
android:layout_width="fill_parent" android:layout_weight="0.25">
</ImageButton>
<ImageButton android:id="@+id/HangUp" android:src="@drawable/red" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25"></ImageButton>
<ImageButton android:id="@+id/HangUp" android:src="@drawable/red"
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:layout_weight="0.25"></ImageButton>
</TableRow>
</TableLayout>
<EditText android:layout_width="fill_parent" android:id="@+id/status_label"
android:clickable="false" android:focusable="false"
android:cursorVisible="false" android:textSize="12sp" android:height="15sp"
android:layout_height="wrap_content"></EditText>
</TableLayout>
<EditText android:layout_width="fill_parent" android:id="@+id/status_label" android:clickable="false" android:focusable="false" android:cursorVisible="false" android:textSize="12sp" android:height="15sp" android:layout_height="wrap_content"></EditText>
</LinearLayout>

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?> <!-- from Android Layout Tricks #1 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<ImageView
android:id="@+id/history_cell_icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="6dip"
android:src="@drawable/icon" />
<TextView
android:id="@+id/history_cell_second_line"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_toRightOf="@id/history_cell_icon"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:singleLine="true"
android:ellipsize="marquee" />
<TextView
android:id="@+id/history_cell_first_line"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/history_cell_icon"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_above="@id/history_cell_second_line"
android:layout_alignWithParentIfMissing="true"
android:gravity="center_vertical"/>
</RelativeLayout>

View file

@ -7,7 +7,7 @@
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
><!-- android:padding="5dp"-->
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
@ -15,7 +15,7 @@
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp" />
android:layout_height="fill_parent"/>
<!-- android:padding="5dp" /-->
</LinearLayout>
</TabHost>

View file

@ -21,4 +21,5 @@
<string name="no">No</string>
<string name="config_error">%s, do you want to return to the settings page ?</string>
<string name="warning_already_incall">Cannot initiate a new call because a call is already engaged</string>
<string name="tab_history">History</string>
</resources>

View file

@ -1,3 +1,21 @@
/*
ContactPickerActivity.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone;
import android.app.Activity;
@ -51,7 +69,7 @@ public class ContactPickerActivity extends Activity {
}
}
Linphone.getLinphone().getTabHost().setCurrentTabByTag(Linphone.DIALER_TAB);
LinphoneActivity.instance().getTabHost().setCurrentTabByTag(LinphoneActivity.DIALER_TAB);
}
}
}

View file

@ -1,3 +1,21 @@
/*
DialerActivity.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone;
import org.linphone.core.LinphoneAddress;
@ -9,6 +27,7 @@ import org.linphone.core.LinphoneCore.GeneralState;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
@ -20,7 +39,7 @@ import android.widget.TextView;
import android.widget.Toast;
public class DialerActivity extends Activity implements LinphoneCoreListener {
private LinphoneCore mLinphoneCore;
private TextView mAddress;
private TextView mStatus;
private ImageButton mCall;
@ -62,18 +81,19 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
setContentView(R.layout.dialer);
mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE));
try {
theDialer = this;
mLinphoneCore = Linphone.getLinphone().getLinphoneCore();
mAddress = (TextView) findViewById(R.id.SipUri);
mCall = (ImageButton) findViewById(R.id.Call);
mCall.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (mLinphoneCore.isInComingInvitePending()) {
mLinphoneCore.acceptCall();
LinphoneCore lLinphoneCore = LinphoneService.instance().getLinphoneCore();
if (lLinphoneCore.isInComingInvitePending()) {
lLinphoneCore.acceptCall();
return;
}
if (mLinphoneCore.isIncall()) {
if (lLinphoneCore.isIncall()) {
Toast toast = Toast.makeText(DialerActivity.this, getString(R.string.warning_already_incall), Toast.LENGTH_LONG);
toast.show();
return;
@ -83,7 +103,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
if (lRawAddress.startsWith("sip:")) {
lCallingUri=lRawAddress;
} else {
LinphoneProxyConfig lProxy = mLinphoneCore.getDefaultProxyConfig();
LinphoneProxyConfig lProxy = lLinphoneCore.getDefaultProxyConfig();
String lDomain=null;
String lNormalizedNumber=lRawAddress;
if (lProxy!=null) {
@ -95,15 +115,17 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
, mDisplayName);
lCallingUri = lAddress.toUri();
}
mLinphoneCore.invite(lCallingUri);
lLinphoneCore.invite(lCallingUri);
}
});
mHangup = (ImageButton) findViewById(R.id.HangUp);
mHangup.setEnabled(false);
mHangup.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mLinphoneCore.terminateCall();
LinphoneCore lLinphoneCore = LinphoneService.instance().getLinphoneCore();
lLinphoneCore.terminateCall();
}
});
@ -116,40 +138,44 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
mAddressView = anAddress;
}
public void onClick(View v) {
mAddressView.append(mKeyCode);
mAddressView.append(mKeyCode);
}
};
mZero = (Button) findViewById(R.id.Button00) ;
mZero.setOnClickListener(new DialKeyListener(mAddress,'0'));
mOne = (Button) findViewById(R.id.Button01) ;
mOne.setOnClickListener(new DialKeyListener(mAddress,'1'));
mTwo = (Button) findViewById(R.id.Button02);
mTwo.setOnClickListener(new DialKeyListener(mAddress,'2'));
mThree = (Button) findViewById(R.id.Button03);
mThree.setOnClickListener(new DialKeyListener(mAddress,'3'));
mFour = (Button) findViewById(R.id.Button04);
mFour.setOnClickListener(new DialKeyListener(mAddress,'4'));
mFive = (Button) findViewById(R.id.Button05);
mFive.setOnClickListener(new DialKeyListener(mAddress,'5'));
mSix = (Button) findViewById(R.id.Button06);
mSix.setOnClickListener(new DialKeyListener(mAddress,'6'));
mSeven = (Button) findViewById(R.id.Button07);
mSeven.setOnClickListener(new DialKeyListener(mAddress,'7'));
mEight = (Button) findViewById(R.id.Button08);
mEight.setOnClickListener(new DialKeyListener(mAddress,'8'));
mNine = (Button) findViewById(R.id.Button09);
mNine.setOnClickListener(new DialKeyListener(mAddress,'9'));
mStar = (Button) findViewById(R.id.ButtonStar);
mStar.setOnClickListener(new DialKeyListener(mAddress,'*'));
mHash = (Button) findViewById(R.id.ButtonHash);
mHash.setOnClickListener(new DialKeyListener(mAddress,'#'));
if (mZero != null) {
mZero.setOnClickListener(new DialKeyListener(mAddress,'0'));
mOne = (Button) findViewById(R.id.Button01) ;
mOne.setOnClickListener(new DialKeyListener(mAddress,'1'));
mTwo = (Button) findViewById(R.id.Button02);
mTwo.setOnClickListener(new DialKeyListener(mAddress,'2'));
mThree = (Button) findViewById(R.id.Button03);
mThree.setOnClickListener(new DialKeyListener(mAddress,'3'));
mFour = (Button) findViewById(R.id.Button04);
mFour.setOnClickListener(new DialKeyListener(mAddress,'4'));
mFive = (Button) findViewById(R.id.Button05);
mFive.setOnClickListener(new DialKeyListener(mAddress,'5'));
mSix = (Button) findViewById(R.id.Button06);
mSix.setOnClickListener(new DialKeyListener(mAddress,'6'));
mSeven = (Button) findViewById(R.id.Button07);
mSeven.setOnClickListener(new DialKeyListener(mAddress,'7'));
mEight = (Button) findViewById(R.id.Button08);
mEight.setOnClickListener(new DialKeyListener(mAddress,'8'));
mNine = (Button) findViewById(R.id.Button09);
mNine.setOnClickListener(new DialKeyListener(mAddress,'9'));
mStar = (Button) findViewById(R.id.ButtonStar);
mStar.setOnClickListener(new DialKeyListener(mAddress,'*'));
mHash = (Button) findViewById(R.id.ButtonHash);
mHash.setOnClickListener(new DialKeyListener(mAddress,'#'));
}
mStatus = (TextView) findViewById(R.id.status_label);
theDialer = this;
} catch (Exception e) {
Log.e(Linphone.TAG,"Cannot start linphone",e);
Log.e(LinphoneService.TAG,"Cannot start linphone",e);
}
}

View file

@ -0,0 +1,106 @@
/*
DialerActivity.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone;
import java.util.List;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCallLog;
import org.linphone.core.LinphoneCallLog.CallDirection;
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class HistoryActivity extends ListActivity {
LayoutInflater mInflater;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
protected void onResume() {
super.onResume();
setListAdapter(new CallHistoryAdapter(this));
}
class CallHistoryAdapter extends BaseAdapter {
private final Context mContext;
final List<LinphoneCallLog> mLogs;
CallHistoryAdapter(Context aContext) {
mContext = aContext;
mLogs = LinphoneService.instance().getLinphoneCore().getCallLogs();
}
public int getCount() {
return mLogs.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LinphoneCallLog lLog = mLogs.get(position);
View lView=null;
LinphoneAddress lAddress;
lView = mInflater.inflate(R.layout.history_cell, null);
TextView lFirstLineView = (TextView) lView.findViewById(R.id.history_cell_first_line);
TextView lSecondLineView = (TextView) lView.findViewById(R.id.history_cell_second_line);
ImageView lDirectionImage = (ImageView) lView.findViewById(R.id.history_cell_icon);
if (lLog.getDirection() == CallDirection.Callincoming) {
lAddress = lLog.getFrom();
lDirectionImage.setImageResource(R.drawable.in_call);
} else {
lAddress = lLog.getTo();
lDirectionImage.setImageResource(R.drawable.out_call);
}
if (lAddress.getDisplayName() == null) {
lFirstLineView.setText(lAddress.getUserName());
lSecondLineView.setVisibility(View.GONE);
} else {
lFirstLineView.setText(lAddress.getDisplayName());
lSecondLineView.setText(lAddress.getUserName());
}
return lView;
}
}
}

View file

@ -0,0 +1,166 @@
/*
LinphoneActivity.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone;
import android.app.AlertDialog;
import android.app.TabActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TabHost;
public class LinphoneActivity extends TabActivity {
public static String DIALER_TAB = "dialer";
private AudioManager mAudioManager;
private static LinphoneActivity theLinphoneActivity;
protected static LinphoneActivity instance()
{
if (theLinphoneActivity == null) {
throw new RuntimeException("LinphoneActivity not instanciated yet");
} else {
return theLinphoneActivity;
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
theLinphoneActivity = this;
mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE));
TabHost lTabHost = getTabHost(); // The activity TabHost
TabHost.TabSpec spec; // Reusable TabSpec for each tab
//Call History
Intent lHistoryItent = new Intent().setClass(this, HistoryActivity.class);
spec = lTabHost.newTabSpec("history").setIndicator(getString(R.string.tab_history),
null)
.setContent(lHistoryItent);
lTabHost.addTab(spec);
// dialer
Intent lDialerIntent = new Intent().setClass(this, DialerActivity.class);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = lTabHost.newTabSpec("dialer").setIndicator(getString(R.string.tab_dialer),
getResources().getDrawable(android.R.drawable.ic_menu_call))
.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),
null)
.setContent(lContactItent);
lTabHost.addTab(spec);
lTabHost.setCurrentTabByTag("dialer");
// start linphone as background
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, LinphoneService.class);
startService(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isFinishing()) {
//restaure audio settings
mAudioManager.setSpeakerphoneOn(true);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.setRouting(AudioManager.MODE_NORMAL,
AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, LinphoneService.class);
stopService(intent);
}
theLinphoneActivity = null;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the currently selected menu XML resource.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.linphone_activity_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_settings:
startprefActivity();
return true;
case R.id.menu_exit:
finish();
break;
default:
Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]");
break;
}
return false;
}
private void startprefActivity() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, LinphonePreferencesActivity.class);
startActivity(intent);
}
public void initFromConf() throws LinphoneException {
try {
LinphoneService.instance().initFromConf();
} catch (LinphoneConfigException e) {
handleBadConfig(e.getMessage());
}
}
private void handleBadConfig(String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.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) {
startprefActivity();
}
})
.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
builder.create().show();
}
}

View file

@ -0,0 +1,40 @@
/*
LinphoneCoreException.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone;
@SuppressWarnings("serial")
public class LinphoneConfigException extends LinphoneException {
public LinphoneConfigException() {
super();
}
public LinphoneConfigException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
public LinphoneConfigException(String detailMessage) {
super(detailMessage);
}
public LinphoneConfigException(Throwable throwable) {
super(throwable);
}
}

View file

@ -36,9 +36,9 @@ public class LinphonePreferencesActivity extends PreferenceActivity {
protected void onStop() {
super.onStop();
try {
Linphone.getLinphone().initFromConf();
} catch (LinphoneCoreException e) {
Log.e(Linphone.TAG, "cannot update config",e);
LinphoneActivity.instance().initFromConf();
} catch (LinphoneException e) {
Log.e(LinphoneService.TAG, "cannot update config",e);
}
}

View file

@ -35,12 +35,16 @@ import org.linphone.core.LinphoneProxyConfig;
import android.app.AlertDialog;
import android.app.Service;
import android.app.TabActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
@ -50,7 +54,7 @@ import android.view.MenuItem;
import android.widget.TabHost;
import android.widget.Toast;
public class Linphone extends TabActivity implements LinphoneCoreListener {
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";
@ -58,26 +62,26 @@ public class Linphone extends TabActivity implements LinphoneCoreListener {
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";
private static Linphone theLinphone;
private static LinphoneService theLinphone;
private LinphoneCore mLinphoneCore;
private SharedPreferences mPref;
Timer mTimer = new Timer("Linphone scheduler");
public static String DIALER_TAB = "dialer";
private Handler mIteratehandler;
static Linphone getLinphone() {
static LinphoneService instance() {
if (theLinphone == null) {
throw new RuntimeException("LinphoneActivity not instanciated yet");
} else {
return theLinphone;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
public void onCreate() {
super.onCreate();
theLinphone = this;
mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
try {
copyAssetsFromPackage();
@ -106,31 +110,6 @@ public class Linphone extends TabActivity implements LinphoneCoreListener {
mTimer.scheduleAtFixedRate(lTask, 0, 100);
TabHost lTabHost = getTabHost(); // The activity TabHost
TabHost.TabSpec spec; // Reusable TabSpec for each tab
// Create an Intent to launch an Activity for the tab (to be reused)
Intent lDialerIntent = new Intent().setClass(this, DialerActivity.class);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = lTabHost.newTabSpec("dialer").setIndicator(getString(R.string.tab_dialer),
getResources().getDrawable(android.R.drawable.ic_menu_call))
.setContent(lDialerIntent);
lTabHost.addTab(spec);
// Do the same for the other tabs
Intent lContactItent = new Intent().setClass(this, ContactPickerActivity.class);
spec = lTabHost.newTabSpec("contact").setIndicator(getString(R.string.tab_contact),
null)
.setContent(lContactItent);
lTabHost.addTab(spec);
lTabHost.setCurrentTabByTag("dialer");
@ -141,11 +120,7 @@ public class Linphone extends TabActivity implements LinphoneCoreListener {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isFinishing()) System.exit(0); // FIXME to destroy liblinphone
}
private void copyAssetsFromPackage() throws IOException {
@ -204,53 +179,24 @@ public class Linphone extends TabActivity implements LinphoneCoreListener {
// TODO Auto-generated method stub
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the currently selected menu XML resource.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.linphone_activity_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_settings:
startprefActivity();
return true;
case R.id.menu_exit:
finish();
break;
default:
Log.e(TAG, "Unknown menu item ["+item+"]");
break;
}
return false;
}
public void initFromConf() throws LinphoneCoreException {
public void initFromConf() throws LinphoneConfigException, LinphoneException {
//1 read proxy config from preferences
String lUserName = mPref.getString(getString(R.string.pref_username_key), null);
if (lUserName == null) {
handleBadConfig(getString(R.string.wrong_username));
return;
throw new LinphoneConfigException(getString(R.string.wrong_username));
}
String lPasswd = mPref.getString(getString(R.string.pref_passwd_key), null);
if (lPasswd == null) {
handleBadConfig(getString(R.string.wrong_passwd));
return;
throw new LinphoneConfigException(getString(R.string.wrong_passwd));
}
String lDomain = mPref.getString(getString(R.string.pref_domain_key), null);
if (lDomain == null) {
handleBadConfig(getString(R.string.wrong_domain));
return;
throw new LinphoneConfigException(getString(R.string.wrong_domain));
}
@ -259,62 +205,58 @@ public class Linphone extends TabActivity implements LinphoneCoreListener {
LinphoneAuthInfo lAuthInfo = LinphoneCoreFactory.instance().createAuthInfo(lUserName, lPasswd);
mLinphoneCore.addAuthInfo(lAuthInfo);
//proxy
String lProxy = mPref.getString(getString(R.string.pref_proxy_key), "sip:"+lDomain);
//get Default proxy if any
LinphoneProxyConfig lDefaultProxyConfig = mLinphoneCore.getDefaultProxyConfig();
String lIdentity = "sip:"+lUserName+"@"+lDomain;
if (lDefaultProxyConfig == null) {
lDefaultProxyConfig = mLinphoneCore.createProxyConfig(lIdentity, lProxy, null,true);
mLinphoneCore.addtProxyConfig(lDefaultProxyConfig);
mLinphoneCore.setDefaultProxyConfig(lDefaultProxyConfig);
try {
if (lDefaultProxyConfig == null) {
lDefaultProxyConfig = mLinphoneCore.createProxyConfig(lIdentity, lProxy, null,true);
mLinphoneCore.addtProxyConfig(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);
} else {
lDefaultProxyConfig.edit();
lDefaultProxyConfig.setIdentity(lIdentity);
lDefaultProxyConfig.setProxy(lProxy);
lDefaultProxyConfig.enableRegister(true);
lDefaultProxyConfig.done();
}
//escape +
lDefaultProxyConfig.setDialEscapePlus(true);
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(true);
}
}catch (LinphoneCoreException e) {
throw new LinphoneException(e);
}
}
private void handleBadConfig(String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.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) {
startprefActivity();
}
})
.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
builder.create().show();
}
private void startprefActivity() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(Linphone.this, LinphonePreferencesActivity.class);
startActivity(intent);
}
protected LinphoneCore getLinphoneCore() {
return mLinphoneCore;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
System.exit(0); // FIXME to destroy liblinphone
}
}

View file

@ -0,0 +1,31 @@
/*
LinPhoneCallLog.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
public interface LinphoneCallLog {
public enum CallDirection {
CallOutgoing,Callincoming
}
public LinphoneAddress getFrom();
public LinphoneAddress getTo ();
public LinphoneCallLog.CallDirection getDirection();
}

View file

@ -0,0 +1,46 @@
/*
LinPhoneCallLogImpl.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
class LinphoneCallLogImpl implements LinphoneCallLog {
protected final long nativePtr;
private native long getFrom(long nativePtr);
private native long getTo(long nativePtr);
private native boolean isIncoming(long nativePtr);
LinphoneCallLogImpl(long aNativePtr) {
nativePtr = aNativePtr;
}
public CallDirection getDirection() {
return isIncoming(nativePtr)?CallDirection.Callincoming:CallDirection.CallOutgoing;
}
public LinphoneAddress getFrom() {
return new LinphoneAddressImpl(getFrom(nativePtr));
}
public LinphoneAddress getTo() {
return new LinphoneAddressImpl(getTo(nativePtr));
}
}

View file

@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
import java.util.List;
public interface LinphoneCore {
@ -116,4 +118,9 @@ public interface LinphoneCore {
public void acceptCall();
/**
* @return a list of LinphoneCallLog
*/
public List<LinphoneCallLog> getCallLogs();
}

View file

@ -20,6 +20,8 @@ package org.linphone.core;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
class LinphoneCoreImpl implements LinphoneCore {
@ -42,6 +44,9 @@ class LinphoneCoreImpl implements LinphoneCore {
private native boolean isInCall(long nativePtr);
private native boolean isInComingInvitePending(long nativePtr);
private native void acceptCall(long nativePtr);
private native long getCallLog(long nativePtr,int position);
private native int getNumberOfCallLogs(long nativePtr);
LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException {
mListener=listener;
@ -109,4 +114,11 @@ class LinphoneCoreImpl implements LinphoneCore {
acceptCall(nativePtr);
}
public List<LinphoneCallLog> getCallLogs() {
List<LinphoneCallLog> logs = new ArrayList<LinphoneCallLog>();
for (int i=0;i < getNumberOfCallLogs(nativePtr);i++) {
logs.add(new LinphoneCallLogImpl(getCallLog(nativePtr, i)));
}
return logs;
}
}

View file

@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
import org.linphone.Linphone;
import org.linphone.LinphoneService;
import android.util.Log;
@ -35,14 +35,14 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig {
setProxy(proxy);
enableRegister(enableRegister);
ownPtr=true;
Log.w(Linphone.TAG, "route ["+route+"] not used yet");
Log.w(LinphoneService.TAG, "route ["+route+"] not used yet");
}
protected LinphoneProxyConfigImpl(long aNativePtr) {
nativePtr = aNativePtr;
ownPtr=false;
}
protected void finalize() throws Throwable {
Log.e(Linphone.TAG,"fixme, should release underlying proxy config");
Log.e(LinphoneService.TAG,"fixme, should release underlying proxy config");
// FIXME if (ownPtr) delete(nativePtr);
}
private native long newLinphoneProxyConfig();