Merge remote branch 'origin/cleaning'
This commit is contained in:
commit
d1b393aa9c
65 changed files with 3811 additions and 1873 deletions
|
@ -3,34 +3,120 @@
|
||||||
package="org.linphone"
|
package="org.linphone"
|
||||||
android:versionCode="1104" android:versionName="1.1.4" android:installLocation="auto">
|
android:versionCode="1104" android:versionName="1.1.4" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="3" />
|
<uses-sdk android:minSdkVersion="3" />
|
||||||
<application android:label="@string/app_name" android:debuggable = "true" android:icon="@drawable/logo_linphone_57x57">
|
|
||||||
|
|
||||||
|
|
||||||
<activity android:name=".LinphoneActivity"
|
|
||||||
|
<!-- Don't remove the space after android:debuggable: it prevents ndk-build to try including gdbserver and crash gcc -->
|
||||||
|
<application android:label="@string/app_name" android:debuggable ="true" android:icon="@drawable/logo_linphone_57x57">
|
||||||
|
|
||||||
|
<activity android:name="org.linphone.LinphoneActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@android:style/Theme.NoTitleBar"
|
android:theme="@android:style/Theme.NoTitleBar"
|
||||||
android:launchMode="singleTask">
|
android:launchMode="singleTask"
|
||||||
|
> <!-- android:alwaysRetainTaskState="true" clearTaskOnLaunch="false"-->
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
|
||||||
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.CALL" />
|
<action android:name="android.intent.action.CALL" />
|
||||||
|
<action android:name="android.intent.action.CALL_PRIVILEGED" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:scheme="tel" />
|
<data android:scheme="tel" />
|
||||||
|
<data android:scheme="sip" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SENDTO" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:scheme="sip" /><!-- maybe one day -->
|
||||||
|
<data android:scheme="imto" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
|
<activity android:name="org.linphone.FirstLoginActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".core.tutorials.TestVideoActivity"
|
|
||||||
|
<activity android:name="org.linphone.IncallActivity"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="org.linphone.LinphonePreferencesActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="org.linphone.DialerActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="org.linphone.VideoCallActivity"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||||
|
android:launchMode="singleTop">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="ContactPickerActivityNew">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="ContactPickerActivityOld">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="org.linphone.HistoryActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="org.linphone.AboutActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<service android:name="org.linphone.LinphoneService" />
|
||||||
|
|
||||||
|
<receiver android:name="org.linphone.NetworkManager">
|
||||||
|
<intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action></intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:name="org.linphone.BootReceiver">
|
||||||
|
<intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"></action></intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<activity android:name="core.tutorials.video.TestVideoActivity"
|
||||||
android:label="Video test"
|
android:label="Video test"
|
||||||
android:theme="@android:style/Theme.NoTitleBar"
|
android:theme="@android:style/Theme.NoTitleBar"
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".core.tutorials.TutorialHelloWorldActivity"
|
<activity android:name="org.linphone.core.tutorials.TutorialHelloWorldActivity"
|
||||||
android:label="Hello World"
|
android:label="Hello World"
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -38,7 +124,7 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".core.tutorials.TutorialRegistrationActivity"
|
<activity android:name="org.linphone.core.tutorials.TutorialRegistrationActivity"
|
||||||
android:label="Registration"
|
android:label="Registration"
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -46,7 +132,7 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".core.tutorials.TutorialBuddyStatusActivity"
|
<activity android:name="org.linphone.core.tutorials.TutorialBuddyStatusActivity"
|
||||||
android:label="Buddy status"
|
android:label="Buddy status"
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -54,7 +140,7 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".core.tutorials.TutorialChatRoomActivity"
|
<activity android:name="org.linphone.core.tutorials.TutorialChatRoomActivity"
|
||||||
android:label="Chat Room"
|
android:label="Chat Room"
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -70,52 +156,9 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".LinphonePreferencesActivity">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity android:name=".DialerActivity">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity android:name=".VideoCallActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity android:name=".ContactPickerActivity">
|
|
||||||
<intent-filter>
|
|
||||||
<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>
|
|
||||||
<activity android:name=".AboutActivity">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<service android:name=".LinphoneService">
|
|
||||||
</service>
|
|
||||||
<receiver android:name="NetworkManager">
|
|
||||||
<intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
<!-- receiver android:name="OutgoingCallReceiver" >
|
|
||||||
<intent-filter android:priority="0"><action android:name="android.intent.action.NEW_OUTGOING_CALL"></action>
|
|
||||||
</intent-filter>
|
|
||||||
</receiver-->
|
|
||||||
<receiver android:name="BootReceiver" >
|
|
||||||
<intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"></action>
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
|
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
|
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||||
|
|
BIN
res/drawable/numpad.png
Normal file
BIN
res/drawable/numpad.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -3,63 +3,60 @@
|
||||||
android:orientation="vertical" android:layout_width="fill_parent"
|
android:orientation="vertical" android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent">
|
android:layout_height="fill_parent">
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/LinearLayout02"
|
|
||||||
android:layout_height="wrap_content" android:layout_width="fill_parent">
|
|
||||||
<LinearLayout android:layout_height="wrap_content"
|
|
||||||
android:layout_width="fill_parent" android:id="@+id/Addresslayout">
|
|
||||||
<EditText android:id="@+id/SipUri" android:layout_height="wrap_content"
|
|
||||||
android:hint="sip:" android:layout_width="fill_parent" android:lines="1"
|
|
||||||
android:layout_weight="0.2"></EditText>
|
|
||||||
<Button android:layout_height="wrap_content" android:id="@+id/Erase"
|
|
||||||
android:layout_width="fill_parent" android:layout_weight="0.8"
|
|
||||||
android:text="<"></Button>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent">
|
||||||
<FrameLayout android:layout_height="wrap_content"
|
<LinearLayout android:layout_height="wrap_content"
|
||||||
android:layout_width="fill_parent" android:id="@+id/IncallAddressLayout">
|
android:layout_width="fill_parent" android:id="@+id/Addresslayout">
|
||||||
<EditText android:text="@+id/EditText01"
|
<org.linphone.ui.AddressText android:id="@+id/SipUri" android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content" android:lines="1"
|
android:hint="sip:" android:layout_width="fill_parent" android:lines="1"
|
||||||
android:id="@+id/DisplayNameView" android:clickable="false"
|
android:layout_weight="0.2" android:editable="@bool/allow_edit_in_dialer"/>
|
||||||
android:cursorVisible="false" android:gravity="center"
|
<org.linphone.ui.EraseButton android:layout_height="wrap_content" android:id="@+id/Erase"
|
||||||
android:layout_width="fill_parent"></EditText>
|
android:layout_width="fill_parent" android:layout_weight="0.8"
|
||||||
<org.linphone.component.ToggleImageButton
|
android:text="<"/>
|
||||||
android:id="@+id/mic_mute_button" android:layout_height="wrap_content"
|
|
||||||
android:layout_width="wrap_content" android:layout_weight="0.5"
|
|
||||||
checked="@drawable/mic_muted" unchecked="@drawable/mic_active"
|
|
||||||
android:layout_gravity="left|center_vertical" />
|
|
||||||
<org.linphone.component.ToggleImageButton
|
|
||||||
android:id="@+id/speaker_button" android:layout_height="wrap_content"
|
|
||||||
android:layout_width="wrap_content" android:layout_weight="0.5"
|
|
||||||
checked="@drawable/speaker_32_on" unchecked="@drawable/speaker_32_off"
|
|
||||||
android:layout_gravity="right|center_vertical" />
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
<TableLayout android:layout_width="fill_parent" android:id="@+id/Dialer"
|
|
||||||
android:layout_height="fill_parent" android:layout_weight="1">
|
|
||||||
<TableRow android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/IncallControlRow" >
|
|
||||||
<ImageButton android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/AddVideo" android:layout_weight="1" android:src="@drawable/startvideo_green" android:background="@drawable/clavier_bg"></ImageButton>
|
|
||||||
<ImageButton android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/HangUp" android:layout_weight="1" android:src="@drawable/stopcall_red" android:background="@drawable/clavier_bg"></ImageButton>
|
|
||||||
</TableRow>
|
|
||||||
</TableLayout>
|
|
||||||
<LinearLayout android:layout_height="fill_parent"
|
|
||||||
android:layout_width="fill_parent" android:id="@+id/CallControlRow" android:layout_weight="1">
|
|
||||||
<ImageButton android:id="@+id/Call"
|
|
||||||
android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25" android:background="@drawable/clavier_bg" android:src="@drawable/startcall_green">
|
|
||||||
</ImageButton>
|
|
||||||
<ImageButton android:layout_height="fill_parent" android:layout_width="fill_parent"
|
|
||||||
android:layout_weight="0.25" android:id="@+id/Decline" android:background="@drawable/clavier_bg" android:src="@drawable/stopcall_red"></ImageButton>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<EditText android:layout_width="fill_parent" android:id="@+id/status_label"
|
|
||||||
|
<FrameLayout android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent" android:id="@+id/IncallAddressLayout">
|
||||||
|
<EditText android:layout_height="wrap_content" android:lines="1"
|
||||||
|
android:id="@+id/DisplayNameView" android:clickable="false"
|
||||||
|
android:cursorVisible="false" android:gravity="center"
|
||||||
|
android:layout_width="fill_parent"></EditText>
|
||||||
|
<org.linphone.ui.MuteMicButton
|
||||||
|
android:id="@+id/mic_mute_button" android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content" android:layout_weight="0.5"
|
||||||
|
checked="@drawable/mic_muted" unchecked="@drawable/mic_active"
|
||||||
|
android:layout_gravity="left|center_vertical" />
|
||||||
|
<org.linphone.ui.SpeakerButton
|
||||||
|
android:id="@+id/speaker_button" android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content" android:layout_weight="0.5"
|
||||||
|
checked="@drawable/speaker_32_on" unchecked="@drawable/speaker_32_off"
|
||||||
|
android:layout_gravity="right|center_vertical" />
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<View android:layout_width="0px" android:visibility="invisible" android:layout_weight="1" android:layout_height="fill_parent" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout android:id="@+id/CallControlRow" android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="bottom">
|
||||||
|
<org.linphone.ui.CallButton android:id="@+id/Call"
|
||||||
|
android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="1" android:background="@drawable/clavier_bg" android:src="@drawable/startcall_green"/>
|
||||||
|
<org.linphone.ui.HangCallButton android:id="@+id/Decline" android:layout_height="fill_parent" android:layout_width="fill_parent"
|
||||||
|
android:layout_weight="1" android:background="@drawable/clavier_bg" android:src="@drawable/stopcall_red"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout android:id="@+id/IncallControlRow" android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="bottom">
|
||||||
|
<org.linphone.ui.AddVideoButton android:id="@+id/AddVideo" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="1" android:src="@drawable/startvideo_green" android:background="@drawable/clavier_bg"/>
|
||||||
|
<org.linphone.ui.HangCallButton android:id="@+id/HangUp" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="1" android:src="@drawable/stopcall_red" android:background="@drawable/clavier_bg"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<EditText android:id="@+id/status_label" android:layout_width="fill_parent"
|
||||||
android:clickable="false" android:focusable="false"
|
android:clickable="false" android:focusable="false"
|
||||||
android:cursorVisible="false" android:textSize="12sp" android:height="15sp"
|
android:cursorVisible="false" android:textSize="12sp" android:height="15sp"
|
||||||
android:background="@android:color/transparent" android:textColor="@android:color/white"
|
android:background="@android:color/transparent" android:textColor="@android:color/white"
|
||||||
android:lines="1" android:layout_height="wrap_content"></EditText>
|
android:lines="1" android:layout_height="wrap_content"></EditText>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
14
res/layout/contact_picker.xml
Normal file
14
res/layout/contact_picker.xml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<EditText android:id="@+id/contactFilter"
|
||||||
|
android:layout_height="wrap_content" android:hint="@string/filter_contacts"
|
||||||
|
android:layout_width="match_parent"></EditText>
|
||||||
|
|
||||||
|
<ListView android:id="@+id/contactList"
|
||||||
|
android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
</LinearLayout>
|
|
@ -1,17 +1,18 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:linphone="http://schemas.android.com/apk/res/linphone"
|
||||||
android:orientation="vertical" android:layout_width="fill_parent"
|
android:orientation="vertical" android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent">
|
android:layout_height="fill_parent">
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/LinearLayout02"
|
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent">
|
||||||
android:layout_height="wrap_content" android:layout_width="fill_parent">
|
|
||||||
<LinearLayout android:layout_height="wrap_content"
|
<LinearLayout android:layout_height="wrap_content"
|
||||||
android:layout_width="fill_parent" android:id="@+id/Addresslayout">
|
android:layout_width="fill_parent" android:id="@+id/Addresslayout">
|
||||||
<EditText android:id="@+id/SipUri" android:background="@drawable/clavier_bg_grey" android:hint="sip:" android:layout_width="fill_parent"
|
<org.linphone.ui.AddressText android:id="@+id/SipUri" android:background="@drawable/clavier_bg_grey" android:hint="sip:" android:layout_width="fill_parent"
|
||||||
android:lines="1" android:layout_weight="0.2" android:layout_height="fill_parent" android:padding="10px" android:maxLines="1"></EditText>
|
android:lines="1" android:layout_weight="0.2" android:layout_height="fill_parent" android:padding="10px" android:maxLines="1" android:editable="@bool/allow_edit_in_dialer"/>
|
||||||
<Button android:layout_height="fill_parent" android:background="@drawable/clavier_bg" android:id="@+id/Erase"
|
<org.linphone.ui.EraseButton android:layout_height="fill_parent" android:background="@drawable/clavier_bg" android:id="@+id/Erase"
|
||||||
android:layout_width="fill_parent" android:layout_weight="0.8" android:textSize="20sp"
|
android:layout_width="fill_parent" android:layout_weight="0.8" android:textSize="20sp"
|
||||||
android:textStyle="bold" android:text="<" android:layout_gravity="top" android:textColor="@android:color/black"></Button>
|
android:textStyle="bold" android:text="<" android:layout_gravity="top" android:textColor="@android:color/black"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,100 +23,32 @@
|
||||||
android:layout_height="wrap_content" android:layout_width="wrap_content"
|
android:layout_height="wrap_content" android:layout_width="wrap_content"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:id="@+id/DisplayNameView" android:clickable="false"
|
android:id="@+id/DisplayNameView" android:clickable="false"
|
||||||
android:cursorVisible="false" android:layout_gravity="center"
|
android:cursorVisible="false" android:layout_gravity="center"></EditText>
|
||||||
></EditText>
|
<org.linphone.ui.MuteMicButton android:id="@+id/mic_mute_button"
|
||||||
<org.linphone.component.ToggleImageButton android:id="@+id/mic_mute_button"
|
|
||||||
android:layout_height="wrap_content" android:layout_width="wrap_content"
|
android:layout_height="wrap_content" android:layout_width="wrap_content"
|
||||||
checked="@drawable/mic_muted" unchecked="@drawable/mic_active"
|
checked="@drawable/mic_muted" unchecked="@drawable/mic_active"
|
||||||
android:layout_gravity="left|center_vertical"/>
|
android:layout_gravity="left|center_vertical"/>
|
||||||
<org.linphone.component.ToggleImageButton android:id="@+id/speaker_button"
|
<org.linphone.ui.SpeakerButton android:id="@+id/speaker_button"
|
||||||
android:layout_height="wrap_content" android:layout_width="wrap_content"
|
android:layout_height="wrap_content" android:layout_width="wrap_content"
|
||||||
checked="@drawable/speaker_32_on" unchecked="@drawable/speaker_32_off"
|
checked="@drawable/speaker_32_on" unchecked="@drawable/speaker_32_off"
|
||||||
android:layout_gravity="right|center_vertical"/>
|
android:layout_gravity="right|center_vertical"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TableLayout android:layout_width="fill_parent" android:id="@+id/Dialer"
|
<org.linphone.ui.Numpad android:id="@+id/Dialer" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="4" />
|
||||||
android:layout_height="fill_parent" android:layout_weight="1">
|
|
||||||
<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:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:id="@+id/Button02" android:text="2"
|
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:id="@+id/Button03" android:text="3"
|
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></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:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:text="5" android:id="@+id/Button05"
|
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:id="@+id/Button06" android:text="6"
|
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></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:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:id="@+id/Button08" android:text="8"
|
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:text="9" android:id="@+id/Button09"
|
|
||||||
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></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:id="@+id/ButtonStar"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent" android:text="0+" android:id="@+id/Button00"
|
|
||||||
android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
<Button android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent" android:id="@+id/ButtonHash"
|
|
||||||
android:text="#" android:textStyle="bold" android:textSize="20sp"
|
|
||||||
android:layout_weight="1" android:background="@drawable/clavier_bg" android:textColor="@android:color/black"></Button>
|
|
||||||
</TableRow>
|
|
||||||
|
|
||||||
|
<LinearLayout android:layout_height="wrap_content" android:orientation="vertical" android:layout_width="fill_parent">
|
||||||
|
<LinearLayout android:id="@+id/CallControlRow" android:layout_height="fill_parent" android:layout_width="fill_parent">
|
||||||
|
<org.linphone.ui.CallButton android:id="@+id/Call" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25" android:src="@drawable/startcall_green" android:background="@drawable/clavier_bg"/>
|
||||||
|
<org.linphone.ui.HangCallButton android:id="@+id/Decline" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25" android:src="@drawable/stopcall_red" android:background="@drawable/clavier_bg"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout android:id="@+id/IncallControlRow" android:layout_height="fill_parent" android:layout_width="fill_parent">
|
||||||
|
<org.linphone.ui.AddVideoButton android:id="@+id/AddVideo" android:src="@drawable/startvideo_green" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25" android:background="@drawable/clavier_bg"/>
|
||||||
|
<org.linphone.ui.HangCallButton android:id="@+id/HangUp" android:src="@drawable/stopcall_red" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25" android:background="@drawable/clavier_bg"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<EditText 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" android:layout_width="fill_parent" android:background="@android:color/transparent" android:textColor="@android:color/white" />
|
||||||
|
|
||||||
<TableRow android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/IncallControlRow">
|
|
||||||
<ImageButton android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/AddVideo" android:layout_weight="1" android:src="@drawable/startvideo_green" android:background="@drawable/clavier_bg"></ImageButton>
|
|
||||||
<ImageButton android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/HangUp" android:layout_weight="1" android:src="@drawable/stopcall_red" android:background="@drawable/clavier_bg"></ImageButton>
|
|
||||||
</TableRow>
|
|
||||||
</TableLayout>
|
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/LinearLayout01" android:layout_height="wrap_content" android:orientation="vertical" android:layout_width="fill_parent">
|
|
||||||
<LinearLayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/CallControlRow">
|
|
||||||
<ImageButton android:id="@+id/Call" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25" android:src="@drawable/startcall_green" android:background="@drawable/clavier_bg"></ImageButton>
|
|
||||||
<ImageButton android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.25" android:id="@+id/Decline" android:src="@drawable/stopcall_red" android:background="@drawable/clavier_bg"></ImageButton>
|
|
||||||
</LinearLayout><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" android:background="@android:color/transparent" android:textColor="@android:color/white"></EditText>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
33
res/layout/first_login_view.xml
Normal file
33
res/layout/first_login_view.xml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:layout_width="fill_parent" a:layout_height="fill_parent" a:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<EditText a:id="@+id/login"
|
||||||
|
a:hint="@string/first_login_username"
|
||||||
|
a:layout_width="wrap_content" a:layout_height="wrap_content"
|
||||||
|
a:layout_marginTop="20sp" a:layout_marginRight="15sp" a:layout_gravity="right"
|
||||||
|
a:width="180sp"/>
|
||||||
|
|
||||||
|
<EditText a:id="@+id/password" a:password="true"
|
||||||
|
a:hint="@string/first_login_password"
|
||||||
|
a:layout_width="wrap_content" a:layout_height="wrap_content"
|
||||||
|
a:layout_marginTop="10sp" a:layout_marginRight="15sp" a:layout_gravity="right"
|
||||||
|
a:width="180sp"/>
|
||||||
|
|
||||||
|
<Button a:id="@+id/connect" a:text="@string/first_login_connect"
|
||||||
|
a:layout_width="wrap_content" a:layout_height="wrap_content"
|
||||||
|
a:layout_marginTop="20sp" a:layout_marginRight="15sp" a:layout_gravity="right"
|
||||||
|
a:width="180sp"/>
|
||||||
|
|
||||||
|
<View a:layout_width="wrap_content" a:layout_height="wrap_content" a:layout_weight="1" />
|
||||||
|
|
||||||
|
<ProgressBar a:id="@+id/progress_bar"
|
||||||
|
a:layout_width="wrap_content" a:layout_height="wrap_content"
|
||||||
|
a:layout_gravity="center|bottom" a:layout_marginTop="50sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View a:layout_width="wrap_content" a:layout_height="wrap_content" a:layout_weight="1" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
4
res/layout/hidden.xml
Normal file
4
res/layout/hidden.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="gone">
|
||||||
|
</LinearLayout>
|
48
res/layout/incall_view.xml
Normal file
48
res/layout/incall_view.xml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content">
|
||||||
|
<TextView android:id="@+id/incallContactName" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
|
||||||
|
<org.linphone.ui.IncallTimer android:id="@+id/incallElapsedTime" android:text="Calling..." android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/incallContactName"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<View android:layout_weight="1" android:layout_width="0px" android:layout_height="0px" android:visibility="invisible"/>
|
||||||
|
|
||||||
|
|
||||||
|
<FrameLayout android:layout_gravity="center" android:layout_margin="20dip"
|
||||||
|
android:layout_width="wrap_content" android:layout_height="wrap_content">
|
||||||
|
<TableLayout android:id="@+id/incallButtonsZone"
|
||||||
|
android:layout_width="wrap_content" android:layout_height="wrap_content">
|
||||||
|
<TableRow>
|
||||||
|
<org.linphone.ui.MuteMicButton checked="@drawable/mic_muted" unchecked="@drawable/mic_active" android:layout_width="wrap_content" android:layout_height="wrap_content" />
|
||||||
|
<RelativeLayout android:layout_gravity="center" ><Button android:id="@+id/incallNumpadShow" android:background="@drawable/numpad"
|
||||||
|
android:layout_width="wrap_content" android:layout_height="wrap_content"/></RelativeLayout>
|
||||||
|
<org.linphone.ui.SpeakerButton checked="@drawable/speaker_32_on" unchecked="@drawable/speaker_32_off" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow>
|
||||||
|
<org.linphone.ui.AddVideoButton android:id="@+id/AddVideo" android:src="@drawable/startvideo_green"
|
||||||
|
android:layout_height="wrap_content" android:layout_width="wrap_content" android:height="10px"
|
||||||
|
android:layout_column="1" />
|
||||||
|
</TableRow>
|
||||||
|
</TableLayout>
|
||||||
|
|
||||||
|
<org.linphone.ui.Numpad android:id="@+id/incallDialer" android:visibility="gone" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<View android:layout_weight="1" android:layout_width="0px" android:layout_height="0px" android:visibility="invisible"/>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content">
|
||||||
|
<org.linphone.ui.HangCallButton android:id="@+id/incallHang" android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/stopcall_red" android:background="@drawable/clavier_bg" android:layout_weight="10" />
|
||||||
|
|
||||||
|
<Button android:text="Close numpad" android:id="@+id/incallNumpadClose"
|
||||||
|
android:visibility="gone" android:layout_width="wrap_content"
|
||||||
|
android:layout_height="fill_parent" android:background="@drawable/clavier_bg" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
19
res/layout/incoming_call.xml
Normal file
19
res/layout/incoming_call.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:linphone="http://schemas.android.com/apk/res/linphone"
|
||||||
|
android:orientation="vertical" android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<!-- <View android:layout_height="0px" android:layout_width="0px" android:layout_weight="1" />-->
|
||||||
|
|
||||||
|
<LinearLayout android:layout_height="fill_parent" android:layout_width="fill_parent"
|
||||||
|
android:gravity="bottom">
|
||||||
|
<org.linphone.ui.CallButton android:id="@+id/Call"
|
||||||
|
android:layout_height="wrap_content" android:layout_width="fill_parent"
|
||||||
|
android:layout_weight="0.25" android:src="@drawable/startcall_green" android:background="@drawable/clavier_bg"/>
|
||||||
|
<org.linphone.ui.HangCallButton android:id="@+id/Decline"
|
||||||
|
android:layout_height="wrap_content" android:layout_width="fill_parent"
|
||||||
|
android:layout_weight="0.25" android:src="@drawable/stopcall_red" android:background="@drawable/clavier_bg"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
31
res/layout/numpad.xml
Normal file
31
res/layout/numpad.xml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1">
|
||||||
|
|
||||||
|
<TableRow android:layout_weight="1">
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit1" android:text="1" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit2" android:text="2" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit3" android:text="3" style="@style/DialerDigit" />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow android:layout_weight="1">
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit4" android:text="4" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit5" android:text="5" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit6" android:text="6" style="@style/DialerDigit" />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow android:layout_weight="1">
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit7" android:text="7" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit8" android:text="8" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit9" android:text="9" style="@style/DialerDigit" />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow android:layout_weight="1">
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/DigitStar" android:text="*" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/Digit00" android:text="0+" style="@style/DialerDigit" />
|
||||||
|
<org.linphone.ui.Digit android:id="@+id/DigitHash" android:text="#" style="@style/DialerDigit" />
|
||||||
|
</TableRow>
|
||||||
|
</TableLayout>
|
||||||
|
<!-- android:layout_width="fill_parent" android:layout_height="fill_parent" android:textColor="@android:color/black" android:background="@drawable/clavier_bg" android:textStyle="bold" android:textSize="20sp" android:layout_weight="1" -->
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:padding="6dip" android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/outcall_chooser_linear_v" android:layout_width="fill_parent"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/LinearLayout02"
|
|
||||||
android:layout_height="wrap_content" android:layout_width="fill_parent"
|
|
||||||
android:layout_weight="0.5" android:gravity="center">
|
|
||||||
<ImageButton android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" android:src="@drawable/logo_linphone_57x57"
|
|
||||||
android:id="@+id/outcall_chooser_linphone_button" android:background="@android:color/transparent"></ImageButton>
|
|
||||||
</LinearLayout>
|
|
||||||
<LinearLayout android:id="@+id/LinearLayout01"
|
|
||||||
android:layout_width="fill_parent" android:layout_weight=".5"
|
|
||||||
android:gravity="center" android:layout_height="fill_parent">
|
|
||||||
<Button android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" android:text="@string/outcall_chooser_cellular"
|
|
||||||
android:layout_below="@+id/outcall_text" android:layout_alignRight="@+id/outcall_text"
|
|
||||||
android:id="@+id/outcall_chooser_cellular_button"></Button>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -40,7 +40,6 @@ el_transmit_thres=1.7
|
||||||
ng_floorgain=0.01
|
ng_floorgain=0.01
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[video]
|
[video]
|
||||||
size=qvga-portrait
|
size=qvga-portrait
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string-array name="pref_handle_outcall_keys">
|
|
||||||
<item>off</item>
|
|
||||||
<item>ask_for_outcall_interception</item>
|
|
||||||
<item>alway_intercept_out_call</item>
|
|
||||||
</string-array>
|
|
||||||
</resources>
|
|
23
res/values/custom.xml
Normal file
23
res/values/custom.xml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="app_name">Linphone</string>
|
||||||
|
<string name="default_domain">test.linphone.org</string>
|
||||||
|
|
||||||
|
<bool name="use_android_contact_picker">true</bool>
|
||||||
|
<!-- <string name="merge_another_contact_provider">content://something</string>-->
|
||||||
|
|
||||||
|
<bool name="useFirstLoginActivity">false</bool>
|
||||||
|
<bool name="useMenuSettings">true</bool>
|
||||||
|
<bool name="useMenuAbout">true</bool>
|
||||||
|
<bool name="use_incall_activity">true</bool>
|
||||||
|
<bool name="use_video_activity">false</bool>
|
||||||
|
<bool name="show_full_remote_address_on_incoming_call">true</bool>
|
||||||
|
|
||||||
|
<string name="notification_title">Linphone</string>
|
||||||
|
<bool name="allow_edit_in_dialer">true</bool>
|
||||||
|
<string name="notification_registered">registered to %s </string>
|
||||||
|
<string name="notification_register_failure">fails to register to %s</string>
|
||||||
|
</resources>
|
||||||
|
|
12
res/values/digit_style.xml
Normal file
12
res/values/digit_style.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="DialerDigit">
|
||||||
|
<item name="android:layout_width">fill_parent</item>
|
||||||
|
<item name="android:layout_height">fill_parent</item>
|
||||||
|
<item name="android:textColor">@android:color/black</item>
|
||||||
|
<item name="android:background">@drawable/clavier_bg</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
|
<item name="android:textSize">20sp</item>
|
||||||
|
<item name="android:layout_weight">1</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
|
@ -1,10 +1,40 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="pref_transport_udp_key">pref_transport_udp_key</string>
|
||||||
|
<string name="pref_transport_tcp_key">pref_transport_tcp_key</string>
|
||||||
|
<string name="pref_transport_tls_key">pref_transport_tls_key</string>
|
||||||
|
<string name="pref_transport_use_standard_ports_key">pref_transport_use_standard_ports_key</string>
|
||||||
|
|
||||||
|
<string name="pref_echo_canceller_calibration_key">pref_echo_canceller_calibration_key</string>
|
||||||
<string name="pref_prefix_key">pref_prefix_key</string>
|
<string name="pref_prefix_key">pref_prefix_key</string>
|
||||||
<string name="pref_proxy_key">pref_proxy_key</string>
|
<string name="pref_proxy_key">pref_proxy_key</string>
|
||||||
<string name="pref_domain_key">pref_domain_key</string>
|
<string name="pref_domain_key">pref_domain_key</string>
|
||||||
<string name="pref_passwd_key">pref_passwd_key</string>
|
<string name="pref_passwd_key">pref_passwd_key</string>
|
||||||
<string name="pref_username_key">pref_username_key</string>
|
<string name="pref_username_key">pref_username_key</string>
|
||||||
<string name="pref_debug_key">pref_debug_key</string>
|
<string name="pref_debug_key">pref_debug_key</string>
|
||||||
|
<string name="first_launch_suceeded_once_key">first_launch_suceeded_once_key</string>
|
||||||
|
|
||||||
|
<string name="pref_video_use_front_camera_key">pref_video_use_front_camera_key</string>
|
||||||
|
<string name="pref_video_codec_h263_key">pref_video_codec_h263_key</string>
|
||||||
|
<string name="pref_video_codec_mpeg4_key">pref_video_codec_mpeg4_key</string>
|
||||||
|
<string name="pref_video_codec_h264_key">pref_video_codec_h264_key</string>
|
||||||
|
<string name="pref_video_automatically_share_my_video_key">pref_video_automatically_share_my_video_key</string>
|
||||||
|
<string name="pref_video_initiate_call_with_video_key">pref_video_initiate_call_with_video_key</string>
|
||||||
|
<string name="pref_video_enable_key">pref_video_enable_key</string>
|
||||||
|
<string name="pref_escape_plus_key">pref_escape_plus_key</string>
|
||||||
|
<string name="pref_echo_cancellation_key">pref_echo_cancellation_key</string>
|
||||||
|
<string name="pref_autostart_key">pref_autostart_key</string>
|
||||||
|
<string name="pref_enable_outbound_proxy_key">Outbound proxy</string>
|
||||||
|
<string name="pref_codec_pcma_key">pref_codec_pcma_key</string>
|
||||||
|
<string name="pref_codec_pcmu_key">pref_codec_pcmu_key</string>
|
||||||
|
<string name="pref_codec_gsm_key">pref_codec_gsm_key</string>
|
||||||
|
<string name="pref_codec_ilbc_key">pref_codec_ilbc_key</string>
|
||||||
|
<string name="pref_codec_speex8_key">pref_codec_speex8_key</string>
|
||||||
|
<string name="pref_codec_speex16_key">pref_codec_speex16_key</string>
|
||||||
|
<string name="pref_codec_speex32_key">pref_codec_speex32_key</string>
|
||||||
|
<string name="pref_codecs_key">pref_codecs_key</string>
|
||||||
|
<string name="pref_stun_server_key">pref_stun_server_key</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,17 +1,36 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="pref_echo_canceller_calibration_key">pref_echo_canceller_calibration_key</string>
|
|
||||||
|
<string name="error_while_accepting_pending_call">Error while accepting pending call</string>
|
||||||
|
<string name="incoming_call_dialog_title">%s is calling you</string>
|
||||||
|
<string name="accept">Accept</string>
|
||||||
|
<string name="decline">Decline</string>
|
||||||
|
<string name="unknown_incoming_call_name">Unknown</string>
|
||||||
|
|
||||||
|
<string name="pref_network_title">Network</string>
|
||||||
|
<string name="pref_transport_udp">UDP</string>
|
||||||
|
<string name="pref_transport_tcp">TCP</string>
|
||||||
|
<string name="pref_transport_tls">TLS</string>
|
||||||
|
<string name="pref_transport_use_standard_ports">Use standard ports</string>
|
||||||
|
<string name="at_least_a_protocol">At least one item is required</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="first_launch_ok">Registration successful</string>
|
||||||
|
<string name="error">Error</string>
|
||||||
|
<string name="click_to_show_first_login_view">Start</string>
|
||||||
|
<string name="dialer_null_on_new_intent">Application not ready</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="no_phone_numbers">No phone numbers found for %s</string>
|
||||||
|
<string name="filter_contacts">Filter contacts</string>
|
||||||
|
<string name="title_numbers_dialog">%s\'s phone numbers</string>
|
||||||
<string name="pref_echo_canceller_calibration">Echo calibration</string>
|
<string name="pref_echo_canceller_calibration">Echo calibration</string>
|
||||||
<string name="pref_video_use_front_camera_title">Use front camera</string>
|
<string name="pref_video_use_front_camera_title">Use front camera</string>
|
||||||
<string name="pref_video_use_front_camera_key">pref_video_use_front_camera_key</string>
|
|
||||||
<string name="pref_video">Video</string>
|
<string name="pref_video">Video</string>
|
||||||
<string name="pref_preferences">Preferences</string>
|
<string name="pref_preferences">Preferences</string>
|
||||||
<string name="pref_video_codec_h263_title">H263</string>
|
<string name="pref_video_codec_h263_title">H263</string>
|
||||||
<string name="pref_video_codec_h263_key">pref_video_codec_h263_key</string>
|
|
||||||
<string name="pref_video_codec_mpeg4_title">MPEG4</string>
|
<string name="pref_video_codec_mpeg4_title">MPEG4</string>
|
||||||
<string name="pref_video_codec_mpeg4_key">pref_video_codec_mpeg4_key</string>
|
|
||||||
<string name="pref_video_codec_h264_title">H264</string>
|
<string name="pref_video_codec_h264_title">H264</string>
|
||||||
<string name="pref_video_codec_h264_key">pref_video_codec_h264_key</string>
|
|
||||||
<string name="pref_video_codecs_title">Codecs</string>
|
<string name="pref_video_codecs_title">Codecs</string>
|
||||||
<string name="pref_video_codecs_key">pref_video_codecs_key</string>
|
<string name="pref_video_codecs_key">pref_video_codecs_key</string>
|
||||||
<string name="menu_videocall_back_to_dialer_title">Display dialer</string>
|
<string name="menu_videocall_back_to_dialer_title">Display dialer</string>
|
||||||
|
@ -24,43 +43,23 @@
|
||||||
<string name="menu_videocall_toggle_camera_enable">Enable camera</string>
|
<string name="menu_videocall_toggle_camera_enable">Enable camera</string>
|
||||||
<string name="menu_videocall_terminate_call_title">Terminate call</string>
|
<string name="menu_videocall_terminate_call_title">Terminate call</string>
|
||||||
<string name="pref_video_settings_title">Video settings</string>
|
<string name="pref_video_settings_title">Video settings</string>
|
||||||
<string name="pref_video_automatically_share_my_video_key">pref_video_automatically_share_my_video_key</string>
|
|
||||||
<string name="pref_video_automatically_share_my_video_title">Share my camera</string>
|
<string name="pref_video_automatically_share_my_video_title">Share my camera</string>
|
||||||
<string name="pref_video_automatically_share_my_video">Automatically send my camera on incoming calls</string>
|
<string name="pref_video_automatically_share_my_video">Automatically send my camera on incoming calls</string>
|
||||||
<string name="pref_video_initiate_call_with_video_key">pref_video_initiate_call_with_video_key</string>
|
|
||||||
<string name="pref_video_initiate_call_with_video_title">Initiate video calls</string>
|
<string name="pref_video_initiate_call_with_video_title">Initiate video calls</string>
|
||||||
<string name="pref_video_initiate_call_with_video">Always send my camera on outgoing calls</string>
|
<string name="pref_video_initiate_call_with_video">Always send my camera on outgoing calls</string>
|
||||||
<string name="pref_video_enable_key">pref_video_enable_key</string>
|
|
||||||
<string name="pref_video_enable_title">Enable Video</string>
|
<string name="pref_video_enable_title">Enable Video</string>
|
||||||
<string name="pref_escape_plus">Replace + by 00</string>
|
<string name="pref_escape_plus">Replace + by 00</string>
|
||||||
<string name="pref_escape_plus_key">pref_escape_plus_key</string>
|
|
||||||
<string name="pref_ilbc_summary">iLBC might be unavailable depending on ARM processor and Android OS version.</string>
|
<string name="pref_ilbc_summary">iLBC might be unavailable depending on ARM processor and Android OS version.</string>
|
||||||
<string name="pref_echo_cancellation">Echo cancellation</string>
|
<string name="pref_echo_cancellation">Echo cancellation</string>
|
||||||
<string name="pref_echo_cancellation_key">pref_echo_cancellation_key</string>
|
|
||||||
<string name="pref_handle_outcall_summarry">Configure how cellular calls are redirected to voip when possible</string>
|
|
||||||
<string name="pref_handle_outcall">Redirect cellular calls</string>
|
|
||||||
<string name="pref_handle_outcall_key">pref_handle_outcall_key_v2</string>
|
|
||||||
<string name="pref_autostart">Start at boot time</string>
|
<string name="pref_autostart">Start at boot time</string>
|
||||||
<string name="pref_autostart_key">pref_autostart_key</string>
|
|
||||||
<string name="outcall_chooser_cellular">Cellular</string>
|
|
||||||
<string name="outcall_chooser_text">Choose application to call %s</string>
|
|
||||||
<string name="pref_enable_outbound_proxy">Outbound proxy</string>
|
<string name="pref_enable_outbound_proxy">Outbound proxy</string>
|
||||||
<string name="pref_enable_outbound_proxy_key">Outbound proxy</string>
|
|
||||||
<string name="pref_codec_pcma">pcma</string>
|
<string name="pref_codec_pcma">pcma</string>
|
||||||
<string name="pref_codec_pcma_key">pref_codec_pcma_key</string>
|
|
||||||
<string name="pref_codec_pcmu">pcmu</string>
|
<string name="pref_codec_pcmu">pcmu</string>
|
||||||
<string name="pref_codec_pcmu_key">pref_codec_pcmu_key</string>
|
|
||||||
<string name="pref_codec_gsm">gsm</string>
|
<string name="pref_codec_gsm">gsm</string>
|
||||||
<string name="pref_codec_gsm_key">pref_codec_gsm_key</string>
|
|
||||||
<string name="pref_codec_ilbc">ilbc</string>
|
<string name="pref_codec_ilbc">ilbc</string>
|
||||||
<string name="pref_codec_ilbc_key">pref_codec_ilbc_key</string>
|
|
||||||
<string name="pref_codec_speex8">speex 8 Khz</string>
|
<string name="pref_codec_speex8">speex 8 Khz</string>
|
||||||
<string name="pref_codec_speex8_key">pref_codec_speex8_key</string>
|
|
||||||
<string name="pref_codec_speex16">speex 16 Khz</string>
|
<string name="pref_codec_speex16">speex 16 Khz</string>
|
||||||
<string name="pref_codec_speex16_key">pref_codec_speex16_key</string>
|
|
||||||
<string name="pref_codec_speex32_key">pref_codec_speex32_key</string>
|
|
||||||
<string name="pref_codecs">Codecs</string>
|
<string name="pref_codecs">Codecs</string>
|
||||||
<string name="pref_codecs_key">pref_codecs_key</string>
|
|
||||||
<string name="place_call_chooser">Place a call</string>
|
<string name="place_call_chooser">Place a call</string>
|
||||||
<string name="pref_debug">Debug</string>
|
<string name="pref_debug">Debug</string>
|
||||||
<string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2\n http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string>
|
<string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2\n http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string>
|
||||||
|
@ -75,7 +74,6 @@
|
||||||
<string name="pref_passwd">Password*</string>
|
<string name="pref_passwd">Password*</string>
|
||||||
<string name="pref_username">Username*</string>
|
<string name="pref_username">Username*</string>
|
||||||
<string name="hello">Hello World, Linphone!</string>
|
<string name="hello">Hello World, Linphone!</string>
|
||||||
<string name="app_name">Linphone</string>
|
|
||||||
<string name="pref_sipaccount">SIP Account</string>
|
<string name="pref_sipaccount">SIP Account</string>
|
||||||
<string name="wrong_username">wrong user name</string>
|
<string name="wrong_username">wrong user name</string>
|
||||||
<string name="wrong_passwd">wrong password</string>
|
<string name="wrong_passwd">wrong password</string>
|
||||||
|
@ -99,20 +97,18 @@
|
||||||
<string name="menu_clear_history">Clear</string>
|
<string name="menu_clear_history">Clear</string>
|
||||||
<string name="error_cannot_get_call_parameters">Cannot get call parameters</string>
|
<string name="error_cannot_get_call_parameters">Cannot get call parameters</string>
|
||||||
<string name="error_cannot_create_default_parameters">Cannot create default call parameters</string>
|
<string name="error_cannot_create_default_parameters">Cannot create default call parameters</string>
|
||||||
<string name="error_cannot_invite_address">Cannot invite destination address [%s]</string>
|
<string name="error_cannot_invite_address">Cannot invite destination address [%s]</string>
|
||||||
<string name="notification_registered">registered to %s </string>
|
|
||||||
<string name="notification_register_failure">fails to register to %s</string>
|
|
||||||
<string name="notification_started">started</string>
|
<string name="notification_started">started</string>
|
||||||
<string name="pref_echo_cancellation_summary">Removes the echo heard by other end</string>
|
<string name="pref_echo_cancellation_summary">Removes the echo heard by other end</string>
|
||||||
<string name="pref_stun_server">Stun server</string>
|
<string name="pref_stun_server">Stun server</string>
|
||||||
<string name="pref_stun_server_key">pref_stun_server_key</string>
|
|
||||||
<string name="ec_calibrating">Calibrating...</string>
|
<string name="ec_calibrating">Calibrating...</string>
|
||||||
<string name="ec_calibrated">Calibrated [%s ms]</string>
|
<string name="ec_calibrated">Calibrated [%s ms]</string>
|
||||||
<string name="failed">failed</string>
|
<string name="failed">failed</string>
|
||||||
|
<string name="first_login_explanation">Enter your username and password to connect to the service.</string>
|
||||||
<string-array name="pref_handle_outcall_values">
|
<string name="first_login_username">Username</string>
|
||||||
<item>Off</item>
|
<string name="first_login_password">Password</string>
|
||||||
<item>On demand</item>
|
<string name="first_login_connect">Connect</string>
|
||||||
<item>Always</item>
|
<string name="first_launch_no_login_password">Please enter your login and password</string>
|
||||||
</string-array>
|
<string name="first_launch_bad_login_password">Couldn\'t connect; check your login and password and start again</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
|
|
||||||
<EditTextPreference android:title="@string/pref_stun_server"
|
<EditTextPreference android:title="@string/pref_stun_server"
|
||||||
android:key="@string/pref_stun_server_key"></EditTextPreference>
|
android:key="@string/pref_stun_server_key"></EditTextPreference>
|
||||||
<ListPreference android:key="@string/pref_handle_outcall_key" android:title="@string/pref_handle_outcall" android:summary="@string/pref_handle_outcall_summarry" android:entryValues="@array/pref_handle_outcall_keys" android:entries="@array/pref_handle_outcall_values" android:defaultValue="ask_for_outcall_interception"></ListPreference>
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,23 +44,25 @@
|
||||||
<CheckBoxPreference android:key="@string/pref_echo_cancellation_key"
|
<CheckBoxPreference android:key="@string/pref_echo_cancellation_key"
|
||||||
android:title="@string/pref_echo_cancellation" android:summary="@string/pref_echo_cancellation_summary"></CheckBoxPreference>
|
android:title="@string/pref_echo_cancellation" android:summary="@string/pref_echo_cancellation_summary"></CheckBoxPreference>
|
||||||
|
|
||||||
<CheckBoxPreference android:key="@string/pref_echo_canceller_calibration_key" android:title="@string/pref_echo_canceller_calibration" android:defaultValue="false"></CheckBoxPreference><PreferenceScreen android:title="@string/pref_codecs"
|
<CheckBoxPreference android:key="@string/pref_echo_canceller_calibration_key"
|
||||||
|
android:title="@string/pref_echo_canceller_calibration" />
|
||||||
|
|
||||||
|
<PreferenceScreen android:title="@string/pref_codecs"
|
||||||
android:key="@string/pref_codecs_key">
|
android:key="@string/pref_codecs_key">
|
||||||
<CheckBoxPreference android:key="@string/pref_codec_speex16_key"
|
<CheckBoxPreference android:key="@string/pref_codec_speex16_key"
|
||||||
android:title="@string/pref_codec_speex16" android:defaultValue="true"
|
android:title="@string/pref_codec_speex16"/>
|
||||||
android:enabled="false"></CheckBoxPreference>
|
|
||||||
<CheckBoxPreference android:key="@string/pref_codec_speex8_key"
|
<CheckBoxPreference android:key="@string/pref_codec_speex8_key"
|
||||||
android:title="@string/pref_codec_speex8" android:defaultValue="true"></CheckBoxPreference>
|
android:title="@string/pref_codec_speex8"/>
|
||||||
<CheckBoxPreference android:key="@string/pref_codec_ilbc_key"
|
<CheckBoxPreference android:key="@string/pref_codec_ilbc_key"
|
||||||
android:title="@string/pref_codec_ilbc" android:enabled="false"
|
android:title="@string/pref_codec_ilbc"
|
||||||
android:shouldDisableView="true" android:defaultValue="true"
|
android:shouldDisableView="true"
|
||||||
android:summary="@string/pref_ilbc_summary"></CheckBoxPreference>
|
android:summary="@string/pref_ilbc_summary"/>
|
||||||
<CheckBoxPreference android:key="@string/pref_codec_gsm_key"
|
<CheckBoxPreference android:key="@string/pref_codec_gsm_key"
|
||||||
android:title="@string/pref_codec_gsm" android:defaultValue="true"></CheckBoxPreference>
|
android:title="@string/pref_codec_gsm"/>
|
||||||
<CheckBoxPreference android:key="@string/pref_codec_pcmu_key"
|
<CheckBoxPreference android:key="@string/pref_codec_pcmu_key"
|
||||||
android:title="@string/pref_codec_pcmu" android:defaultValue="true"></CheckBoxPreference>
|
android:title="@string/pref_codec_pcmu"/>
|
||||||
<CheckBoxPreference android:key="@string/pref_codec_pcma_key"
|
<CheckBoxPreference android:key="@string/pref_codec_pcma_key"
|
||||||
android:title="@string/pref_codec_pcma" android:defaultValue="true"></CheckBoxPreference>
|
android:title="@string/pref_codec_pcma"/>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
@ -95,9 +96,9 @@
|
||||||
<CheckBoxPreference android:key="@string/pref_video_codec_mpeg4_key"
|
<CheckBoxPreference android:key="@string/pref_video_codec_mpeg4_key"
|
||||||
android:title="@string/pref_video_codec_mpeg4_title"
|
android:title="@string/pref_video_codec_mpeg4_title"
|
||||||
android:defaultValue="true"></CheckBoxPreference>
|
android:defaultValue="true"></CheckBoxPreference>
|
||||||
<!-- <CheckBoxPreference android:key="@string/pref_video_codec_h263_key"
|
<CheckBoxPreference android:key="@string/pref_video_codec_h263_key"
|
||||||
android:title="@string/pref_video_codec_h263_title" android:enabled="false"
|
android:title="@string/pref_video_codec_h263_title"
|
||||||
android:defaultValue="false" android:selectable="false"></CheckBoxPreference>-->
|
android:defaultValue="false" android:layout="@layout/hidden"></CheckBoxPreference>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
@ -113,6 +114,17 @@
|
||||||
|
|
||||||
<CheckBoxPreference android:key="@string/pref_debug_key"
|
<CheckBoxPreference android:key="@string/pref_debug_key"
|
||||||
android:title="@string/pref_debug" android:enabled="true"></CheckBoxPreference>
|
android:title="@string/pref_debug" android:enabled="true"></CheckBoxPreference>
|
||||||
|
|
||||||
|
<PreferenceScreen android:title="@string/pref_network_title">
|
||||||
|
<CheckBoxPreference android:key="@string/pref_transport_udp_key"
|
||||||
|
android:title="@string/pref_transport_udp" android:defaultValue="true"/>
|
||||||
|
<CheckBoxPreference android:key="@string/pref_transport_tcp_key"
|
||||||
|
android:title="@string/pref_transport_tcp" />
|
||||||
|
<CheckBoxPreference android:key="@string/pref_transport_tls_key"
|
||||||
|
android:title="@string/pref_transport_tls" android:layout="@layout/hidden"/>
|
||||||
|
<CheckBoxPreference android:key="@string/pref_transport_use_standard_ports_key"
|
||||||
|
android:title="@string/pref_transport_use_standard_ports"/>
|
||||||
|
</PreferenceScreen>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class AboutActivity extends Activity {
|
||||||
try {
|
try {
|
||||||
aboutText.setText(String.format(getString(R.string.about_text), getPackageManager().getPackageInfo(getPackageName(), 0).versionName));
|
aboutText.setText(String.format(getString(R.string.about_text), getPackageManager().getPackageInfo(getPackageName(), 0).versionName));
|
||||||
} catch (NameNotFoundException e) {
|
} catch (NameNotFoundException e) {
|
||||||
Log.e(LinphoneService.TAG, "cannot get version name", e);
|
Log.e(LinphoneManager.TAG, "cannot get version name", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone;
|
package org.linphone;
|
||||||
|
|
||||||
import org.linphone.core.AndroidCameraRecordManager;
|
|
||||||
import org.linphone.core.LinphoneCallParams;
|
import org.linphone.core.LinphoneCallParams;
|
||||||
import org.linphone.core.LinphoneCore;
|
import org.linphone.core.LinphoneCore;
|
||||||
import org.linphone.core.VideoSize;
|
import org.linphone.core.VideoSize;
|
||||||
|
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||||
|
|
||||||
public class BandwidthManager {
|
public class BandwidthManager {
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ public class BandwidthManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onProfileChanged(int newProfile) {
|
private void onProfileChanged(int newProfile) {
|
||||||
LinphoneCore lc = LinphoneService.instance().getLinphoneCore();
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
lc.setUploadBandwidth(bandwidthes[newProfile][0]);
|
lc.setUploadBandwidth(bandwidthes[newProfile][0]);
|
||||||
lc.setDownloadBandwidth(bandwidthes[newProfile][1]);
|
lc.setDownloadBandwidth(bandwidthes[newProfile][1]);
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone;
|
package org.linphone;
|
||||||
|
|
||||||
import org.linphone.core.AndroidCameraRecordManager;
|
|
||||||
import org.linphone.core.LinphoneAddress;
|
import org.linphone.core.LinphoneAddress;
|
||||||
import org.linphone.core.LinphoneCall;
|
import org.linphone.core.LinphoneCall;
|
||||||
import org.linphone.core.LinphoneCallParams;
|
import org.linphone.core.LinphoneCallParams;
|
||||||
import org.linphone.core.LinphoneCore;
|
import org.linphone.core.LinphoneCore;
|
||||||
import org.linphone.core.LinphoneCoreException;
|
import org.linphone.core.LinphoneCoreException;
|
||||||
|
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle call updating, reinvites.
|
* Handle call updating, reinvites.
|
||||||
|
@ -31,7 +31,7 @@ import org.linphone.core.LinphoneCoreException;
|
||||||
* @author Guillaume Beraudo
|
* @author Guillaume Beraudo
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CallManager {
|
class CallManager {
|
||||||
|
|
||||||
private static CallManager instance;
|
private static CallManager instance;
|
||||||
|
|
||||||
|
@ -41,9 +41,6 @@ public class CallManager {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinphoneCore lc() {
|
|
||||||
return LinphoneService.instance().getLinphoneCore();
|
|
||||||
}
|
|
||||||
private AndroidCameraRecordManager videoManager() {
|
private AndroidCameraRecordManager videoManager() {
|
||||||
return AndroidCameraRecordManager.getInstance();
|
return AndroidCameraRecordManager.getInstance();
|
||||||
}
|
}
|
||||||
|
@ -54,8 +51,8 @@ public class CallManager {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void inviteAddress(LinphoneAddress lAddress, boolean videoEnabled) throws LinphoneCoreException {
|
void inviteAddress(LinphoneAddress lAddress, boolean videoEnabled) throws LinphoneCoreException {
|
||||||
LinphoneCore lc = lc();
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
|
|
||||||
LinphoneCallParams params = lc.createDefaultCallParameters();
|
LinphoneCallParams params = lc.createDefaultCallParameters();
|
||||||
bm().updateWithProfileSettings(lc, params);
|
bm().updateWithProfileSettings(lc, params);
|
||||||
|
@ -79,8 +76,8 @@ public class CallManager {
|
||||||
* or if the bandwidth settings are too low.
|
* or if the bandwidth settings are too low.
|
||||||
* @return if updateCall called
|
* @return if updateCall called
|
||||||
*/
|
*/
|
||||||
public boolean reinviteWithVideo() {
|
boolean reinviteWithVideo() {
|
||||||
LinphoneCore lc = lc();
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
LinphoneCall lCall = lc.getCurrentCall();
|
LinphoneCall lCall = lc.getCurrentCall();
|
||||||
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
||||||
|
|
||||||
|
@ -105,8 +102,8 @@ public class CallManager {
|
||||||
/**
|
/**
|
||||||
* Re-invite with parameters updated from profile.
|
* Re-invite with parameters updated from profile.
|
||||||
*/
|
*/
|
||||||
public void reinvite() {
|
void reinvite() {
|
||||||
LinphoneCore lc = lc();
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
LinphoneCall lCall = lc.getCurrentCall();
|
LinphoneCall lCall = lc.getCurrentCall();
|
||||||
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
||||||
bm().updateWithProfileSettings(lc, params);
|
bm().updateWithProfileSettings(lc, params);
|
||||||
|
@ -115,14 +112,14 @@ public class CallManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update current call, without reinvite.
|
* Update current call, without reinvite.
|
||||||
|
* The camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
||||||
*/
|
*/
|
||||||
public void updateCall() {
|
void updateCall() {
|
||||||
LinphoneCore lc = lc();
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
LinphoneCall lCall = lc.getCurrentCall();
|
LinphoneCall lCall = lc.getCurrentCall();
|
||||||
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
LinphoneCallParams params = lCall.getCurrentParamsCopy();
|
||||||
bm().updateWithProfileSettings(lc, params);
|
bm().updateWithProfileSettings(lc, params);
|
||||||
lc.updateCall(lCall, null);
|
lc.updateCall(lCall, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
271
src/org/linphone/ContactPickerActivityNew.java
Normal file
271
src/org/linphone/ContactPickerActivityNew.java
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
/*
|
||||||
|
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 java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.FilterQueryProvider;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.SimpleCursorAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activity for retrieving a phone number / SIP address to call.
|
||||||
|
* <br />
|
||||||
|
*
|
||||||
|
* The cinematic is:
|
||||||
|
* <ul>
|
||||||
|
* <li>Select contact (either through native or custom way)</li>
|
||||||
|
* <li>Select phone number or SIP address
|
||||||
|
* <li>Back to dialer</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ContactPickerActivityNew extends Activity implements FilterQueryProvider {
|
||||||
|
|
||||||
|
private ListView mContactList;
|
||||||
|
private EditText mcontactFilter;
|
||||||
|
|
||||||
|
private SimpleCursorAdapter adapter;
|
||||||
|
private boolean useNativePicker;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
useNativePicker = getResources().getBoolean(R.bool.use_android_contact_picker);
|
||||||
|
|
||||||
|
if (!useNativePicker) {
|
||||||
|
setContentView(R.layout.contact_picker);
|
||||||
|
createPicker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void createPicker() {
|
||||||
|
mContactList = (ListView) findViewById(R.id.contactList);
|
||||||
|
|
||||||
|
mcontactFilter = (EditText) findViewById(R.id.contactFilter);
|
||||||
|
mcontactFilter.addTextChangedListener(new TextWatcher() {
|
||||||
|
public void onTextChanged(CharSequence s, int start, int b, int c) {}
|
||||||
|
public void beforeTextChanged(CharSequence s, int st, int c, int a) {}
|
||||||
|
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
adapter.runQueryOnBackgroundThread(s);
|
||||||
|
adapter.getFilter().filter(s.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Populate the contact list
|
||||||
|
String[] from = new String[] {ContactsContract.Data.DISPLAY_NAME};
|
||||||
|
int[] to = new int[] {android.R.id.text1};
|
||||||
|
int layout = android.R.layout.simple_list_item_1;
|
||||||
|
adapter = new SimpleCursorAdapter(this, layout, runQuery(null), from, to);
|
||||||
|
adapter.setFilterQueryProvider(this);
|
||||||
|
mContactList.setAdapter(adapter);
|
||||||
|
|
||||||
|
mContactList.setOnItemClickListener(new OnItemClickListener() {
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
final CharSequence contactName = ((TextView) view.findViewById(android.R.id.text1)).getText();
|
||||||
|
choosePhoneNumberAndDial(contactName, String.valueOf(id));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void choosePhoneNumberAndDial(final CharSequence contactName, final String id) {
|
||||||
|
List<String> phones = extractPhones(id);
|
||||||
|
phones.addAll(extractSipNumbers(id));
|
||||||
|
|
||||||
|
switch (phones.size()) {
|
||||||
|
case 0:
|
||||||
|
String msg = String.format(getString(R.string.no_phone_numbers), contactName);
|
||||||
|
Toast.makeText(ContactPickerActivityNew.this, msg, Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
returnSelectedValues(phones.get(0), contactName.toString());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(ContactPickerActivityNew.this);
|
||||||
|
|
||||||
|
final ArrayAdapter<String> pAdapter = new ArrayAdapter<String>(ContactPickerActivityNew.this,
|
||||||
|
android.R.layout.simple_dropdown_item_1line, phones);
|
||||||
|
|
||||||
|
builder.setTitle(String.format(getString(R.string.title_numbers_dialog),contactName));
|
||||||
|
builder.setAdapter(pAdapter, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
returnSelectedValues(pAdapter.getItem(which), contactName.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setCancelable(true);
|
||||||
|
builder.setNeutralButton("cancel", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AlertDialog dialog = builder.create();
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void returnSelectedValues(String number, String name) {
|
||||||
|
/* if (getCallingActivity() != null) {
|
||||||
|
setResult(RESULT_OK, new Intent()
|
||||||
|
.putExtra(Intent.EXTRA_PHONE_NUMBER, number)
|
||||||
|
.putExtra(EXTRA_CONTACT_NAME, name));
|
||||||
|
finish();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
LinphoneActivity.setAddressAndGoToDialer(number, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<String> extractPhones(String id) {
|
||||||
|
List<String> list = new ArrayList<String>();
|
||||||
|
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
|
||||||
|
String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
|
||||||
|
String[] selArgs = new String[] {id};
|
||||||
|
Cursor c = this.getContentResolver().query(uri, null, selection, selArgs, null);
|
||||||
|
|
||||||
|
int nbId = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
|
||||||
|
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
list.add(c.getString(nbId));
|
||||||
|
}
|
||||||
|
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> extractSipNumbers(String id) {
|
||||||
|
List<String> list = new ArrayList<String>();
|
||||||
|
Uri uri = ContactsContract.Data.CONTENT_URI;
|
||||||
|
String selection = new StringBuilder()
|
||||||
|
.append(ContactsContract.Data.CONTACT_ID).append(" = ? AND ")
|
||||||
|
.append(ContactsContract.Data.MIMETYPE).append(" = ? ")
|
||||||
|
.append(" AND lower(")
|
||||||
|
.append(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL)
|
||||||
|
.append(") = 'sip'").toString();
|
||||||
|
String[] selArgs = new String[] {id, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE};
|
||||||
|
Cursor c = this.getContentResolver().query(uri, null, selection, selArgs, null);
|
||||||
|
|
||||||
|
int nbId = c.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA);
|
||||||
|
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
list.add("sip:" + c.getString(nbId));
|
||||||
|
}
|
||||||
|
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
if (useNativePicker) {
|
||||||
|
Uri uri = ContactsContract.Contacts.CONTENT_URI;
|
||||||
|
//ContactsContract.CommonDataKinds.Phone.CONTENT_URI
|
||||||
|
startActivityForResult(new Intent(Intent.ACTION_PICK, uri), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onActivityResult(int reqCode, int resultCode, Intent intent) {
|
||||||
|
// If using native picker
|
||||||
|
if (reqCode == 0) {
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
String id = intent.getData().getLastPathSegment();
|
||||||
|
String contactName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||||
|
if (contactName == null)
|
||||||
|
contactName = retrieveContactName(id);
|
||||||
|
choosePhoneNumberAndDial(contactName, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LinphoneActivity.instance().getTabHost().setCurrentTabByTag(LinphoneActivity.DIALER_TAB);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String retrieveContactName(String id) {
|
||||||
|
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
|
||||||
|
String selection = ContactsContract.CommonDataKinds.Phone._ID + " = ?";
|
||||||
|
String[] selArgs = new String[] {id};
|
||||||
|
Cursor c = this.getContentResolver().query(uri, null, selection, selArgs, null);
|
||||||
|
|
||||||
|
String name = "";
|
||||||
|
if (c.moveToFirst()) {
|
||||||
|
name = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
|
||||||
|
}
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Cursor runQuery(CharSequence constraint) {
|
||||||
|
// Run query
|
||||||
|
Uri uri = ContactsContract.Contacts.CONTENT_URI;
|
||||||
|
String[] projection = new String[] {
|
||||||
|
ContactsContract.Contacts._ID,
|
||||||
|
ContactsContract.Contacts.DISPLAY_NAME
|
||||||
|
};
|
||||||
|
String selection =
|
||||||
|
ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1' and "
|
||||||
|
+ ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
|
||||||
|
String[] selectionArgs = null;
|
||||||
|
if (!TextUtils.isEmpty(constraint)) {
|
||||||
|
// FIXME absolutely unsecure
|
||||||
|
selection += " and " + ContactsContract.Contacts.DISPLAY_NAME + " ilike '%"+mcontactFilter.getText()+"%'";
|
||||||
|
}
|
||||||
|
|
||||||
|
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
|
||||||
|
|
||||||
|
return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -25,8 +25,8 @@ import android.os.Bundle;
|
||||||
import android.provider.Contacts;
|
import android.provider.Contacts;
|
||||||
import android.provider.Contacts.People;
|
import android.provider.Contacts.People;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class ContactPickerActivity extends Activity {
|
public class ContactPickerActivityOld extends Activity {
|
||||||
static final int PICK_CONTACT_REQUEST = 0;
|
static final int PICK_CONTACT_REQUEST = 0;
|
||||||
static final int PICK_PHONE_NUMBER_REQUEST = 1;
|
static final int PICK_PHONE_NUMBER_REQUEST = 1;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class ContactPickerActivity extends Activity {
|
||||||
// Get the field values
|
// Get the field values
|
||||||
lName = lCur.getString(lCur.getColumnIndex(People.NAME));
|
lName = lCur.getString(lCur.getColumnIndex(People.NAME));
|
||||||
lPhoneNo = lCur.getString(lCur.getColumnIndex(People.NUMBER));
|
lPhoneNo = lCur.getString(lCur.getColumnIndex(People.NUMBER));
|
||||||
DialerActivity.getDialer().setContactAddress(lPhoneNo, lName);
|
DialerActivity.instance().setContactAddress(lPhoneNo, lName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
126
src/org/linphone/FirstLoginActivity.java
Normal file
126
src/org/linphone/FirstLoginActivity.java
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
IncallActivity.java
|
||||||
|
Copyright (C) 2011 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.LinphoneCore.RegistrationState;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
public class FirstLoginActivity extends Activity implements OnClickListener {
|
||||||
|
|
||||||
|
private TextView login;
|
||||||
|
private TextView password;
|
||||||
|
private SharedPreferences mPref;
|
||||||
|
private ProgressBar bar;
|
||||||
|
static FirstLoginActivity instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.first_login_view);
|
||||||
|
mPref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
setDefaultDomain(getString(R.string.default_domain));
|
||||||
|
|
||||||
|
login = (TextView) findViewById(R.id.login);
|
||||||
|
login.setText(mPref.getString(getString(R.string.pref_username_key), ""));
|
||||||
|
|
||||||
|
password = (TextView) findViewById(R.id.password);
|
||||||
|
password.setText(mPref.getString(getString(R.string.pref_passwd_key), ""));
|
||||||
|
|
||||||
|
bar = (ProgressBar) findViewById(R.id.progress_bar);
|
||||||
|
bar.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
|
|
||||||
|
findViewById(R.id.connect).setOnClickListener(this);
|
||||||
|
instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDefaultDomain(String string) {
|
||||||
|
String domain = mPref.getString(getString(R.string.pref_domain_key), "");
|
||||||
|
if (domain.length() != 0) return;
|
||||||
|
|
||||||
|
writePreference(R.string.pref_domain_key, getString(R.string.default_domain));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (login.getText() == null || login.length() == 0
|
||||||
|
|| password.getText() == null || password.length() == 0) {
|
||||||
|
toast(R.string.first_launch_no_login_password);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
|
||||||
|
|
||||||
|
writePreference(R.string.pref_username_key, login.getText().toString());
|
||||||
|
writePreference(R.string.pref_passwd_key, password.getText().toString());
|
||||||
|
|
||||||
|
LinphoneManager.getInstance().initializePayloads();
|
||||||
|
|
||||||
|
try {
|
||||||
|
LinphoneManager.getInstance().initFromConf(getApplicationContext());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Log.e(LinphoneManager.TAG, "Error while initializing from config in first login activity", e);
|
||||||
|
toast(R.string.error);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void writePreference(int key, String value) {
|
||||||
|
mPref.edit().putString(getString(key), value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
instance = null;
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRegistrationStateChanged(RegistrationState state) {
|
||||||
|
if (RegistrationState.RegistrationOk == state) {
|
||||||
|
bar.setVisibility(View.INVISIBLE);
|
||||||
|
toast(R.string.first_launch_ok);
|
||||||
|
mPref.edit().putBoolean(getString(R.string.first_launch_suceeded_once_key), true).commit();
|
||||||
|
setResult(RESULT_OK);
|
||||||
|
finish();
|
||||||
|
} else if (RegistrationState.RegistrationFailed == state) {
|
||||||
|
bar.setVisibility(View.INVISIBLE);
|
||||||
|
toast(R.string.first_launch_bad_login_password);
|
||||||
|
} else if (RegistrationState.RegistrationProgress == state) {
|
||||||
|
bar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toast(int key) {
|
||||||
|
Toast.makeText(instance, instance.getString(key), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -59,12 +59,12 @@ public class HistoryActivity extends ListActivity {
|
||||||
TextView lSecondLineView = (TextView) v.findViewById(R.id.history_cell_second_line);
|
TextView lSecondLineView = (TextView) v.findViewById(R.id.history_cell_second_line);
|
||||||
if (lSecondLineView.getVisibility() == View.GONE) {
|
if (lSecondLineView.getVisibility() == View.GONE) {
|
||||||
// no display name
|
// no display name
|
||||||
DialerActivity.getDialer().setContactAddress(lFirstLineView.getText().toString(), null);
|
LinphoneActivity.setAddressAndGoToDialer(lFirstLineView.getText().toString(), null);
|
||||||
} else {
|
} else {
|
||||||
DialerActivity.getDialer().setContactAddress(lSecondLineView.getText().toString()
|
LinphoneActivity.setAddressAndGoToDialer(
|
||||||
,lFirstLineView.getText().toString());
|
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) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_clear_history:
|
case R.id.menu_clear_history:
|
||||||
LinphoneService.instance().getLinphoneCore().clearCallLogs();
|
LinphoneManager.getLc().clearCallLogs();
|
||||||
setListAdapter(new CallHistoryAdapter(this));
|
setListAdapter(new CallHistoryAdapter(this));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]");
|
Log.e(LinphoneManager.TAG, "Unknown menu item ["+item+"]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +101,10 @@ public class HistoryActivity extends ListActivity {
|
||||||
|
|
||||||
class CallHistoryAdapter extends BaseAdapter {
|
class CallHistoryAdapter extends BaseAdapter {
|
||||||
final List<LinphoneCallLog> mLogs;
|
final List<LinphoneCallLog> mLogs;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
CallHistoryAdapter(Context aContext) {
|
CallHistoryAdapter(Context aContext) {
|
||||||
mLogs = LinphoneService.instance().getLinphoneCore().getCallLogs();
|
mLogs = LinphoneManager.getLc().getCallLogs();
|
||||||
}
|
}
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return mLogs.size();
|
return mLogs.size();
|
||||||
|
@ -142,7 +144,7 @@ public class HistoryActivity extends ListActivity {
|
||||||
lDirectionImageIn.setVisibility(View.GONE);
|
lDirectionImageIn.setVisibility(View.GONE);
|
||||||
lDirectionImageOut.setVisibility(View.VISIBLE);
|
lDirectionImageOut.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
LinphoneCore lc = LinphoneService.instance().getLinphoneCore();
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
LinphoneProxyConfig lProxyConfig = lc.getDefaultProxyConfig();
|
LinphoneProxyConfig lProxyConfig = lc.getDefaultProxyConfig();
|
||||||
String lDetailedName=null;
|
String lDetailedName=null;
|
||||||
String lDisplayName = lAddress.getDisplayName();
|
String lDisplayName = lAddress.getDisplayName();
|
||||||
|
|
149
src/org/linphone/IncallActivity.java
Normal file
149
src/org/linphone/IncallActivity.java
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
IncallActivity.java
|
||||||
|
Copyright (C) 2011 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.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import org.linphone.ui.HangCallButton;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
public class IncallActivity extends Activity implements OnClickListener {
|
||||||
|
|
||||||
|
public static final String CONTACT_KEY = "contact";
|
||||||
|
private View numpadClose;
|
||||||
|
private View numpadShow;
|
||||||
|
private View numpad;
|
||||||
|
private View buttonsZone;
|
||||||
|
private HangCallButton hangButton;
|
||||||
|
private Timer timer = new Timer();
|
||||||
|
private TimerTask task;
|
||||||
|
private TextView elapsedTime;
|
||||||
|
private Handler handler = new Handler();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.incall_view);
|
||||||
|
|
||||||
|
numpad = findViewById(R.id.incallDialer);
|
||||||
|
buttonsZone = findViewById(R.id.incallButtonsZone);
|
||||||
|
|
||||||
|
numpadClose = findViewById(R.id.incallNumpadClose);
|
||||||
|
numpadClose.setOnClickListener(this);
|
||||||
|
|
||||||
|
numpadShow = findViewById(R.id.incallNumpadShow);
|
||||||
|
numpadShow.setOnClickListener(this);
|
||||||
|
|
||||||
|
hangButton = (HangCallButton) findViewById(R.id.incallHang);
|
||||||
|
hangButton.setOnClickListener(this);
|
||||||
|
|
||||||
|
TextView contact = (TextView) findViewById(R.id.incallContactName);
|
||||||
|
if (getIntent().getExtras() != null) {
|
||||||
|
contact.setText(getIntent().getExtras().getCharSequence(CONTACT_KEY));
|
||||||
|
} else {
|
||||||
|
contact.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsedTime = (TextView) findViewById(R.id.incallElapsedTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (v == numpadClose) {
|
||||||
|
numpad.setVisibility(View.GONE);
|
||||||
|
numpadClose.setVisibility(View.GONE);
|
||||||
|
buttonsZone.setVisibility(View.VISIBLE);
|
||||||
|
} else if (v == numpadShow) {
|
||||||
|
buttonsZone.setVisibility(View.GONE);
|
||||||
|
numpad.setVisibility(View.VISIBLE);
|
||||||
|
numpadClose.setVisibility(View.VISIBLE);
|
||||||
|
} else if (v == hangButton) {
|
||||||
|
hangButton.onClick(v);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
task = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!LinphoneManager.getLc().isIncall()) return;
|
||||||
|
|
||||||
|
final int duration = LinphoneManager.getLc().getCurrentCall().getDuration();
|
||||||
|
if (duration == 0) return;
|
||||||
|
|
||||||
|
handler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
elapsedTime.setText(String.valueOf(duration));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
timer.scheduleAtFixedRate(task, 0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
if (task != null) {
|
||||||
|
task.cancel();
|
||||||
|
task = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Go to home on Back key
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||||
|
if (event.getAction() == KeyEvent.ACTION_DOWN
|
||||||
|
&& event.getRepeatCount() == 0) {
|
||||||
|
// Tell the framework to start tracking this event.
|
||||||
|
numpad.getKeyDispatcherState().startTracking(event, this);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
numpad.getKeyDispatcherState().handleUpEvent(event);
|
||||||
|
if (event.isTracking() && !event.isCanceled()) {
|
||||||
|
startActivity(new Intent()
|
||||||
|
.setAction(Intent.ACTION_MAIN)
|
||||||
|
.addCategory(Intent.CATEGORY_HOME));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.dispatchKeyEvent(event);
|
||||||
|
} else {
|
||||||
|
return super.dispatchKeyEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
ContactPickerActivity.java
|
KeepAliveReceiver.java
|
||||||
Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
|
@ -25,19 +25,19 @@ import android.util.Log;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class KeepAliveManager extends BroadcastReceiver {
|
public class KeepAliveReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
|
||||||
if (!LinphoneService.isready()) {
|
if (!LinphoneService.isReady()) {
|
||||||
Log.i(LinphoneService.TAG, "Linphone service not ready");
|
Log.i(LinphoneManager.TAG, "Keep alive broadcast received while Linphone service not ready");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_ON)) {
|
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)) {
|
} else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_OFF)) {
|
||||||
LinphoneService.getLc().enableKeepAlive(false);
|
LinphoneManager.getLc().enableKeepAlive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
LinphoneActivity.java
|
iLinphoneActivity.java
|
||||||
Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
|
@ -19,20 +19,35 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
package org.linphone;
|
package org.linphone;
|
||||||
|
|
||||||
|
|
||||||
|
import static android.content.Intent.ACTION_MAIN;
|
||||||
|
import static android.media.AudioManager.MODE_NORMAL;
|
||||||
|
import static android.media.AudioManager.ROUTE_ALL;
|
||||||
|
import static android.media.AudioManager.ROUTE_SPEAKER;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager.EcCalibrationListener;
|
||||||
|
import org.linphone.core.LinphoneCore;
|
||||||
|
import org.linphone.core.LinphoneCoreException;
|
||||||
|
import org.linphone.core.Version;
|
||||||
|
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||||
|
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.TabActivity;
|
import android.app.TabActivity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.hardware.Sensor;
|
import android.hardware.Sensor;
|
||||||
import android.hardware.SensorEvent;
|
import android.hardware.SensorEvent;
|
||||||
import android.hardware.SensorEventListener;
|
import android.hardware.SensorEventListener;
|
||||||
import android.hardware.SensorManager;
|
import android.hardware.SensorManager;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.text.Html;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
@ -40,134 +55,209 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TabHost;
|
import android.widget.TabWidget;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import android.widget.TabHost.TabSpec;
|
||||||
|
|
||||||
public class LinphoneActivity extends TabActivity {
|
public class LinphoneActivity extends TabActivity {
|
||||||
public static String DIALER_TAB = "dialer";
|
public static final String DIALER_TAB = "dialer";
|
||||||
|
public static final String PREF_FIRST_LAUNCH = "pref_first_launch";
|
||||||
|
static final int VIDEO_VIEW_ACTIVITY = 100;
|
||||||
|
static final int FIRST_LOGIN_ACTIVITY = 101;
|
||||||
|
static final int INCALL_ACTIVITY = 102;
|
||||||
|
static final int INCOMING_CALL_ACTIVITY = 103;
|
||||||
|
private static final String PREF_CHECK_CONFIG = "pref_check_config";
|
||||||
|
|
||||||
|
private static LinphoneActivity instance;
|
||||||
private AudioManager mAudioManager;
|
private AudioManager mAudioManager;
|
||||||
private static LinphoneActivity theLinphoneActivity;
|
|
||||||
|
|
||||||
|
|
||||||
private FrameLayout mMainFrame;
|
private FrameLayout mMainFrame;
|
||||||
private SensorManager mSensorManager;
|
private SensorManager mSensorManager;
|
||||||
static private SensorEventListener mSensorEventListener;
|
private static SensorEventListener mSensorEventListener;
|
||||||
|
private static String TAG = LinphoneManager.TAG;
|
||||||
|
|
||||||
private static String SCREEN_IS_HIDDEN ="screen_is_hidden";
|
private static final String SCREEN_IS_HIDDEN = "screen_is_hidden";
|
||||||
|
|
||||||
protected static LinphoneActivity instance()
|
|
||||||
{
|
// Customization
|
||||||
if (theLinphoneActivity == null) {
|
private static boolean useFirstLoginActivity;
|
||||||
throw new RuntimeException("LinphoneActivity not instanciated yet");
|
private static boolean useMenuSettings;
|
||||||
} else {
|
private static boolean useMenuAbout;
|
||||||
return theLinphoneActivity;
|
private boolean checkAccount;
|
||||||
}
|
|
||||||
|
|
||||||
|
static final boolean isInstanciated() {
|
||||||
|
return instance != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final LinphoneActivity instance() {
|
||||||
|
if (instance != null) return instance;
|
||||||
|
|
||||||
|
throw new RuntimeException("LinphoneActivity not instantiated yet");
|
||||||
|
}
|
||||||
|
|
||||||
protected void onSaveInstanceState (Bundle outState) {
|
protected void onSaveInstanceState (Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
if (mMainFrame.getVisibility() == View.INVISIBLE) {
|
outState.putBoolean(SCREEN_IS_HIDDEN, mMainFrame.getVisibility() == View.INVISIBLE);
|
||||||
outState.putBoolean(SCREEN_IS_HIDDEN, true);
|
|
||||||
} else {
|
|
||||||
outState.putBoolean(SCREEN_IS_HIDDEN, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
instance = this;
|
||||||
setContentView(R.layout.main);
|
setContentView(R.layout.main);
|
||||||
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
|
||||||
|
|
||||||
theLinphoneActivity = this;
|
useFirstLoginActivity = getResources().getBoolean(R.bool.useFirstLoginActivity);
|
||||||
|
useMenuSettings = getResources().getBoolean(R.bool.useMenuSettings);
|
||||||
|
useMenuAbout = getResources().getBoolean(R.bool.useMenuAbout);
|
||||||
|
checkAccount = !useFirstLoginActivity;
|
||||||
|
|
||||||
// start linphone as background
|
// start linphone as background
|
||||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
|
||||||
intent.setClass(this, LinphoneService.class);
|
|
||||||
startService(intent);
|
|
||||||
|
|
||||||
mMainFrame = (FrameLayout) findViewById(R.id.main_frame);
|
mMainFrame = (FrameLayout) findViewById(R.id.main_frame);
|
||||||
|
|
||||||
mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE));
|
mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE));
|
||||||
|
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
||||||
|
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
|
||||||
TabHost lTabHost = getTabHost(); // The activity TabHost
|
if (!useFirstLoginActivity || pref.getBoolean(getString(R.string.first_launch_suceeded_once_key), false)) {
|
||||||
TabHost.TabSpec spec; // Reusable TabSpec for each tab
|
fillTabHost();
|
||||||
|
} else {
|
||||||
|
startActivityForResult(new Intent().setClass(this, FirstLoginActivity.class), FIRST_LOGIN_ACTIVITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkAccount && !useFirstLoginActivity) {
|
||||||
|
if (pref.getBoolean(PREF_FIRST_LAUNCH, true)) {
|
||||||
|
onFirstLaunch();
|
||||||
|
} else if (!pref.getBoolean(PREF_CHECK_CONFIG, false)
|
||||||
|
&& !checkDefined(pref, R.string.pref_username_key, R.string.pref_passwd_key, R.string.pref_domain_key)) {
|
||||||
|
onBadSettings(pref);
|
||||||
|
} else {
|
||||||
|
checkAccount = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//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);
|
|
||||||
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);
|
|
||||||
lTabHost.addTab(spec);
|
|
||||||
|
|
||||||
lTabHost.setCurrentTabByTag("dialer");
|
|
||||||
if (savedInstanceState !=null && savedInstanceState.getBoolean(SCREEN_IS_HIDDEN,false)) {
|
if (savedInstanceState !=null && savedInstanceState.getBoolean(SCREEN_IS_HIDDEN,false)) {
|
||||||
hideScreen(true);
|
hideScreen(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
|
||||||
|
if (requestCode == FIRST_LOGIN_ACTIVITY) {
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
Toast.makeText(this, getString(R.string.ec_calibration_launch_message), Toast.LENGTH_LONG).show();
|
||||||
|
try {
|
||||||
|
LinphoneManager.getInstance().startEcCalibration(new EcCalibrationListener() {
|
||||||
|
public void onEcCalibrationStatus(EcCalibratorStatus status, int delayMs) {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(LinphoneActivity.this)
|
||||||
|
.edit().putBoolean(
|
||||||
|
getString(R.string.pref_echo_canceller_calibration_key),
|
||||||
|
status == EcCalibratorStatus.Done).commit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (LinphoneCoreException e) {
|
||||||
|
Log.e(TAG, "Unable to calibrate EC", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillTabHost();
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
stopService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private synchronized void fillTabHost() {
|
||||||
|
if (((TabWidget) findViewById(android.R.id.tabs)).getChildCount() != 0) return;
|
||||||
|
|
||||||
|
startActivityInTab("history",
|
||||||
|
new Intent().setClass(this, HistoryActivity.class),
|
||||||
|
R.string.tab_history, R.drawable.history_orange);
|
||||||
|
|
||||||
|
|
||||||
|
startActivityInTab(DIALER_TAB,
|
||||||
|
new Intent().setClass(this, DialerActivity.class).setData(getIntent().getData()),
|
||||||
|
R.string.tab_dialer, R.drawable.dialer_orange);
|
||||||
|
|
||||||
|
|
||||||
|
startActivityInTab("contact",
|
||||||
|
new Intent().setClass(this, Version.sdkAboveOrEqual(5) ?
|
||||||
|
ContactPickerActivityNew.class : ContactPickerActivityOld.class),
|
||||||
|
R.string.tab_contact, R.drawable.contact_orange);
|
||||||
|
|
||||||
|
|
||||||
|
/*if (LinphoneService.isReady()) {
|
||||||
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
|
if (lc.isIncall()) {
|
||||||
|
String caller = LinphoneManager.getInstance().extractADisplayName();
|
||||||
|
startIncallActivity(caller);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
gotToDialer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onNewIntent(Intent intent) {
|
protected void onNewIntent(Intent intent) {
|
||||||
super.onNewIntent(intent);
|
super.onNewIntent(intent);
|
||||||
if (intent.getData() != null) {
|
if (intent.getData() == null) {
|
||||||
DialerActivity.getDialer().newOutgoingCall(intent.getData().toString().substring("tel://".length()));
|
Log.e(TAG, "LinphoneActivity received an intent without data, recreating GUI if needed");
|
||||||
intent.setData(null);
|
if (!LinphoneService.isReady() || !LinphoneManager.getLc().isIncall()) return;
|
||||||
}
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
|
if(lc.isInComingInvitePending()) {
|
||||||
|
gotToDialer();
|
||||||
|
} else {
|
||||||
|
if (getResources().getBoolean(R.bool.use_incall_activity)) {
|
||||||
|
startIncallActivity(LinphoneManager.getInstance().extractADisplayName());
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
Log.e(TAG, "Not handled case: recreation while in call and not using incall activity");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (DialerActivity.instance() != null) {
|
||||||
|
DialerActivity.instance().newOutgoingCall(intent);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, getString(R.string.dialer_null_on_new_intent), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
if (isFinishing()) {
|
if (isFinishing()) {
|
||||||
//restaure audio settings
|
//restore audio settings
|
||||||
if (Integer.parseInt(Build.VERSION.SDK) <=4 /*<donut*/) {
|
if (Version.sdkStrictlyBelow(4) /*<donut*/) {
|
||||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
mAudioManager.setMode(MODE_NORMAL);
|
||||||
mAudioManager.setRouting(AudioManager.MODE_NORMAL,
|
mAudioManager.setRouting(MODE_NORMAL, ROUTE_SPEAKER, ROUTE_ALL);
|
||||||
AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
|
|
||||||
} else {
|
} else {
|
||||||
mAudioManager.setSpeakerphoneOn(false);
|
mAudioManager.setSpeakerphoneOn(false);
|
||||||
}
|
}
|
||||||
stopProxymitySensor();//just in case
|
stopProxymitySensor();//just in case
|
||||||
theLinphoneActivity = null;
|
instance = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStop() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
super.onStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Inflate the currently selected menu XML resource.
|
// Inflate the currently selected menu XML resource.
|
||||||
MenuInflater inflater = getMenuInflater();
|
MenuInflater inflater = getMenuInflater();
|
||||||
inflater.inflate(R.menu.linphone_activity_menu, menu);
|
inflater.inflate(R.menu.linphone_activity_menu, menu);
|
||||||
|
|
||||||
|
menu.findItem(R.id.menu_settings).setVisible(useMenuSettings);
|
||||||
|
menu.findItem(R.id.menu_about).setVisible(useMenuAbout);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,58 +269,29 @@ public class LinphoneActivity extends TabActivity {
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_exit:
|
case R.id.menu_exit:
|
||||||
finish();
|
finish();
|
||||||
Intent exitIntent = new Intent(Intent.ACTION_MAIN);
|
stopService(new Intent(ACTION_MAIN)
|
||||||
exitIntent.setClass(this, LinphoneService.class);
|
.setClass(this, LinphoneService.class));
|
||||||
stopService(exitIntent);
|
|
||||||
break;
|
break;
|
||||||
case R.id.menu_about:
|
case R.id.menu_about:
|
||||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
startActivity(new Intent(ACTION_MAIN)
|
||||||
intent.setClass(this, AboutActivity.class);
|
.setClass(this, AboutActivity.class));
|
||||||
startActivity(intent);
|
|
||||||
default:
|
default:
|
||||||
Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]");
|
Log.e(TAG, "Unknown menu item ["+item+"]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
protected void startprefActivity() {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
void startprefActivity() {
|
||||||
|
Intent intent = new Intent(ACTION_MAIN);
|
||||||
intent.setClass(this, LinphonePreferencesActivity.class);
|
intent.setClass(this, LinphonePreferencesActivity.class);
|
||||||
startActivity(intent);
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
|
||||||
//nop
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void hideScreen(boolean isHidden) {
|
|
||||||
|
void hideScreen(boolean isHidden) {
|
||||||
WindowManager.LayoutParams lAttrs =getWindow().getAttributes();
|
WindowManager.LayoutParams lAttrs =getWindow().getAttributes();
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
lAttrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
lAttrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||||
|
@ -241,16 +302,17 @@ public class LinphoneActivity extends TabActivity {
|
||||||
}
|
}
|
||||||
getWindow().setAttributes(lAttrs);
|
getWindow().setAttributes(lAttrs);
|
||||||
}
|
}
|
||||||
protected synchronized void startProxymitySensor() {
|
|
||||||
|
synchronized void startProxymitySensor() {
|
||||||
if (mSensorEventListener != null) {
|
if (mSensorEventListener != null) {
|
||||||
Log.i(LinphoneService.TAG, "proximity sensor already active");
|
Log.i(TAG, "proximity sensor already active");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<Sensor> lSensorList = mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY);
|
List<Sensor> lSensorList = mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY);
|
||||||
mSensorEventListener = new SensorEventListener() {
|
mSensorEventListener = new SensorEventListener() {
|
||||||
public void onSensorChanged(SensorEvent event) {
|
public void onSensorChanged(SensorEvent event) {
|
||||||
if (event.timestamp == 0) return; //just ignoring for nexus 1
|
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(TAG, "Proximity sensor report ["+event.values[0]+"] , for max range ["+event.sensor.getMaximumRange()+"]");
|
||||||
|
|
||||||
if (event.values[0] != event.sensor.getMaximumRange() ) {
|
if (event.values[0] != event.sensor.getMaximumRange() ) {
|
||||||
instance().hideScreen(true);
|
instance().hideScreen(true);
|
||||||
|
@ -263,9 +325,10 @@ public class LinphoneActivity extends TabActivity {
|
||||||
};
|
};
|
||||||
if (lSensorList.size() >0) {
|
if (lSensorList.size() >0) {
|
||||||
mSensorManager.registerListener(mSensorEventListener,lSensorList.get(0),SensorManager.SENSOR_DELAY_UI);
|
mSensorManager.registerListener(mSensorEventListener,lSensorList.get(0),SensorManager.SENSOR_DELAY_UI);
|
||||||
Log.i(LinphoneService.TAG, "Proximity sensor detected, registering");
|
Log.i(TAG, "Proximity sensor detected, registering");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void stopProxymitySensor() {
|
protected synchronized void stopProxymitySensor() {
|
||||||
if (mSensorManager!=null) {
|
if (mSensorManager!=null) {
|
||||||
mSensorManager.unregisterListener(mSensorEventListener);
|
mSensorManager.unregisterListener(mSensorEventListener);
|
||||||
|
@ -273,5 +336,164 @@ public class LinphoneActivity extends TabActivity {
|
||||||
}
|
}
|
||||||
hideScreen(false);
|
hideScreen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void showPreferenceErrorDialog(String message) {
|
||||||
|
if (!useMenuSettings) {
|
||||||
|
Toast.makeText(this, message, Toast.LENGTH_LONG);
|
||||||
|
} else {
|
||||||
|
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) {
|
||||||
|
startprefActivity();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRegistrationStateChanged(RegistrationState state,
|
||||||
|
String message) {
|
||||||
|
|
||||||
|
if (FirstLoginActivity.instance != null) {
|
||||||
|
FirstLoginActivity.instance.onRegistrationStateChanged(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***** Check Account *******/
|
||||||
|
private boolean checkDefined(SharedPreferences pref, int ... keys) {
|
||||||
|
for (int key : keys) {
|
||||||
|
String conf = pref.getString(getString(key), null);
|
||||||
|
if (conf == null || "".equals(conf))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onFirstLaunch() {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
TextView lDialogTextView = new TextView(this);
|
||||||
|
lDialogTextView.setAutoLinkMask(0x0f/*all*/);
|
||||||
|
lDialogTextView.setPadding(10, 10, 10, 10);
|
||||||
|
|
||||||
|
lDialogTextView.setText(Html.fromHtml(getString(R.string.first_launch_message)));
|
||||||
|
|
||||||
|
builder.setCustomTitle(lDialogTextView)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString(R.string.cont), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
LinphoneManager.getInstance().initializePayloads();
|
||||||
|
startprefActivity();
|
||||||
|
checkAccount = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onBadSettings(final SharedPreferences pref) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
TextView lDialogTextView = new TextView(this);
|
||||||
|
lDialogTextView.setAutoLinkMask(0x0f/*all*/);
|
||||||
|
lDialogTextView.setPadding(10, 10, 10, 10);
|
||||||
|
|
||||||
|
lDialogTextView.setText(Html.fromHtml(getString(R.string.initial_config_error)));
|
||||||
|
|
||||||
|
builder.setCustomTitle(lDialogTextView)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
startprefActivity();
|
||||||
|
checkAccount = false;
|
||||||
|
}
|
||||||
|
}).setNeutralButton(getString(R.string.no), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
checkAccount = false;
|
||||||
|
}
|
||||||
|
}).setNegativeButton(getString(R.string.never_remind), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
pref.edit().putBoolean(PREF_CHECK_CONFIG, true).commit();
|
||||||
|
dialog.cancel();
|
||||||
|
checkAccount = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setAddressAndGoToDialer(String number, String name) {
|
||||||
|
DialerActivity.instance().setContactAddress(number, name);
|
||||||
|
instance.gotToDialer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gotToDialer() {
|
||||||
|
getTabHost().setCurrentTabByTag(DIALER_TAB);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void startActivityInTab(String tag, Intent intent, int indicatorId, int drawableId) {
|
||||||
|
Drawable tabDrawable = getResources().getDrawable(drawableId);
|
||||||
|
TabSpec spec = getTabHost().newTabSpec(tag)
|
||||||
|
.setIndicator(getString(indicatorId), tabDrawable)
|
||||||
|
.setContent(intent);
|
||||||
|
getTabHost().addTab(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startIncallActivity(CharSequence callerName) {
|
||||||
|
startActivityForResult(
|
||||||
|
new Intent().setClass(this, IncallActivity.class)
|
||||||
|
.putExtra(IncallActivity.CONTACT_KEY, callerName),
|
||||||
|
INCALL_ACTIVITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeIncallActivity() {
|
||||||
|
finishActivity(INCALL_ACTIVITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
private String INCALL_ACTIVITY_TAG = "incall";
|
||||||
|
|
||||||
|
void changeTabVisibility(String tag, int value) {
|
||||||
|
View tab = getTabHost().getTabWidget().findViewWithTag(tag);
|
||||||
|
if (tab != null) {
|
||||||
|
tab.setVisibility(value);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Tab not found: " + tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeIncallActivity() {
|
||||||
|
changeTabVisibility(DIALER_TAB, View.VISIBLE);
|
||||||
|
getTabHost().setCurrentTabByTag(DIALER_TAB);
|
||||||
|
getLocalActivityManager().getActivity(INCALL_ACTIVITY_TAG).finish();
|
||||||
|
getTabHost().clearAllTabs();
|
||||||
|
fillTabHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishFromChild(Activity child) {
|
||||||
|
if (child instanceof IncallActivity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.finishFromChild(child);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
public void startVideoActivity() {
|
||||||
|
startActivityForResult(
|
||||||
|
new Intent().setClass(this, VideoCallActivity.class),
|
||||||
|
LinphoneActivity.VIDEO_VIEW_ACTIVITY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,22 +21,17 @@ package org.linphone;
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class LinphoneException extends Exception {
|
public class LinphoneException extends Exception {
|
||||||
|
|
||||||
public LinphoneException() {
|
public LinphoneException() {}
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
|
||||||
|
|
||||||
public LinphoneException(String detailMessage) {
|
public LinphoneException(String detailMessage) {
|
||||||
super(detailMessage);
|
super(detailMessage);
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinphoneException(Throwable throwable) {
|
public LinphoneException(Throwable throwable) {
|
||||||
super(throwable);
|
super(throwable);
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinphoneException(String detailMessage, Throwable throwable) {
|
public LinphoneException(String detailMessage, Throwable throwable) {
|
||||||
super(detailMessage, throwable);
|
super(detailMessage, throwable);
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
839
src/org/linphone/LinphoneManager.java
Normal file
839
src/org/linphone/LinphoneManager.java
Normal file
|
@ -0,0 +1,839 @@
|
||||||
|
/*
|
||||||
|
LinphoneManager.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 static android.media.AudioManager.MODE_IN_CALL;
|
||||||
|
import static android.media.AudioManager.MODE_NORMAL;
|
||||||
|
import static android.media.AudioManager.MODE_RINGTONE;
|
||||||
|
import static android.media.AudioManager.ROUTE_SPEAKER;
|
||||||
|
import static android.media.AudioManager.STREAM_RING;
|
||||||
|
import static android.media.AudioManager.STREAM_VOICE_CALL;
|
||||||
|
import static android.media.AudioManager.VIBRATE_TYPE_RINGER;
|
||||||
|
import static org.linphone.R.string.pref_codec_ilbc_key;
|
||||||
|
import static org.linphone.R.string.pref_codec_speex16_key;
|
||||||
|
import static org.linphone.R.string.pref_codec_speex32_key;
|
||||||
|
import static org.linphone.R.string.pref_echo_cancellation_key;
|
||||||
|
import static org.linphone.core.LinphoneCall.State.CallEnd;
|
||||||
|
import static org.linphone.core.LinphoneCall.State.Error;
|
||||||
|
import static org.linphone.core.LinphoneCall.State.IncomingReceived;
|
||||||
|
|
||||||
|
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.Hacks;
|
||||||
|
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.Version;
|
||||||
|
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 org.linphone.core.LinphoneCore.Transports;
|
||||||
|
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.Editor;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.MediaPlayer;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.os.Vibrator;
|
||||||
|
import android.os.PowerManager.WakeLock;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.provider.Settings.SettingNotFoundException;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.OrientationEventListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Manager of the low level LibLinphone stuff.<br />
|
||||||
|
* Including:<ul>
|
||||||
|
* <li>Starting C liblinphone</li>
|
||||||
|
* <li>Reacting to C liblinphone state changes</li>
|
||||||
|
* <li>Calling Linphone android service listener methods</li>
|
||||||
|
* <li>Interacting from Android GUI/service with low level SIP stuff/</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* 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 PowerManager mPowerManager;
|
||||||
|
private SharedPreferences mPref;
|
||||||
|
private Resources mR;
|
||||||
|
private LinphoneCore mLc;
|
||||||
|
private int mPhoneOrientation;
|
||||||
|
private static Transports initialTransports;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private LinphoneManager(final Context c) {
|
||||||
|
String basePath = c.getFilesDir().getAbsolutePath();
|
||||||
|
linphoneInitialConfigFile = basePath + "/linphonerc";
|
||||||
|
linphoneConfigFile = basePath + "/.linphonerc";
|
||||||
|
ringSoundFile = basePath + "/oldphone_mono.wav";
|
||||||
|
ringbackSoundFile = basePath + "/ringback.wav";
|
||||||
|
|
||||||
|
mAudioManager = ((AudioManager) c.getSystemService(Context.AUDIO_SERVICE));
|
||||||
|
mVibrator = (Vibrator) c.getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
|
mPref = PreferenceManager.getDefaultSharedPreferences(c);
|
||||||
|
mPowerManager = (PowerManager) c.getSystemService(Context.POWER_SERVICE);
|
||||||
|
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();
|
||||||
|
|
||||||
|
detectIfHasCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void detectIfHasCamera() {
|
||||||
|
Log.i(TAG, "Detecting if a camera is present");
|
||||||
|
try {
|
||||||
|
Camera camera = Camera.open();
|
||||||
|
if (hasCamera = camera != null) {
|
||||||
|
camera.release();
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {}
|
||||||
|
Log.i(TAG, (hasCamera ? "A" : "No") + " camera is present");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String TAG="Linphone";
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
private final String linphoneInitialConfigFile;
|
||||||
|
private final String linphoneConfigFile;
|
||||||
|
private final String ringSoundFile;
|
||||||
|
private final String ringbackSoundFile;
|
||||||
|
|
||||||
|
private Timer mTimer = new Timer("Linphone scheduler");
|
||||||
|
|
||||||
|
private BroadcastReceiver mKeepAliveReceiver = new KeepAliveReceiver();
|
||||||
|
private boolean hasCamera;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void routeAudioToSpeaker() {
|
||||||
|
if (Integer.parseInt(Build.VERSION.SDK) <= 4 /*<donut*/) {
|
||||||
|
mAudioManager.setRouting(MODE_NORMAL,
|
||||||
|
AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
|
||||||
|
} else {
|
||||||
|
mAudioManager.setSpeakerphoneOn(true);
|
||||||
|
}
|
||||||
|
if (mLc.isIncall()) {
|
||||||
|
/*disable EC*/
|
||||||
|
mLc.getCurrentCall().enableEchoCancellation(false);
|
||||||
|
mLc.getCurrentCall().enableEchoLimiter(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void routeAudioToReceiver() {
|
||||||
|
if (Integer.parseInt(Build.VERSION.SDK) <=4 /*<donut*/) {
|
||||||
|
mAudioManager.setRouting(MODE_NORMAL,
|
||||||
|
AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
|
||||||
|
} else {
|
||||||
|
mAudioManager.setSpeakerphoneOn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mLc.isIncall()) {
|
||||||
|
//Restore default value
|
||||||
|
mLc.getCurrentCall().enableEchoCancellation(mLc.isEchoCancellationEnabled());
|
||||||
|
mLc.getCurrentCall().enableEchoLimiter(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static final LinphoneManager createAndStart(
|
||||||
|
Context c, LinphoneServiceListener listener) {
|
||||||
|
if (instance != null)
|
||||||
|
throw new RuntimeException("Linphone Manager is already initialized");
|
||||||
|
|
||||||
|
instance = new LinphoneManager(c);
|
||||||
|
instance.serviceListener = listener;
|
||||||
|
instance.startLibLinphone(c);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final LinphoneManager getInstance() {
|
||||||
|
if (instance != null) return instance;
|
||||||
|
|
||||||
|
throw new RuntimeException("Linphone Manager should be created before accessed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final LinphoneCore getLc() {
|
||||||
|
return getInstance().mLc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isSpeakerOn() {
|
||||||
|
return (Integer.parseInt(Build.VERSION.SDK) <=4 && mAudioManager.getRouting(MODE_NORMAL) == ROUTE_SPEAKER)
|
||||||
|
|| Integer.parseInt(Build.VERSION.SDK) >4 &&mAudioManager.isSpeakerphoneOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void newOutgoingCall(AddressType address) {
|
||||||
|
String to = address.getText().toString();
|
||||||
|
|
||||||
|
if (mLc.isIncall()) {
|
||||||
|
serviceListener.tryingNewOutgoingCallButAlreadyInCall();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LinphoneAddress lAddress;
|
||||||
|
try {
|
||||||
|
lAddress = mLc.interpretUrl(to);
|
||||||
|
} catch (LinphoneCoreException e) {
|
||||||
|
serviceListener.tryingNewOutgoingCallButWrongDestinationAddress();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lAddress.setDisplayName(address.getDisplayedName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
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);
|
||||||
|
|
||||||
|
} catch (LinphoneCoreException e) {
|
||||||
|
serviceListener.tryingNewOutgoingCallButCannotGetCallParameters();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void resetCameraFromPreferences() {
|
||||||
|
boolean useFrontCam = mPref.getBoolean(mR.getString(R.string.pref_video_use_front_camera_key), false);
|
||||||
|
AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam);
|
||||||
|
AndroidCameraRecordManager.getInstance().setPhoneOrientation(mPhoneOrientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface AddressType {
|
||||||
|
void setText(CharSequence s);
|
||||||
|
CharSequence getText();
|
||||||
|
void setDisplayedName(String s);
|
||||||
|
String getDisplayedName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static interface NewOutgoingCallUiListener {
|
||||||
|
public void onWrongDestinationAddress();
|
||||||
|
public void onCannotGetCallParameters();
|
||||||
|
public void onAlreadyInCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void sendStaticImage(boolean send) {
|
||||||
|
if (mLc.isIncall()) {
|
||||||
|
mLc.getCurrentCall().enableCamera(!send);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playDtmf(ContentResolver r, char dtmf) {
|
||||||
|
try {
|
||||||
|
if (Settings.System.getInt(r, Settings.System.DTMF_TONE_WHEN_DIALING) == 0) {
|
||||||
|
// audible touch disabled: don't play on speaker, only send in outgoing stream
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (SettingNotFoundException e) {}
|
||||||
|
|
||||||
|
getLc().playDtmf(dtmf, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void changeResolution() {
|
||||||
|
BandwidthManager manager = BandwidthManager.getInstance();
|
||||||
|
manager.setUserRestriction(!manager.isUserRestriction());
|
||||||
|
sendStaticImage(AndroidCameraRecordManager.getInstance().isMuted());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void terminateCall() {
|
||||||
|
if (mLc.isIncall()) {
|
||||||
|
mLc.terminateCall(mLc.getCurrentCall());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Camera will be restarted when mediastreamer chain is recreated and setParameters is called.
|
||||||
|
*/
|
||||||
|
public void switchCamera() {
|
||||||
|
AndroidCameraRecordManager rm = AndroidCameraRecordManager.getInstance();
|
||||||
|
rm.stopVideoRecording();
|
||||||
|
rm.toggleUseFrontCamera();
|
||||||
|
CallManager.getInstance().updateCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleCameraMuting() {
|
||||||
|
AndroidCameraRecordManager rm = AndroidCameraRecordManager.getInstance();
|
||||||
|
sendStaticImage(rm.toggleMute());
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void startLibLinphone(final Context context) {
|
||||||
|
try {
|
||||||
|
copyAssetsFromPackage(context);
|
||||||
|
|
||||||
|
mLc = LinphoneCoreFactory.instance().createLinphoneCore(
|
||||||
|
this, linphoneConfigFile, linphoneInitialConfigFile, 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,ringSoundFile);
|
||||||
|
copyIfNotExist(context, R.raw.ringback,ringbackSoundFile);
|
||||||
|
copyFromPackage(context, R.raw.linphonerc, new File(linphoneInitialConfigFile).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);
|
||||||
|
|
||||||
|
if (initialTransports == null)
|
||||||
|
initialTransports = mLc.getSignalingTransportPorts();
|
||||||
|
|
||||||
|
setSignalingTransportsFromConfiguration(initialTransports);
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 boolean getBool(int key, boolean defValue) {
|
||||||
|
return mPref.getBoolean(getString(key), defValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSignalingTransportsFromConfiguration(Transports t) {
|
||||||
|
Transports ports = new Transports(t);
|
||||||
|
boolean useStandardPort = getBool(R.string.pref_transport_use_standard_ports_key, false);
|
||||||
|
|
||||||
|
if (!getBool(R.string.pref_transport_udp_key, false)) {
|
||||||
|
ports.udp = 0;
|
||||||
|
} else if (useStandardPort) {
|
||||||
|
ports.udp = 5060;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!getBool(R.string.pref_transport_tcp_key, false)) {
|
||||||
|
ports.tcp = 0;
|
||||||
|
} else if (useStandardPort) {
|
||||||
|
ports.tcp = 5060;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!getBool(R.string.pref_transport_tls_key, false)) {
|
||||||
|
ports.tls = 0;
|
||||||
|
} else if (useStandardPort) {
|
||||||
|
ports.tls = 5060;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLc.setSignalingTransportPorts(ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 hasCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 tryingNewOutgoingCallButCannotGetCallParameters();
|
||||||
|
void tryingNewOutgoingCallButWrongDestinationAddress();
|
||||||
|
void tryingNewOutgoingCallButAlreadyInCall();
|
||||||
|
void onRegistrationStateChanged(RegistrationState state, String message);
|
||||||
|
void onCallStateChanged(LinphoneCall call, State state, String message);
|
||||||
|
void onRingerPlayerCreated(MediaPlayer mRingerPlayer);
|
||||||
|
void onDisplayStatus(String message);
|
||||||
|
void onAlreadyInVideoCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface EcCalibrationListener {
|
||||||
|
void onEcCalibrationStatus(EcCalibratorStatus status, int delayMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 == IncomingReceived && !call.equals(lc.getCurrentCall())) {
|
||||||
|
if (call.getReplacedCall()==null){
|
||||||
|
//no multicall support, just decline
|
||||||
|
lc.terminateCall(call);
|
||||||
|
}//otherwise it will be accepted automatically.
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == IncomingReceived) {
|
||||||
|
// Brighten screen for at least 10 seconds
|
||||||
|
WakeLock wl = mPowerManager.newWakeLock(
|
||||||
|
PowerManager.ACQUIRE_CAUSES_WAKEUP
|
||||||
|
|PowerManager.ON_AFTER_RELEASE
|
||||||
|
|PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
|
||||||
|
"incoming_call");
|
||||||
|
wl.acquire(10000);
|
||||||
|
|
||||||
|
startRinging();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCurrentCallState == IncomingReceived) {
|
||||||
|
//previous state was ringing, so stop ringing
|
||||||
|
stopRinging();
|
||||||
|
//routeAudioToReceiver();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == CallEnd || state == Error) {
|
||||||
|
mAudioManager.setMode(MODE_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentCallState=state;
|
||||||
|
serviceListener.onCallStateChanged(call, state, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ecCalibrationStatus(final LinphoneCore lc,final EcCalibratorStatus status, final int delayMs,
|
||||||
|
final Object data) {
|
||||||
|
EcCalibrationListener listener = (EcCalibrationListener) data;
|
||||||
|
listener.onEcCalibrationStatus(status, delayMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void startEcCalibration(EcCalibrationListener l) throws LinphoneCoreException {
|
||||||
|
int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL);
|
||||||
|
int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL);
|
||||||
|
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0);
|
||||||
|
|
||||||
|
mLc.startEchoCalibration(l);
|
||||||
|
|
||||||
|
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private synchronized void startRinging() {
|
||||||
|
if (Hacks.isGalaxyS()) {
|
||||||
|
mAudioManager.setMode(MODE_RINGTONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER) && mVibrator !=null) {
|
||||||
|
long[] patern = {0,1000,1000};
|
||||||
|
mVibrator.vibrate(patern, 1);
|
||||||
|
}
|
||||||
|
if (mRingerPlayer == null) {
|
||||||
|
mRingerPlayer = new MediaPlayer();
|
||||||
|
mRingerPlayer.setAudioStreamType(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Hacks.isGalaxyS()) {
|
||||||
|
mAudioManager.setMode(MODE_IN_CALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String extractADisplayName() {
|
||||||
|
final LinphoneAddress remote = mLc.getRemoteAddress();
|
||||||
|
if (remote == null) return mR.getString(R.string.unknown_incoming_call_name);
|
||||||
|
|
||||||
|
final String displayName = remote.getDisplayName();
|
||||||
|
if (displayName!=null) {
|
||||||
|
return displayName;
|
||||||
|
} else if (remote.getUserName() != null){
|
||||||
|
return remote.getUserName();
|
||||||
|
} else {
|
||||||
|
String rms = remote.toString();
|
||||||
|
if (rms != null && rms.length() > 1)
|
||||||
|
return rms;
|
||||||
|
|
||||||
|
return mR.getString(R.string.unknown_incoming_call_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean reinviteWithVideo() {
|
||||||
|
return CallManager.getInstance().reinviteWithVideo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVideoEnabled() {
|
||||||
|
return mPref.getBoolean(getString(R.string.pref_video_enable_key), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAudioModeIncallForGalaxyS() {
|
||||||
|
if (!Hacks.isGalaxyS()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
stopRinging();
|
||||||
|
Thread.sleep(100);
|
||||||
|
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
/* ops */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializePayloads() {
|
||||||
|
Log.i(TAG, "Initializing supported payloads");
|
||||||
|
Editor e = mPref.edit();
|
||||||
|
boolean fastCpu = Version.isArmv7();
|
||||||
|
|
||||||
|
e.putBoolean(getString(pref_echo_cancellation_key), fastCpu);
|
||||||
|
|
||||||
|
e.putBoolean(getString(R.string.pref_codec_gsm_key), true);
|
||||||
|
e.putBoolean(getString(R.string.pref_codec_pcma_key), true);
|
||||||
|
e.putBoolean(getString(R.string.pref_codec_pcmu_key), true);
|
||||||
|
e.putBoolean(getString(R.string.pref_codec_speex8_key), true);
|
||||||
|
e.putBoolean(getString(pref_codec_speex16_key), fastCpu);
|
||||||
|
e.putBoolean(getString(pref_codec_speex32_key), fastCpu);
|
||||||
|
|
||||||
|
boolean ilbc = LinphoneService.isReady() && LinphoneManager.getLc()
|
||||||
|
.findPayloadType("iLBC", 8000)!=null;
|
||||||
|
e.putBoolean(getString(pref_codec_ilbc_key), ilbc);
|
||||||
|
|
||||||
|
e.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addVideo() {
|
||||||
|
if (!LinphoneManager.getLc().isIncall()) return;
|
||||||
|
if (!reinviteWithVideo()) {
|
||||||
|
serviceListener.onAlreadyInVideoCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean acceptCallIfIncomingPending() throws LinphoneCoreException {
|
||||||
|
setAudioModeIncallForGalaxyS();
|
||||||
|
if (mLc.isInComingInvitePending()) {
|
||||||
|
mLc.acceptCall(mLc.getCurrentCall());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String extractIncomingRemoteName() {
|
||||||
|
if (!mR.getBoolean(R.bool.show_full_remote_address_on_incoming_call))
|
||||||
|
return extractADisplayName();
|
||||||
|
|
||||||
|
LinphoneAddress remote = mLc.getRemoteAddress();
|
||||||
|
if (remote != null)
|
||||||
|
return remote.toString();
|
||||||
|
|
||||||
|
return mR.getString(R.string.unknown_incoming_call_name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,113 +15,199 @@ GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.linphone;
|
package org.linphone;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.linphone.R.string.ec_calibrating;
|
||||||
|
import static org.linphone.R.string.ec_calibration_launch_message;
|
||||||
|
import static org.linphone.R.string.pref_codec_ilbc_key;
|
||||||
|
import static org.linphone.R.string.pref_codec_speex16_key;
|
||||||
|
import static org.linphone.R.string.pref_echo_canceller_calibration_key;
|
||||||
|
import static org.linphone.R.string.pref_video_enable_key;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager.EcCalibrationListener;
|
||||||
import org.linphone.core.LinphoneCoreException;
|
import org.linphone.core.LinphoneCoreException;
|
||||||
|
import org.linphone.core.Version;
|
||||||
|
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.content.SharedPreferences;
|
||||||
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.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.preference.CheckBoxPreference;
|
import android.preference.CheckBoxPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.Preference.OnPreferenceClickListener;
|
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
|
import android.preference.Preference.OnPreferenceChangeListener;
|
||||||
|
import android.preference.Preference.OnPreferenceClickListener;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class LinphonePreferencesActivity extends PreferenceActivity {
|
public class LinphonePreferencesActivity extends PreferenceActivity implements EcCalibrationListener {
|
||||||
private static final int version = Integer.parseInt(Build.VERSION.SDK);
|
private Handler mHandler = new Handler();
|
||||||
boolean mIsLowEndCpu = true;
|
private CheckBoxPreference ecPref;
|
||||||
private AudioManager mAudioManager;
|
|
||||||
|
private SharedPreferences prefs() {
|
||||||
|
return getPreferenceManager().getSharedPreferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckBoxPreference findCheckbox(int key) {
|
||||||
|
return (CheckBoxPreference) findPreference(getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
mAudioManager = ((AudioManager)getSystemService(Context.AUDIO_SERVICE));
|
|
||||||
boolean enableIlbc=false;
|
|
||||||
if (LinphoneService.isready()) {
|
|
||||||
// if not ilbc, we are on low end cpu.
|
|
||||||
enableIlbc = LinphoneService.instance().getLinphoneCore().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();
|
|
||||||
}
|
|
||||||
if (mIsLowEndCpu) {
|
|
||||||
getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(R.string.pref_codec_ilbc_key), false).commit();
|
|
||||||
getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(R.string.pref_codec_speex16_key), false).commit();
|
|
||||||
getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(R.string.pref_codec_speex32_key), false).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the preferences from an XML resource
|
// Load the preferences from an XML resource
|
||||||
addPreferencesFromResource(R.xml.preferences);
|
addPreferencesFromResource(R.xml.preferences);
|
||||||
if (!mIsLowEndCpu) {
|
|
||||||
getPreferenceScreen().findPreference(getString(R.string.pref_codec_ilbc_key)).setEnabled(enableIlbc);
|
addTransportChecboxesListener();
|
||||||
getPreferenceScreen().findPreference(getString(R.string.pref_codec_speex16_key)).setEnabled(enableIlbc);
|
|
||||||
//getPreferenceScreen().findPreference(getString(R.string.pref_codec_speex32_key)).setEnabled(enableIlbc);
|
ecPref = (CheckBoxPreference) findPreference(pref_echo_canceller_calibration_key);
|
||||||
}
|
ecPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
getPreferenceScreen().findPreference(getString(R.string.pref_echo_canceller_calibration_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
startEcCalibration(preference);
|
startEcCalibration();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Force disable video
|
boolean fastCpu = Version.isArmv7();
|
||||||
if (version < 5 || !enableIlbc) {
|
if (fastCpu) {
|
||||||
disableCheckbox(R.string.pref_video_enable_key);
|
boolean ilbc = LinphoneService.isReady() && LinphoneManager.getLc().findPayloadType("iLBC", 8000)!=null;
|
||||||
|
findPreference(pref_codec_ilbc_key).setEnabled(ilbc);
|
||||||
|
findPreference(pref_codec_speex16_key).setEnabled(true);
|
||||||
|
//findPreference(pref_codec_speex32_key)).setEnabled(enableIlbc);
|
||||||
}
|
}
|
||||||
if (getPreferenceManager().getSharedPreferences().getBoolean(DialerActivity.PREF_FIRST_LAUNCH,true)) {
|
|
||||||
if (!mIsLowEndCpu ) {
|
// No video
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
if (Version.sdkStrictlyBelow(5) || !fastCpu || !LinphoneManager.getInstance().hasCamera()) {
|
||||||
builder.setTitle(R.string.ec_calibration_launch_message).setCancelable(false).setPositiveButton(getString(R.string.cont), new OnClickListener() {
|
disableCheckbox(pref_video_enable_key);
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
}
|
||||||
startEcCalibration(getPreferenceScreen().findPreference(getString(R.string.pref_echo_canceller_calibration_key)));
|
if (prefs().getBoolean(LinphoneActivity.PREF_FIRST_LAUNCH,true)) {
|
||||||
|
if (fastCpu) {
|
||||||
|
Toast.makeText(this, getString(ec_calibration_launch_message), Toast.LENGTH_LONG).show();
|
||||||
|
startEcCalibration();
|
||||||
|
}
|
||||||
|
|
||||||
|
prefs().edit().putBoolean(LinphoneActivity.PREF_FIRST_LAUNCH, false).commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void addTransportChecboxesListener() {
|
||||||
|
|
||||||
|
final List<CheckBoxPreference> checkboxes = Arrays.asList(
|
||||||
|
findCheckbox(R.string.pref_transport_udp_key)
|
||||||
|
,findCheckbox(R.string.pref_transport_tcp_key)
|
||||||
|
// ,findCheckbox(R.string.pref_transport_tls_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
OnPreferenceChangeListener changedListener = new OnPreferenceChangeListener() {
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
|
if ((Boolean) newValue) {
|
||||||
|
for (CheckBoxPreference p : checkboxes) {
|
||||||
|
if (p == preference) continue;
|
||||||
|
p.setChecked(false);
|
||||||
}
|
}
|
||||||
}).create().show();
|
return true;
|
||||||
|
} else {
|
||||||
|
for (CheckBoxPreference p : checkboxes) {
|
||||||
|
if (p == preference) continue;
|
||||||
|
if (p.isChecked()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
getPreferenceManager().getSharedPreferences().edit().putBoolean(DialerActivity.PREF_FIRST_LAUNCH, false).commit();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
OnPreferenceClickListener clickListener = new OnPreferenceClickListener() {
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
// Forbid no protocol selection
|
||||||
|
|
||||||
|
if (((CheckBoxPreference) preference).isChecked()) {
|
||||||
|
// Trying to unckeck
|
||||||
|
for (CheckBoxPreference p : checkboxes) {
|
||||||
|
if (p == preference) continue;
|
||||||
|
if (p.isChecked()) return false;
|
||||||
|
}
|
||||||
|
/*Toast.makeText(LinphonePreferencesActivity.this,
|
||||||
|
getString(R.string.at_least_a_protocol),
|
||||||
|
Toast.LENGTH_SHORT).show();*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (CheckBoxPreference c : checkboxes) {
|
||||||
|
c.setOnPreferenceChangeListener(changedListener);
|
||||||
|
c.setOnPreferenceClickListener(clickListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void startEcCalibration(Preference preference) {
|
|
||||||
|
private synchronized void startEcCalibration() {
|
||||||
try {
|
try {
|
||||||
while (mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL) != mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL)) {
|
LinphoneManager.getInstance().startEcCalibration(this);
|
||||||
mAudioManager.adjustStreamVolume(AudioManager.STREAM_VOICE_CALL, AudioManager.ADJUST_RAISE, 0);
|
|
||||||
}
|
ecPref.setSummary(ec_calibrating);
|
||||||
LinphoneService.getLc().startEchoCalibration(preference);
|
ecPref.getEditor().putBoolean(getString(pref_echo_canceller_calibration_key), false).commit();
|
||||||
preference.setSummary(R.string.ec_calibrating);
|
|
||||||
preference.getEditor().putBoolean(getString(R.string.pref_echo_canceller_calibration_key), false).commit();
|
|
||||||
} catch (LinphoneCoreException e) {
|
} catch (LinphoneCoreException e) {
|
||||||
Log.w(LinphoneService.TAG, "Cannot calibrate EC",e);
|
Log.w(LinphoneManager.TAG, "Cannot calibrate EC",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onEcCalibrationStatus(final EcCalibratorStatus status, final int delayMs) {
|
||||||
|
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (status == EcCalibratorStatus.Done) {
|
||||||
|
ecPref.setSummary(String.format(getString(R.string.ec_calibrated), delayMs));
|
||||||
|
ecPref.setChecked(true);
|
||||||
|
|
||||||
|
} else if (status == EcCalibratorStatus.Failed) {
|
||||||
|
ecPref.setSummary(R.string.failed);
|
||||||
|
ecPref.setChecked(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void disableCheckbox(int key) {
|
private void disableCheckbox(int key) {
|
||||||
getPreferenceManager().getSharedPreferences().edit().putBoolean(getString(key), false).commit();
|
writeBoolean(key, false);
|
||||||
CheckBoxPreference box = (CheckBoxPreference) getPreferenceScreen().findPreference(getString(key));
|
CheckBoxPreference box = (CheckBoxPreference) findPreference(key);
|
||||||
box.setEnabled(false);
|
box.setEnabled(false);
|
||||||
box.setChecked(false);
|
box.setChecked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Preference findPreference(int key) {
|
||||||
|
return getPreferenceManager().findPreference(getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeBoolean(int key, boolean value) {
|
||||||
|
prefs().edit().putBoolean(getString(key), value).commit();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
if (isFinishing()) {
|
|
||||||
try {
|
if (!isFinishing()) return;
|
||||||
LinphoneActivity.instance().initFromConf();
|
|
||||||
} catch (LinphoneException e) {
|
|
||||||
Log.e(LinphoneService.TAG, "cannot update config",e);
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,447 +18,123 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone;
|
package org.linphone;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
import org.linphone.core.LinphoneAddress;
|
import org.linphone.LinphoneManager.LinphoneServiceListener;
|
||||||
import org.linphone.core.LinphoneAuthInfo;
|
import org.linphone.LinphoneManager.NewOutgoingCallUiListener;
|
||||||
|
import org.linphone.core.Hacks;
|
||||||
import org.linphone.core.LinphoneCall;
|
import org.linphone.core.LinphoneCall;
|
||||||
import org.linphone.core.LinphoneChatRoom;
|
|
||||||
import org.linphone.core.LinphoneCore;
|
|
||||||
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
|
||||||
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.LinphoneCall.State;
|
||||||
import org.linphone.core.LinphoneCore.FirewallPolicy;
|
|
||||||
import org.linphone.core.LinphoneCore.GlobalState;
|
import org.linphone.core.LinphoneCore.GlobalState;
|
||||||
|
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
import android.media.RingtoneManager;
|
import android.media.RingtoneManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.Uri;
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Vibrator;
|
|
||||||
import android.preference.CheckBoxPreference;
|
|
||||||
import android.preference.Preference;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class LinphoneService extends Service implements LinphoneCoreListener {
|
/***
|
||||||
static final public String TAG="Linphone";
|
*
|
||||||
/** Called when the activity is first created. */
|
* Linphone service, reacting to Incoming calls, ...<br />
|
||||||
private static String LINPHONE_FACTORY_RC = "/data/data/org.linphone/files/linphonerc";
|
*
|
||||||
private static String LINPHONE_RC = "/data/data/org.linphone/files/.linphonerc";
|
* Roles include:<ul>
|
||||||
private static String RING_SND = "/data/data/org.linphone/files/oldphone_mono.wav";
|
* <li>Initializing LinphoneManager</li>
|
||||||
private static String RINGBACK_SND = "/data/data/org.linphone/files/ringback.wav";
|
* <li>Starting C libLinphone through LinphoneManager</li>
|
||||||
|
* <li>Reacting to LinphoneManager state changes</li>
|
||||||
|
* <li>Delegating GUI state change actions to GUI listener</li>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @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 static LinphoneService theLinphone;
|
private Handler mHandler = new Handler();
|
||||||
private LinphoneCore mLinphoneCore;
|
private static LinphoneService instance;
|
||||||
private SharedPreferences mPref;
|
|
||||||
Timer mTimer = new Timer("Linphone scheduler");
|
|
||||||
|
|
||||||
NotificationManager mNotificationManager;
|
static boolean isReady() { return (instance!=null); }
|
||||||
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;
|
* @throws RuntimeException service not instantiated
|
||||||
final int IC_LEVEL_GREEN=1;
|
*/
|
||||||
final int IC_LEVEL_RED=2;
|
|
||||||
|
|
||||||
MediaPlayer mRingerPlayer;
|
|
||||||
LinphoneCall.State mCurrentCallState;
|
|
||||||
Vibrator mVibrator;
|
|
||||||
private AudioManager mAudioManager;
|
|
||||||
private BroadcastReceiver mKeepAliveMgrReceiver = new KeepAliveManager();
|
|
||||||
private BroadcastReceiver mOutgoingCallReceiver = null;
|
|
||||||
|
|
||||||
private Handler mHandler = new Handler() ;
|
|
||||||
static boolean isready() {
|
|
||||||
return (theLinphone!=null);
|
|
||||||
}
|
|
||||||
static LinphoneService instance() {
|
static LinphoneService instance() {
|
||||||
if (theLinphone == null) {
|
if (isReady()) return instance;
|
||||||
throw new RuntimeException("LinphoneActivity not instanciated yet");
|
|
||||||
} else {
|
throw new RuntimeException("LinphoneService not instantiated yet");
|
||||||
return theLinphone;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private NotificationManager mNotificationMgr;
|
||||||
|
private final static int NOTIF_ID=1;
|
||||||
|
|
||||||
|
private Notification mNotif;
|
||||||
|
private PendingIntent mNotifContentIntent;
|
||||||
|
private String notificationTitle;
|
||||||
|
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
theLinphone = this;
|
instance = this;
|
||||||
|
|
||||||
|
notificationTitle = getString(R.string.app_name);
|
||||||
|
|
||||||
// Dump some debugging information to the logs
|
// Dump some debugging information to the logs
|
||||||
Hacks.dumpDeviceInformation();
|
Hacks.dumpDeviceInformation();
|
||||||
|
|
||||||
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
mNotificationMgr = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
mNotification = new Notification(R.drawable.status_level
|
mNotif = new Notification(R.drawable.status_level, "", System.currentTimeMillis());
|
||||||
, ""
|
mNotif.iconLevel=IC_LEVEL_ORANGE;
|
||||||
, System.currentTimeMillis());
|
mNotif.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||||
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
|
Intent notifIntent = new Intent(this, LinphoneActivity.class);
|
||||||
, LINPHONE_RC
|
mNotifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, 0);
|
||||||
, LINPHONE_FACTORY_RC
|
mNotif.setLatestEventInfo(this, notificationTitle,"", mNotifContentIntent);
|
||||||
, null);
|
mNotificationMgr.notify(NOTIF_ID, mNotif);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
LinphoneManager.createAndStart(this, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void sendNotification(int level, int textId) {
|
||||||
private void copyAssetsFromPackage() throws IOException {
|
mNotif.iconLevel = level;
|
||||||
copyIfNotExist(R.raw.oldphone_mono,RING_SND);
|
mNotif.when=System.currentTimeMillis();
|
||||||
copyIfNotExist(R.raw.ringback,RINGBACK_SND);
|
String text = getString(textId);
|
||||||
copyFromPackage(R.raw.linphonerc, new File(LINPHONE_FACTORY_RC).getName());
|
if (text.contains("%s")) {
|
||||||
}
|
String id = LinphoneManager.getLc().getDefaultProxyConfig().getIdentity();
|
||||||
private void copyIfNotExist(int ressourceId,String target) throws IOException {
|
text = String.format(text, id);
|
||||||
File lFileToCopy = new File(target);
|
|
||||||
if (!lFileToCopy.exists()) {
|
|
||||||
copyFromPackage(ressourceId,lFileToCopy.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
mNotif.setLatestEventInfo(this, notificationTitle, text, mNotifContentIntent);
|
||||||
private void copyFromPackage(int ressourceId,String target) throws IOException{
|
mNotificationMgr.notify(NOTIF_ID, mNotif);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected LinphoneCore getLinphoneCore() {
|
|
||||||
return mLinphoneCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -467,78 +143,136 @@ public class LinphoneService extends Service implements LinphoneCoreListener {
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
mTimer.cancel();
|
LinphoneManager.destroy(this);
|
||||||
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
|
|
||||||
|
|
||||||
}
|
mNotificationMgr.cancel(NOTIF_ID);
|
||||||
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
|
|
||||||
|
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
private synchronized void stopRinging() {
|
|
||||||
if (mRingerPlayer !=null) {
|
|
||||||
mRingerPlayer.stop();
|
|
||||||
mRingerPlayer.release();
|
public void onDisplayStatus(final String message) {
|
||||||
mRingerPlayer=null;
|
|
||||||
}
|
|
||||||
if (mVibrator!=null) {
|
|
||||||
mVibrator.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void ecCalibrationStatus(final LinphoneCore lc,final EcCalibratorStatus status, final int delay_ms,
|
|
||||||
final Object data) {
|
|
||||||
final CheckBoxPreference pref = (CheckBoxPreference) data;
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (status == EcCalibratorStatus.Done) {
|
if (guiListener() != null) guiListener().onDisplayStatus(message);
|
||||||
pref.setSummary(String.format(getString(R.string.ec_calibrated), delay_ms));
|
|
||||||
pref.setChecked(true);
|
|
||||||
|
|
||||||
} else if (status == EcCalibratorStatus.Failed) {
|
|
||||||
pref.setSummary(R.string.failed);
|
|
||||||
pref.setChecked(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(final RegistrationState state,
|
||||||
|
final String message) {
|
||||||
|
if (state == RegistrationState.RegistrationOk && LinphoneManager.getLc().getDefaultProxyConfig().isRegistered()) {
|
||||||
|
sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == RegistrationState.RegistrationFailed) {
|
||||||
|
sendNotification(IC_LEVEL_OFFLINE, R.string.notification_register_failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == RegistrationState.RegistrationOk || state == RegistrationState.RegistrationFailed) {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (LinphoneActivity.isInstanciated())
|
||||||
|
LinphoneActivity.instance().onRegistrationStateChanged(state, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
} else if (state == LinphoneCall.State.StreamsRunning) {
|
||||||
|
if (LinphoneActivity.isInstanciated()
|
||||||
|
&& getResources().getBoolean(R.bool.use_video_activity)
|
||||||
|
&& LinphoneManager.getLc().getCurrentCall().getCurrentParamsCopy().getVideoEnabled()) {
|
||||||
|
LinphoneActivity.instance().startVideoActivity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (guiListener() != null)
|
||||||
|
guiListener().onCallStateChanged(call, state, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public interface LinphoneGuiListener extends NewOutgoingCallUiListener {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryingNewOutgoingCallButAlreadyInCall() {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (guiListener() != null)
|
||||||
|
guiListener().onAlreadyInCall();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryingNewOutgoingCallButCannotGetCallParameters() {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (guiListener() != null)
|
||||||
|
guiListener().onCannotGetCallParameters();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryingNewOutgoingCallButWrongDestinationAddress() {
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (guiListener() != null)
|
||||||
|
guiListener().onWrongDestinationAddress();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAlreadyInVideoCall() {
|
||||||
|
LinphoneActivity.instance().startVideoActivity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,27 +27,34 @@ import android.util.Log;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Intercept network state changes and update linphone core through LinphoneManager.
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class NetworkManager extends BroadcastReceiver {
|
public class NetworkManager extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
|
||||||
NetworkInfo lNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
|
NetworkInfo lNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
|
||||||
Log.i(LinphoneService.TAG, "Network info ["+lNetworkInfo+"]");
|
Log.i(LinphoneManager.TAG, "Network info ["+lNetworkInfo+"]");
|
||||||
Boolean lNoConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,false);
|
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;
|
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){
|
} else if (lNetworkInfo.getState() == NetworkInfo.State.CONNECTED){
|
||||||
LinphoneService.instance().getLinphoneCore().setNetworkReachable(true);
|
LinphoneManager.getLc().setNetworkReachable(true);
|
||||||
} else {
|
} else {
|
||||||
//unhandled event
|
// Other unhandled events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
OutgoingCallReceiver.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;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
|
|
||||||
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";
|
|
||||||
@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) {
|
|
||||||
//just return
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setResult(Activity.RESULT_OK,null, null);
|
|
||||||
Intent lIntent = new Intent();
|
|
||||||
// 1 check config
|
|
||||||
if (PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.pref_handle_outcall_key),key_on_demand).equals(key_always)) {
|
|
||||||
//start linphone directly
|
|
||||||
lIntent.setClass(context, LinphoneActivity.class);
|
|
||||||
} else {
|
|
||||||
//start activity chooser
|
|
||||||
lIntent.setAction(Intent.ACTION_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
lIntent.setData(Uri.parse("tel://"+to+TAG));
|
|
||||||
lIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
context.startActivity(lIntent);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
setResult(Activity.RESULT_OK,to.replace(TAG, ""),null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -20,10 +20,10 @@ package org.linphone;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.linphone.core.AndroidCameraRecordManager;
|
|
||||||
import org.linphone.core.LinphoneCore;
|
import org.linphone.core.LinphoneCore;
|
||||||
import org.linphone.core.Version;
|
import org.linphone.core.Version;
|
||||||
import org.linphone.core.VideoSize;
|
import org.linphone.core.VideoSize;
|
||||||
|
import org.linphone.core.video.AndroidCameraRecordManager;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -38,6 +38,11 @@ import android.view.MenuItem;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Android SDK >=
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class VideoCallActivity extends Activity {
|
public class VideoCallActivity extends Activity {
|
||||||
private SurfaceView mVideoView;
|
private SurfaceView mVideoView;
|
||||||
private SurfaceView mVideoCaptureView;
|
private SurfaceView mVideoCaptureView;
|
||||||
|
@ -46,7 +51,6 @@ public class VideoCallActivity extends Activity {
|
||||||
public static boolean launched = false;
|
public static boolean launched = false;
|
||||||
private WakeLock mWakeLock;
|
private WakeLock mWakeLock;
|
||||||
private static final int capturePreviewLargestDimension = 150;
|
private static final int capturePreviewLargestDimension = 150;
|
||||||
// private static final float similarRatio = 0.1f;
|
|
||||||
private int previousPhoneOrientation;
|
private int previousPhoneOrientation;
|
||||||
private int phoneOrientation;
|
private int phoneOrientation;
|
||||||
|
|
||||||
|
@ -57,7 +61,7 @@ public class VideoCallActivity extends Activity {
|
||||||
setContentView(R.layout.videocall);
|
setContentView(R.layout.videocall);
|
||||||
|
|
||||||
mVideoView = (SurfaceView) findViewById(R.id.video_surface);
|
mVideoView = (SurfaceView) findViewById(R.id.video_surface);
|
||||||
LinphoneCore lc = LinphoneService.getLc();
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
lc.setVideoWindow(mVideoView);
|
lc.setVideoWindow(mVideoView);
|
||||||
|
|
||||||
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
|
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
|
||||||
|
@ -68,12 +72,12 @@ public class VideoCallActivity extends Activity {
|
||||||
recordManager.setSurfaceView(mVideoCaptureView, phoneOrientation);
|
recordManager.setSurfaceView(mVideoCaptureView, phoneOrientation);
|
||||||
mVideoCaptureView.setZOrderOnTop(true);
|
mVideoCaptureView.setZOrderOnTop(true);
|
||||||
|
|
||||||
if (!recordManager.isMuted()) sendStaticImage(false);
|
if (!recordManager.isMuted()) LinphoneManager.getInstance().sendStaticImage(false);
|
||||||
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
||||||
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone");
|
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone");
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
|
|
||||||
if (Version.sdkBelow(8)) {
|
if (Version.sdkStrictlyBelow(8)) {
|
||||||
// Force to display in portrait orientation for old devices
|
// Force to display in portrait orientation for old devices
|
||||||
// as they do not support surfaceView rotation
|
// as they do not support surfaceView rotation
|
||||||
setRequestedOrientation(recordManager.isCameraOrientationPortrait() ?
|
setRequestedOrientation(recordManager.isCameraOrientationPortrait() ?
|
||||||
|
@ -81,23 +85,17 @@ public class VideoCallActivity extends Activity {
|
||||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base capture frame on streamed dimensions and orientation.
|
resizeCapturePreview(mVideoCaptureView);
|
||||||
resizeCapturePreview(mVideoCaptureView, lc.getPreferredVideoSize());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCallIfOrientationChanged() {
|
|
||||||
if (Version.sdkAbove(8) && previousPhoneOrientation != phoneOrientation) {
|
|
||||||
CallManager.getInstance().updateCall();
|
|
||||||
// camera will be restarted when mediastreamer chain is recreated and setParameters is called
|
|
||||||
|
|
||||||
// Base capture frame on streamed dimensions and orientation.
|
|
||||||
resizeCapturePreview(mVideoCaptureView, LinphoneService.getLc().getPreferredVideoSize());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
updateCallIfOrientationChanged();
|
// Update call if orientation changed
|
||||||
|
if (Version.sdkAboveOrEqual(8) && previousPhoneOrientation != phoneOrientation) {
|
||||||
|
CallManager.getInstance().updateCall();
|
||||||
|
resizeCapturePreview(mVideoCaptureView);
|
||||||
|
}
|
||||||
super.onResume();
|
super.onResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +108,7 @@ public class VideoCallActivity extends Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void rewriteChangeResolutionItem(MenuItem item) {
|
private void rewriteChangeResolutionItem(MenuItem item) {
|
||||||
if (BandwidthManager.getInstance().isUserRestriction()) {
|
if (BandwidthManager.getInstance().isUserRestriction()) {
|
||||||
item.setTitle(getString(R.string.menu_videocall_change_resolution_when_low_resolution));
|
item.setTitle(getString(R.string.menu_videocall_change_resolution_when_low_resolution));
|
||||||
|
@ -134,23 +133,18 @@ public class VideoCallActivity extends Activity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendStaticImage(boolean send) {
|
|
||||||
LinphoneCore lc = LinphoneService.getLc();
|
|
||||||
if (lc.isIncall()) {
|
|
||||||
lc.getCurrentCall().enableCamera(!send);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Base capture frame on streamed dimensions and orientation.
|
||||||
* @param sv capture surface view to resize the layout
|
* @param sv capture surface view to resize the layout
|
||||||
* @param vs video size from which to calculate the dimensions
|
* @param vs video size from which to calculate the dimensions
|
||||||
*/
|
*/
|
||||||
private void resizeCapturePreview(SurfaceView sv, VideoSize vs) {
|
private void resizeCapturePreview(SurfaceView sv) {
|
||||||
LayoutParams lp = sv.getLayoutParams();
|
LayoutParams lp = sv.getLayoutParams();
|
||||||
float newRatio = ratioWidthHeight(vs);
|
VideoSize vs = LinphoneManager.getLc().getPreferredVideoSize();
|
||||||
|
|
||||||
// float previewRatio = (float) lp.width / lp.height;
|
float newRatio = (float) vs.width / vs.height;
|
||||||
// if (Math.abs((newRatio-previewRatio)/newRatio) < similarRatio) return;
|
|
||||||
|
|
||||||
if (vs.isPortrait()) {
|
if (vs.isPortrait()) {
|
||||||
lp.height = capturePreviewLargestDimension;
|
lp.height = capturePreviewLargestDimension;
|
||||||
|
@ -163,49 +157,39 @@ public class VideoCallActivity extends Activity {
|
||||||
sv.setLayoutParams(lp);
|
sv.setLayoutParams(lp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.videocall_menu_back_to_dialer:
|
case R.id.videocall_menu_back_to_dialer:
|
||||||
if (!recordManager.isMuted()) sendStaticImage(true);
|
if (!recordManager.isMuted())
|
||||||
|
LinphoneManager.getInstance().sendStaticImage(true);
|
||||||
finish();
|
finish();
|
||||||
break;
|
break;
|
||||||
case R.id.videocall_menu_change_resolution:
|
case R.id.videocall_menu_change_resolution:
|
||||||
BandwidthManager manager = BandwidthManager.getInstance();
|
LinphoneManager.getInstance().changeResolution();
|
||||||
manager.setUserRestriction(!manager.isUserRestriction());
|
|
||||||
sendStaticImage(recordManager.isMuted());
|
|
||||||
rewriteChangeResolutionItem(item);
|
rewriteChangeResolutionItem(item);
|
||||||
|
resizeCapturePreview(mVideoCaptureView);
|
||||||
// Resize preview frame
|
|
||||||
VideoSize newVideoSize = LinphoneService.getLc().getPreferredVideoSize();
|
|
||||||
resizeCapturePreview(mVideoCaptureView, newVideoSize);
|
|
||||||
break;
|
break;
|
||||||
case R.id.videocall_menu_terminate_call:
|
case R.id.videocall_menu_terminate_call:
|
||||||
LinphoneCore lc = LinphoneService.getLc();
|
LinphoneManager.getInstance().terminateCall();
|
||||||
if (lc.isIncall()) {
|
|
||||||
lc.terminateCall(lc.getCurrentCall());
|
|
||||||
}
|
|
||||||
finish();
|
finish();
|
||||||
break;
|
break;
|
||||||
case R.id.videocall_menu_toggle_camera:
|
case R.id.videocall_menu_toggle_camera:
|
||||||
sendStaticImage(recordManager.toggleMute());
|
LinphoneManager.getInstance().toggleCameraMuting();
|
||||||
rewriteToggleCameraItem(item);
|
rewriteToggleCameraItem(item);
|
||||||
break;
|
break;
|
||||||
case R.id.videocall_menu_switch_camera:
|
case R.id.videocall_menu_switch_camera:
|
||||||
recordManager.stopVideoRecording();
|
LinphoneManager.getInstance().switchCamera();
|
||||||
recordManager.toggleUseFrontCamera();
|
resizeCapturePreview(mVideoCaptureView);
|
||||||
CallManager.getInstance().updateCall();
|
|
||||||
// camera will be restarted when mediastreamer chain is recreated and setParameters is called
|
|
||||||
|
|
||||||
// Base capture frame on streamed dimensions and orientation.
|
|
||||||
resizeCapturePreview(mVideoCaptureView, LinphoneService.getLc().getPreferredVideoSize());
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]");
|
Log.e(LinphoneManager.TAG, "Unknown menu item ["+item+"]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,13 +202,10 @@ public class VideoCallActivity extends Activity {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
Log.d(tag, "onPause VideoCallActivity");
|
Log.d(tag, "onPause VideoCallActivity");
|
||||||
|
LinphoneManager.getInstance().sendStaticImage(true);
|
||||||
if (mWakeLock.isHeld()) mWakeLock.release();
|
if (mWakeLock.isHeld()) mWakeLock.release();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public float ratioWidthHeight(VideoSize vs) {
|
|
||||||
return (float) vs.width / vs.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
AndroidCameraRecordImplAPI5.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;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import android.hardware.Camera;
|
|
||||||
import android.hardware.Camera.Parameters;
|
|
||||||
import android.hardware.Camera.Size;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
|
|
||||||
public class AndroidCameraRecord5Impl extends AndroidCameraRecordImpl {
|
|
||||||
|
|
||||||
public AndroidCameraRecord5Impl(RecorderParams parameters) {
|
|
||||||
super(parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSettingCameraParameters(Parameters parameters) {
|
|
||||||
super.onSettingCameraParameters(parameters);
|
|
||||||
|
|
||||||
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
|
||||||
Log.w(tag, "Auto Focus supported by camera device");
|
|
||||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
||||||
} else {
|
|
||||||
Log.w(tag, "Auto Focus not supported by camera device");
|
|
||||||
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
|
|
||||||
Log.w(tag, "Infinity Focus supported by camera device");
|
|
||||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
|
|
||||||
} else {
|
|
||||||
Log.w(tag, "Infinity Focus not supported by camera device");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Size> oneShotSupportedVideoSizes() {
|
|
||||||
Camera camera = Camera.open();
|
|
||||||
List<Size> supportedVideoSizes =camera.getParameters().getSupportedPreviewSizes();
|
|
||||||
camera.release();
|
|
||||||
return supportedVideoSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Size> getSupportedPreviewSizes(Parameters parameters) {
|
|
||||||
return parameters.getSupportedPreviewSizes();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,11 +34,11 @@ public class AndroidVideoWindowImpl {
|
||||||
mSurface=holder.getSurface();
|
mSurface=holder.getSurface();
|
||||||
}
|
}
|
||||||
if (mListener!=null) mListener.onSurfaceReady(AndroidVideoWindowImpl.this);
|
if (mListener!=null) mListener.onSurfaceReady(AndroidVideoWindowImpl.this);
|
||||||
Log.w("Linphone", "Video display surface changed");
|
Log.w(TAG, "Video display surface changed");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void surfaceCreated(SurfaceHolder holder) {
|
public void surfaceCreated(SurfaceHolder holder) {
|
||||||
Log.w("Linphone", "Video display surface created");
|
Log.w(TAG, "Video display surface created");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||||
|
@ -48,7 +48,7 @@ public class AndroidVideoWindowImpl {
|
||||||
}
|
}
|
||||||
if (mListener!=null)
|
if (mListener!=null)
|
||||||
mListener.onSurfaceDestroyed(AndroidVideoWindowImpl.this);
|
mListener.onSurfaceDestroyed(AndroidVideoWindowImpl.this);
|
||||||
Log.d("Linphone", "Video display surface destroyed");
|
Log.d(TAG, "Video display surface destroyed");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,28 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone;
|
package org.linphone.core;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class Hacks {
|
public final class Hacks {
|
||||||
|
|
||||||
|
private Hacks() {}
|
||||||
|
|
||||||
public static boolean isGalaxyS() {
|
public static boolean isGalaxyS() {
|
||||||
return Build.DEVICE.startsWith("GT-I9000") || Build.DEVICE.startsWith("GT-P1000");
|
return Build.DEVICE.startsWith("GT-I9000");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isGalaxySOrTab() {
|
||||||
|
return isGalaxyS() || isGalaxyTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isGalaxyTab() {
|
||||||
|
return Build.DEVICE.startsWith("GT-P1000");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* private static final boolean log(final String msg) {
|
/* private static final boolean log(final String msg) {
|
||||||
|
@ -68,6 +80,6 @@ public class Hacks {
|
||||||
//sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
|
//sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
|
||||||
sb.append("SDK=").append(Build.VERSION.SDK);
|
sb.append("SDK=").append(Build.VERSION.SDK);
|
||||||
|
|
||||||
Log.d("Linphone", sb.toString());
|
Log.d(LinphoneManager.TAG, sb.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -36,6 +36,7 @@ class LinphoneCallImpl implements LinphoneCall {
|
||||||
private native void enableEchoLimiter(long nativePtr,boolean enable);
|
private native void enableEchoLimiter(long nativePtr,boolean enable);
|
||||||
private native boolean isEchoLimiterEnabled(long nativePtr);
|
private native boolean isEchoLimiterEnabled(long nativePtr);
|
||||||
private native long getReplacedCall(long nativePtr);
|
private native long getReplacedCall(long nativePtr);
|
||||||
|
private native int getDuration(long nativePtr);
|
||||||
|
|
||||||
protected LinphoneCallImpl(long aNativePtr) {
|
protected LinphoneCallImpl(long aNativePtr) {
|
||||||
nativePtr = aNativePtr;
|
nativePtr = aNativePtr;
|
||||||
|
@ -97,4 +98,8 @@ class LinphoneCallImpl implements LinphoneCall {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDuration() {
|
||||||
|
return getDuration(nativePtr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,8 @@ class LinphoneCoreImpl implements LinphoneCore {
|
||||||
private native void enableKeepAlive(long nativePtr,boolean enable);
|
private native void enableKeepAlive(long nativePtr,boolean enable);
|
||||||
private native boolean isKeepAliveEnabled(long nativePtr);
|
private native boolean isKeepAliveEnabled(long nativePtr);
|
||||||
private native int startEchoCalibration(long nativePtr,Object data);
|
private native int startEchoCalibration(long nativePtr,Object data);
|
||||||
|
private native int getSignalingTransportPort(long nativePtr, int code);
|
||||||
|
private native void setSignalingTransportPorts(long nativePtr, int udp, int tcp, int tls);
|
||||||
|
|
||||||
LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException {
|
LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException {
|
||||||
mListener=listener;
|
mListener=listener;
|
||||||
|
@ -285,10 +286,6 @@ class LinphoneCoreImpl implements LinphoneCore {
|
||||||
public void setPlayLevel(int level) {
|
public void setPlayLevel(int level) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
|
||||||
public void setSignalingTransport(Transport aTransport) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public void enableSpeaker(boolean value) {
|
public void enableSpeaker(boolean value) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
@ -439,4 +436,19 @@ class LinphoneCoreImpl implements LinphoneCore {
|
||||||
public void startEchoCalibration(Object data) throws LinphoneCoreException {
|
public void startEchoCalibration(Object data) throws LinphoneCoreException {
|
||||||
startEchoCalibration(nativePtr, data);
|
startEchoCalibration(nativePtr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Transports getSignalingTransportPorts() {
|
||||||
|
Transports transports = new Transports();
|
||||||
|
transports.udp = getSignalingTransportPort(nativePtr, 0);
|
||||||
|
transports.tcp = getSignalingTransportPort(nativePtr, 1);
|
||||||
|
transports.tls = getSignalingTransportPort(nativePtr, 3);
|
||||||
|
// See C struct LCSipTransports in linphonecore.h
|
||||||
|
// Code is the index in the structure
|
||||||
|
return transports;
|
||||||
|
}
|
||||||
|
public void setSignalingTransportPorts(Transports transports) {
|
||||||
|
setSignalingTransportPorts(nativePtr, transports.udp, transports.tcp, transports.tls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,25 @@ public class Version {
|
||||||
8 : Integer.parseInt(Build.VERSION.SDK); // Force versions above 9 to 8
|
8 : Integer.parseInt(Build.VERSION.SDK); // Force versions above 9 to 8
|
||||||
// 7; // 2.1
|
// 7; // 2.1
|
||||||
|
|
||||||
public static final boolean sdkAbove(int value) {
|
public static final boolean sdkAboveOrEqual(int value) {
|
||||||
return buildVersion >= value;
|
return buildVersion >= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final boolean sdkBelow(int value) {
|
public static final boolean sdkStrictlyBelow(int value) {
|
||||||
return buildVersion < value;
|
return buildVersion < value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int sdk() {
|
||||||
|
return buildVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isArmv7() {
|
||||||
|
try {
|
||||||
|
return sdkAboveOrEqual(4)
|
||||||
|
&& Build.class.getField("CPU_ABI").get(null).toString().startsWith("armeabi-v7");
|
||||||
|
} catch (Throwable e) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,11 +23,12 @@ import android.widget.TextView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write notifications to a TextView widget.
|
* Write notifications to a TextView widget.
|
||||||
|
* This is an helper class, not a test activity.
|
||||||
*
|
*
|
||||||
* @author Guillaume Beraudo
|
* @author Guillaume Beraudo
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AndroidTutorialNotifier extends TutorialNotifier {
|
class AndroidTutorialNotifier extends TutorialNotifier {
|
||||||
|
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
private TextView outputTextView;
|
private TextView outputTextView;
|
||||||
|
|
|
@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core.tutorials;
|
package org.linphone.core.tutorials;
|
||||||
|
|
||||||
import org.linphone.core.AndroidCameraRecord;
|
import org.linphone.core.video.AndroidCameraRecord;
|
||||||
|
|
||||||
import android.hardware.Camera;
|
import android.hardware.Camera;
|
||||||
import android.hardware.Camera.PreviewCallback;
|
import android.hardware.Camera.PreviewCallback;
|
||||||
|
@ -26,7 +26,13 @@ import android.hardware.Camera.Size;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
public class JavaCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
|
/**
|
||||||
|
* This is an helper class, not a test activity.
|
||||||
|
*
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class JavaCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
|
||||||
|
|
||||||
private TextView debug;
|
private TextView debug;
|
||||||
private long count = 0;
|
private long count = 0;
|
||||||
|
@ -53,7 +59,7 @@ public class JavaCameraRecordImpl extends AndroidCameraRecord implements Preview
|
||||||
Size s = camera.getParameters().getPreviewSize();
|
Size s = camera.getParameters().getPreviewSize();
|
||||||
int expectedBuffLength = s.width * s.height * 3 /2;
|
int expectedBuffLength = s.width * s.height * 3 /2;
|
||||||
if (expectedBuffLength != data.length) {
|
if (expectedBuffLength != data.length) {
|
||||||
Log.e("Linphone", "onPreviewFrame called with bad buffer length " + data.length
|
Log.e(tag, "onPreviewFrame called with bad buffer length " + data.length
|
||||||
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
|
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ package org.linphone.core.tutorials;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.core.AndroidCameraRecord;
|
|
||||||
import org.linphone.core.VideoSize;
|
import org.linphone.core.VideoSize;
|
||||||
|
import org.linphone.core.video.AndroidCameraRecord;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
|
@ -16,18 +16,18 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core;
|
package org.linphone.core.video;
|
||||||
|
|
||||||
import org.linphone.Hacks;
|
import org.linphone.core.Hacks;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class AndroidCameraConf {
|
class AndroidCameraConf {
|
||||||
private static final String tag = "Linphone";
|
private static final String tag = "Linphone";
|
||||||
|
|
||||||
public void findFrontAndRearCameraIds(int[] frontCameraId, int[] rearCameraId, int[] cameraId) {
|
public void findFrontAndRearCameraIds(int[] frontCameraId, int[] rearCameraId, int[] cameraId) {
|
||||||
Log.i(tag, "Detecting cameras");
|
Log.i(tag, "Detecting cameras");
|
||||||
if (Hacks.isGalaxyS()) {
|
if (Hacks.isGalaxySOrTab()) {
|
||||||
Log.d(tag, "Hack Galaxy S : has 2 cameras front=2; rear=1");
|
Log.d(tag, "Hack Galaxy S : has 2 cameras front=2; rear=1");
|
||||||
frontCameraId[0] = 2;
|
frontCameraId[0] = 2;
|
||||||
rearCameraId[0] = 1;
|
rearCameraId[0] = 1;
|
||||||
|
@ -39,8 +39,9 @@ public class AndroidCameraConf {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfCameras() {
|
public int getNumberOfCameras() {
|
||||||
|
Log.i(tag, "Detecting the number of cameras");
|
||||||
// Use hacks to guess the number of cameras
|
// Use hacks to guess the number of cameras
|
||||||
if (Hacks.isGalaxyS()) {
|
if (Hacks.isGalaxySOrTab()) {
|
||||||
Log.d(tag, "Hack Galaxy S : has 2 cameras");
|
Log.d(tag, "Hack Galaxy S : has 2 cameras");
|
||||||
return 2;
|
return 2;
|
||||||
} else
|
} else
|
||||||
|
@ -51,7 +52,7 @@ public class AndroidCameraConf {
|
||||||
|
|
||||||
public int getCameraOrientation(int cameraId) {
|
public int getCameraOrientation(int cameraId) {
|
||||||
// Use hacks to guess orientation of the camera
|
// Use hacks to guess orientation of the camera
|
||||||
if (cameraId == 2 && Hacks.isGalaxyS()) {
|
if (cameraId == 2 && Hacks.isGalaxySOrTab()) {
|
||||||
Log.d(tag, "Hack Galaxy S : rear camera id=2 ; mounted landscape");
|
Log.d(tag, "Hack Galaxy S : rear camera id=2 ; mounted landscape");
|
||||||
// mounted in landscape for a portrait phone orientation
|
// mounted in landscape for a portrait phone orientation
|
||||||
return 90;
|
return 90;
|
||||||
|
@ -64,7 +65,7 @@ public class AndroidCameraConf {
|
||||||
|
|
||||||
public boolean isFrontCamera(int cameraId) {
|
public boolean isFrontCamera(int cameraId) {
|
||||||
// Use hacks to guess facing of the camera
|
// Use hacks to guess facing of the camera
|
||||||
if (cameraId == 2 && Hacks.isGalaxyS()) {
|
if (cameraId == 2 && Hacks.isGalaxySOrTab()) {
|
||||||
Log.d(tag, "Hack Galaxy S : front camera has id=2");
|
Log.d(tag, "Hack Galaxy S : front camera has id=2");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
|
@ -16,11 +16,11 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core;
|
package org.linphone.core.video;
|
||||||
|
|
||||||
import android.hardware.Camera;
|
import android.hardware.Camera;
|
||||||
|
|
||||||
public class AndroidCameraConf9 extends AndroidCameraConf {
|
class AndroidCameraConf9 extends AndroidCameraConf {
|
||||||
|
|
||||||
public void findFrontAndRearCameraIds9(Integer frontCameraId, Integer rearCameraId, Integer cameraId) {
|
public void findFrontAndRearCameraIds9(Integer frontCameraId, Integer rearCameraId, Integer cameraId) {
|
||||||
for (int id=0; id < getNumberOfCameras(); id++) {
|
for (int id=0; id < getNumberOfCameras(); id++) {
|
|
@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core;
|
package org.linphone.core.video;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
|
@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core;
|
package org.linphone.core.video;
|
||||||
|
|
||||||
import android.hardware.Camera;
|
import android.hardware.Camera;
|
||||||
import android.hardware.Camera.Parameters;
|
import android.hardware.Camera.Parameters;
|
||||||
|
@ -30,17 +30,17 @@ import android.util.Log;
|
||||||
* @author Guillaume Beraudo
|
* @author Guillaume Beraudo
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AndroidCameraRecord8Impl extends AndroidCameraRecord5Impl {
|
class AndroidCameraRecord8 extends AndroidCameraRecordImpl {
|
||||||
|
|
||||||
|
|
||||||
public AndroidCameraRecord8Impl(RecorderParams parameters) {
|
public AndroidCameraRecord8(RecorderParams parameters) {
|
||||||
super(parameters);
|
super(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
Log.d("Linphone", "Setting optimized callback with buffer (Android >= 8). Remember to manage the pool of buffers!!!");
|
Log.d(tag, "Setting optimized callback with buffer (Android >= 8). Remember to manage the pool of buffers!!!");
|
||||||
}
|
}
|
||||||
camera.setPreviewCallbackWithBuffer(cb);
|
camera.setPreviewCallbackWithBuffer(cb);
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core;
|
package org.linphone.core.video;
|
||||||
|
|
||||||
import android.hardware.Camera;
|
import android.hardware.Camera;
|
||||||
|
|
||||||
|
@ -26,10 +26,10 @@ import android.hardware.Camera;
|
||||||
* @author Guillaume Beraudo
|
* @author Guillaume Beraudo
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AndroidCameraRecord9Impl extends AndroidCameraRecord8Impl {
|
class AndroidCameraRecord9 extends AndroidCameraRecord8 {
|
||||||
|
|
||||||
|
|
||||||
public AndroidCameraRecord9Impl(RecorderParams parameters) {
|
public AndroidCameraRecord9(RecorderParams parameters) {
|
||||||
super(parameters);
|
super(parameters);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,19 +16,24 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core;
|
package org.linphone.core.video;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import android.hardware.Camera;
|
import android.hardware.Camera;
|
||||||
|
import android.hardware.Camera.Parameters;
|
||||||
import android.hardware.Camera.PreviewCallback;
|
import android.hardware.Camera.PreviewCallback;
|
||||||
|
import android.hardware.Camera.Size;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record from Android camera.
|
* Record from Android camera.
|
||||||
|
* Android >= 5 (2.0) version.
|
||||||
*
|
*
|
||||||
* @author Guillaume Beraudo
|
* @author Guillaume Beraudo
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
|
class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
|
||||||
|
|
||||||
private long filterCtxPtr;
|
private long filterCtxPtr;
|
||||||
private double timeElapsedBetweenFrames = 0;
|
private double timeElapsedBetweenFrames = 0;
|
||||||
|
@ -51,17 +56,17 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
|
||||||
|
|
||||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
Log.e("Linphone", "onPreviewFrame Called with null buffer");
|
Log.e(tag, "onPreviewFrame Called with null buffer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (filterCtxPtr == 0l) {
|
if (filterCtxPtr == 0l) {
|
||||||
Log.e("Linphone", "onPreviewFrame Called with no filterCtxPtr set");
|
Log.e(tag, "onPreviewFrame Called with no filterCtxPtr set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int expectedBuffLength = getExpectedBufferLength();
|
int expectedBuffLength = getExpectedBufferLength();
|
||||||
if (expectedBuffLength != data.length) {
|
if (expectedBuffLength != data.length) {
|
||||||
Log.e("Linphone", "onPreviewFrame called with bad buffer length " + data.length
|
Log.e(tag, "onPreviewFrame called with bad buffer length " + data.length
|
||||||
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
|
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +80,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
|
||||||
|
|
||||||
double currentTimeElapsed = 0.8 * (curTime - lastFrameTime) / 1000 + 0.2 * timeElapsedBetweenFrames;
|
double currentTimeElapsed = 0.8 * (curTime - lastFrameTime) / 1000 + 0.2 * timeElapsedBetweenFrames;
|
||||||
if (currentTimeElapsed < expectedTimeBetweenFrames) {
|
if (currentTimeElapsed < expectedTimeBetweenFrames) {
|
||||||
// Log.d("Linphone", "Clipping frame " + Math.round(1 / currentTimeElapsed) + " > " + fps);
|
// Log.d(tag, "Clipping frame " + Math.round(1 / currentTimeElapsed) + " > " + fps);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastFrameTime = curTime;
|
lastFrameTime = curTime;
|
||||||
|
@ -85,7 +90,35 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
|
||||||
putImage(filterCtxPtr, data, rotation);
|
putImage(filterCtxPtr, data, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSettingCameraParameters(Parameters parameters) {
|
||||||
|
super.onSettingCameraParameters(parameters);
|
||||||
|
|
||||||
|
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
||||||
|
Log.w(tag, "Auto Focus supported by camera device");
|
||||||
|
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
||||||
|
} else {
|
||||||
|
Log.w(tag, "Auto Focus not supported by camera device");
|
||||||
|
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
|
||||||
|
Log.w(tag, "Infinity Focus supported by camera device");
|
||||||
|
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
|
||||||
|
} else {
|
||||||
|
Log.w(tag, "Infinity Focus not supported by camera device");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Size> oneShotSupportedVideoSizes() {
|
||||||
|
Camera camera = Camera.open();
|
||||||
|
List<Size> supportedVideoSizes =camera.getParameters().getSupportedPreviewSizes();
|
||||||
|
camera.release();
|
||||||
|
return supportedVideoSizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Size> getSupportedPreviewSizes(Parameters parameters) {
|
||||||
|
return parameters.getSupportedPreviewSizes();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
|
|
@ -16,11 +16,12 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.core;
|
package org.linphone.core.video;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.linphone.core.AndroidCameraRecord.RecorderParams;
|
import org.linphone.core.Version;
|
||||||
|
import org.linphone.core.video.AndroidCameraRecord.RecorderParams;
|
||||||
|
|
||||||
import android.hardware.Camera.Size;
|
import android.hardware.Camera.Size;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -67,7 +68,7 @@ public class AndroidCameraRecordManager {
|
||||||
|
|
||||||
// singleton
|
// singleton
|
||||||
private AndroidCameraRecordManager() {
|
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};
|
int[] fId = {-1};int[] rId = {-1};int[] cId = {-1};
|
||||||
cc.findFrontAndRearCameraIds(fId, rId, cId);
|
cc.findFrontAndRearCameraIds(fId, rId, cId);
|
||||||
|
@ -144,14 +145,19 @@ public class AndroidCameraRecordManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMuted(boolean muteState) {
|
/**
|
||||||
if (muteState == muted) return;
|
* @param muteState
|
||||||
|
* @return true if mute state changed
|
||||||
|
*/
|
||||||
|
public boolean setMuted(boolean muteState) {
|
||||||
|
if (muteState == muted) return false;
|
||||||
muted = muteState;
|
muted = muteState;
|
||||||
if (muted) {
|
if (muted) {
|
||||||
stopVideoRecording();
|
stopVideoRecording();
|
||||||
} else {
|
} else {
|
||||||
tryToStartVideoRecording();
|
tryToStartVideoRecording();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
public boolean toggleMute() {
|
public boolean toggleMute() {
|
||||||
setMuted(!muted);
|
setMuted(!muted);
|
||||||
|
@ -172,14 +178,14 @@ public class AndroidCameraRecordManager {
|
||||||
parameters.rotation = bufferRotationForCorrectImageOrientation();
|
parameters.rotation = bufferRotationForCorrectImageOrientation();
|
||||||
|
|
||||||
parameters.surfaceView = surfaceView;
|
parameters.surfaceView = surfaceView;
|
||||||
if (Version.sdkAbove(9)) {
|
if (Version.sdkAboveOrEqual(9)) {
|
||||||
recorder = new AndroidCameraRecord9Impl(parameters);
|
recorder = new AndroidCameraRecord9(parameters);
|
||||||
} else if (Version.sdkAbove(8)) {
|
} else if (Version.sdkAboveOrEqual(8)) {
|
||||||
recorder = new AndroidCameraRecord8Impl(parameters);
|
recorder = new AndroidCameraRecord8(parameters);
|
||||||
} else if (Version.sdkAbove(5)) {
|
} else if (Version.sdkAboveOrEqual(5)) {
|
||||||
recorder = new AndroidCameraRecord5Impl(parameters);
|
|
||||||
} else {
|
|
||||||
recorder = new AndroidCameraRecordImpl(parameters);
|
recorder = new AndroidCameraRecordImpl(parameters);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("SDK version unsupported " + Version.sdk());
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder.startPreview();
|
recorder.startPreview();
|
||||||
|
@ -208,8 +214,8 @@ public class AndroidCameraRecordManager {
|
||||||
if (supportedVideoSizes != null) return supportedVideoSizes;
|
if (supportedVideoSizes != null) return supportedVideoSizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Version.sdkAbove(5)) {
|
if (Version.sdkAboveOrEqual(5)) {
|
||||||
supportedVideoSizes = AndroidCameraRecord5Impl.oneShotSupportedVideoSizes();
|
supportedVideoSizes = AndroidCameraRecordImpl.oneShotSupportedVideoSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eventually null
|
// eventually null
|
||||||
|
@ -253,7 +259,7 @@ public class AndroidCameraRecordManager {
|
||||||
|
|
||||||
private int bufferRotationForCorrectImageOrientation() {
|
private int bufferRotationForCorrectImageOrientation() {
|
||||||
final int cameraOrientation = cc.getCameraOrientation(cameraId);
|
final int cameraOrientation = cc.getCameraOrientation(cameraId);
|
||||||
final int rotation = Version.sdkAbove(8) ?
|
final int rotation = Version.sdkAboveOrEqual(8) ?
|
||||||
(360 - cameraOrientation + 90 - phoneOrientation) % 360
|
(360 - cameraOrientation + 90 - phoneOrientation) % 360
|
||||||
: 0;
|
: 0;
|
||||||
Log.d(tag, "Capture video buffer will need a rotation of " + rotation
|
Log.d(tag, "Capture video buffer will need a rotation of " + rotation
|
43
src/org/linphone/ui/AddVideoButton.java
Normal file
43
src/org/linphone/ui/AddVideoButton.java
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
AddVideoButton.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.ui;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AddVideoButton extends ImageButton implements OnClickListener {
|
||||||
|
|
||||||
|
public AddVideoButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
LinphoneManager.getInstance().addVideo();
|
||||||
|
}
|
||||||
|
}
|
31
src/org/linphone/ui/AddressAware.java
Normal file
31
src/org/linphone/ui/AddressAware.java
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
AddressAwareWidget.java
|
||||||
|
Copyright (C) 2011 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.ui;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface AddressAware {
|
||||||
|
|
||||||
|
void setAddressWidget(AddressText address);
|
||||||
|
|
||||||
|
}
|
64
src/org/linphone/ui/AddressText.java
Normal file
64
src/org/linphone/ui/AddressText.java
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
AddressView.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.ui;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager.AddressType;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AddressText extends EditText implements AddressType {
|
||||||
|
|
||||||
|
private String displayedName;
|
||||||
|
|
||||||
|
public AddressText(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearDisplayedName() {
|
||||||
|
displayedName = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayedName() {
|
||||||
|
return displayedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactAddress(String uri, String displayedName) {
|
||||||
|
setText(uri);
|
||||||
|
this.displayedName = displayedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisplayedName(String displayedName) {
|
||||||
|
this.displayedName = displayedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onTextChanged(CharSequence text, int start, int before,
|
||||||
|
int after) {
|
||||||
|
clearDisplayedName();
|
||||||
|
super.onTextChanged(text, start, before, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
73
src/org/linphone/ui/CallButton.java
Normal file
73
src/org/linphone/ui/CallButton.java
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
CallButton.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.ui;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
import org.linphone.R;
|
||||||
|
import org.linphone.core.LinphoneCoreException;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CallButton extends ImageButton implements OnClickListener, AddressAware {
|
||||||
|
|
||||||
|
private AddressText mAddress;
|
||||||
|
public void setAddressWidget(AddressText a) {mAddress = a;}
|
||||||
|
|
||||||
|
private OnClickListener externalClickListener;
|
||||||
|
public void setExternalClickListener(OnClickListener e) {externalClickListener = e;}
|
||||||
|
|
||||||
|
public CallButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
try {
|
||||||
|
if (!LinphoneManager.getInstance().acceptCallIfIncomingPending()) {
|
||||||
|
if (mAddress.getText().length() >0) {
|
||||||
|
LinphoneManager.getInstance().newOutgoingCall(mAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (LinphoneCoreException e) {
|
||||||
|
LinphoneManager.getInstance().terminateCall();
|
||||||
|
onWrongDestinationAddress();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (externalClickListener != null) externalClickListener.onClick(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
132
src/org/linphone/ui/Digit.java
Normal file
132
src/org/linphone/ui/Digit.java
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
Digit.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.ui;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
import org.linphone.core.LinphoneCore;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
public class Digit extends Button implements AddressAware {
|
||||||
|
|
||||||
|
private AddressText mAddress;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onTextChanged(CharSequence text, int start, int before,
|
||||||
|
int after) {
|
||||||
|
super.onTextChanged(text, start, before, after);
|
||||||
|
|
||||||
|
if (text == null || text.length() < 1) return;
|
||||||
|
|
||||||
|
DialKeyListener lListener = new DialKeyListener();
|
||||||
|
setOnClickListener(lListener);
|
||||||
|
setOnTouchListener(lListener);
|
||||||
|
|
||||||
|
if ("0+".equals(text)) {
|
||||||
|
setOnLongClickListener(lListener);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Digit(Context context, AttributeSet attrs, int style) {
|
||||||
|
super(context, attrs, style);
|
||||||
|
setLongClickable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Digit(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setLongClickable(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Digit(Context context) {
|
||||||
|
super(context);
|
||||||
|
setLongClickable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class DialKeyListener implements OnClickListener, OnTouchListener, OnLongClickListener {
|
||||||
|
final CharSequence mKeyCode;
|
||||||
|
boolean mIsDtmfStarted=false;
|
||||||
|
|
||||||
|
DialKeyListener() {
|
||||||
|
mKeyCode = Digit.this.getText().subSequence(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
|
lc.stopDtmf();
|
||||||
|
mIsDtmfStarted =false;
|
||||||
|
|
||||||
|
if (lc.isIncall()) {
|
||||||
|
lc.sendDtmf(mKeyCode.charAt(0));
|
||||||
|
} else if (mAddress != null) {
|
||||||
|
int lBegin = mAddress.getSelectionStart();
|
||||||
|
if (lBegin == -1) {
|
||||||
|
lBegin = mAddress.length();
|
||||||
|
}
|
||||||
|
if (lBegin >=0) {
|
||||||
|
mAddress.getEditableText().insert(lBegin,mKeyCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_DOWN && mIsDtmfStarted ==false) {
|
||||||
|
LinphoneManager.getInstance().playDtmf(getContext().getContentResolver(), mKeyCode.charAt(0));
|
||||||
|
mIsDtmfStarted=true;
|
||||||
|
} else {
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_UP)
|
||||||
|
lc.stopDtmf();
|
||||||
|
mIsDtmfStarted =false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
// Called if "0+" dtmf
|
||||||
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
|
lc.stopDtmf();
|
||||||
|
|
||||||
|
if (mAddress == null) return true;
|
||||||
|
|
||||||
|
int lBegin = mAddress.getSelectionStart();
|
||||||
|
if (lBegin == -1) {
|
||||||
|
lBegin = mAddress.getEditableText().length();
|
||||||
|
}
|
||||||
|
if (lBegin >=0) {
|
||||||
|
mAddress.getEditableText().insert(lBegin,"+");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void setAddressWidget(AddressText address) {
|
||||||
|
mAddress = address;
|
||||||
|
}
|
||||||
|
}
|
59
src/org/linphone/ui/EraseButton.java
Normal file
59
src/org/linphone/ui/EraseButton.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
EraseButton.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.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.View.OnLongClickListener;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
public class EraseButton extends Button implements OnClickListener, OnLongClickListener{
|
||||||
|
|
||||||
|
private AddressText address;
|
||||||
|
|
||||||
|
public EraseButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setOnClickListener(this);
|
||||||
|
setOnLongClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (address.getText().length() >0) {
|
||||||
|
int lBegin = address.getSelectionStart();
|
||||||
|
if (lBegin == -1) {
|
||||||
|
lBegin = address.getEditableText().length()-1;
|
||||||
|
}
|
||||||
|
if (lBegin >0) {
|
||||||
|
address.getEditableText().delete(lBegin-1,lBegin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
address.getEditableText().clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddressView(AddressText view) {
|
||||||
|
address = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
46
src/org/linphone/ui/HangCallButton.java
Normal file
46
src/org/linphone/ui/HangCallButton.java
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
HangCallButton.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.ui;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
import org.linphone.core.LinphoneCore;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
|
||||||
|
public class HangCallButton extends ImageButton implements OnClickListener {
|
||||||
|
|
||||||
|
private OnClickListener externalClickListener;
|
||||||
|
public void setExternalClickListener(OnClickListener e) {externalClickListener = e;}
|
||||||
|
|
||||||
|
public HangCallButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
LinphoneCore lc = LinphoneManager.getLc();
|
||||||
|
lc.terminateCall(lc.getCurrentCall());
|
||||||
|
|
||||||
|
if (externalClickListener != null) externalClickListener.onClick(v);
|
||||||
|
}
|
||||||
|
}
|
93
src/org/linphone/ui/IncallTimer.java
Normal file
93
src/org/linphone/ui/IncallTimer.java
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
IncallTimer.java
|
||||||
|
Copyright (C) 2011 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.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Widget displaying a time
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IncallTimer extends TextView {
|
||||||
|
|
||||||
|
public IncallTimer(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncallTimer(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncallTimer(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(CharSequence text, BufferType type) {
|
||||||
|
try {
|
||||||
|
int seconds = Integer.parseInt(text.toString());
|
||||||
|
super.setText(formatTime(seconds), type);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
super.setText(text, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String formatTime(final int seconds) {
|
||||||
|
String time = String.format("%02d : %02d",
|
||||||
|
(seconds / 60) % 60,
|
||||||
|
seconds % 60);
|
||||||
|
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
if (hours != 0) {
|
||||||
|
return hours + " - " + time;
|
||||||
|
} else {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format time as "days - hh : mm : ss".
|
||||||
|
* @param seconds
|
||||||
|
* @return formated string
|
||||||
|
*/
|
||||||
|
/*protected String formatTime(final int seconds) {
|
||||||
|
int value = seconds;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (int base : Arrays.asList(60, 60, 24)) {
|
||||||
|
if (value == 0) break;
|
||||||
|
|
||||||
|
int remainder = value % base;
|
||||||
|
value /= base;
|
||||||
|
|
||||||
|
if (sb.length() != 0) sb.insert(0, " : ");
|
||||||
|
sb.insert(0, remainder < 10 ? "0" + remainder : remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != 0) sb.insert(0, value + " - ");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
55
src/org/linphone/ui/MuteMicButton.java
Normal file
55
src/org/linphone/ui/MuteMicButton.java
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
SpeakerButton.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.ui;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
import org.linphone.ui.ToggleImageButton.OnCheckedChangeListener;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MuteMicButton extends ToggleImageButton implements OnCheckedChangeListener {
|
||||||
|
|
||||||
|
public MuteMicButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setOnCheckedChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isMicMuted() {
|
||||||
|
return isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMicMuted(boolean state) {
|
||||||
|
setChecked(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onCheckedChanged(ToggleImageButton button, boolean checked) {
|
||||||
|
if (checked) {
|
||||||
|
LinphoneManager.getLc().muteMic(true);
|
||||||
|
} else {
|
||||||
|
LinphoneManager.getLc().muteMic(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
src/org/linphone/ui/Numpad.java
Normal file
68
src/org/linphone/ui/Numpad.java
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
NumpadView.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.ui;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.linphone.R;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Numpad extends LinearLayout implements AddressAware {
|
||||||
|
|
||||||
|
public Numpad(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.numpad, this);
|
||||||
|
setLongClickable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddressWidget(AddressText address) {
|
||||||
|
for (AddressAware v : retrieveChildren(this)) {
|
||||||
|
v.setAddressWidget(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Collection<AddressAware> retrieveChildren(ViewGroup viewGroup) {
|
||||||
|
final Collection<AddressAware> views = new ArrayList<AddressAware>();
|
||||||
|
|
||||||
|
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
||||||
|
View v = viewGroup.getChildAt(i);
|
||||||
|
if (v instanceof ViewGroup) {
|
||||||
|
views.addAll(retrieveChildren((ViewGroup) v));
|
||||||
|
} else {
|
||||||
|
if (v instanceof AddressAware)
|
||||||
|
views.add((AddressAware) v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
57
src/org/linphone/ui/SpeakerButton.java
Normal file
57
src/org/linphone/ui/SpeakerButton.java
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
SpeakerButton.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.ui;
|
||||||
|
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
import org.linphone.ui.ToggleImageButton.OnCheckedChangeListener;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guillaume Beraudo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SpeakerButton extends ToggleImageButton implements OnCheckedChangeListener {
|
||||||
|
|
||||||
|
public SpeakerButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setOnCheckedChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isSpeakerOn() {
|
||||||
|
return isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpeakerOn(boolean state) {
|
||||||
|
setChecked(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onCheckedChanged(ToggleImageButton button, boolean checked) {
|
||||||
|
if (checked) {
|
||||||
|
LinphoneManager.getInstance().routeAudioToSpeaker();
|
||||||
|
} else {
|
||||||
|
LinphoneManager.getInstance().routeAudioToReceiver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
package org.linphone.component;
|
package org.linphone.ui;
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -36,7 +36,8 @@ import android.widget.ImageButton;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ToggleImageButton extends ImageButton implements OnClickListener {
|
public class ToggleImageButton extends ImageButton implements OnClickListener {
|
||||||
private static final String namespace = null;
|
// private static final String ns = "http://schemas.android.com/apk/res/linphone";
|
||||||
|
private static final String ns = null;
|
||||||
private boolean checked;
|
private boolean checked;
|
||||||
private Drawable stateChecked;
|
private Drawable stateChecked;
|
||||||
private Drawable stateUnChecked;
|
private Drawable stateUnChecked;
|
||||||
|
@ -44,8 +45,8 @@ public class ToggleImageButton extends ImageButton implements OnClickListener {
|
||||||
|
|
||||||
public ToggleImageButton(Context context, AttributeSet attrs) {
|
public ToggleImageButton(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
stateChecked = getResources().getDrawable(attrs.getAttributeResourceValue(namespace, "checked", -1));
|
stateChecked = getResources().getDrawable(attrs.getAttributeResourceValue(ns, "checked", -1));
|
||||||
stateUnChecked = getResources().getDrawable(attrs.getAttributeResourceValue(namespace, "unchecked", -1));
|
stateUnChecked = getResources().getDrawable(attrs.getAttributeResourceValue(ns, "unchecked", -1));
|
||||||
setBackgroundColor(Color.TRANSPARENT);
|
setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
setOnClickListener(this);
|
setOnClickListener(this);
|
|
@ -1 +1 @@
|
||||||
Subproject commit aff1134b38c23eccadc4ee40c7cba7b10b6d04ef
|
Subproject commit 2e35f52d35dc6f2e22ffa85130ad233172a5f488
|
Loading…
Reference in a new issue