Merge remote-tracking branch 'origin/master' into dev_in_app_purchase

Conflicts:
	AndroidManifest.xml
This commit is contained in:
Sylvain Berfini 2015-05-12 17:15:16 +02:00
commit d7bb9a7f19
40 changed files with 272 additions and 170 deletions

1
.gitignore vendored
View file

@ -37,3 +37,4 @@ submodules/externals/build/openh264/x86
tests/*$py.class tests/*$py.class
tests/build.xml tests/build.xml
tests/project.properties tests/project.properties
ant_password.properties

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.linphone" package="org.linphone"
android:versionCode="2410" android:installLocation="auto"> android:versionCode="2400" android:installLocation="auto">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="22"/> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="22"/>
<!-- Permissions for Push Notification --> <!-- Permissions for Push Notification -->
@ -119,6 +119,7 @@
<activity android:name="org.linphone.ChatActivity" <activity android:name="org.linphone.ChatActivity"
android:theme="@style/NoTitle" android:theme="@style/NoTitle"
android:configChanges="orientation|screenSize|keyboardHidden"
android:windowSoftInputMode="adjustPan|adjustResize" android:windowSoftInputMode="adjustPan|adjustResize"
android:launchMode="singleTask"> android:launchMode="singleTask">
<intent-filter> <intent-filter>

View file

@ -99,6 +99,15 @@ ifneq ($(shell ls ./submodules/linphone/mediastreamer2/java/src/org/linphone/med
$(error ./submodules/linphone/mediastreamer2/java/src/org/linphone/mediastream/MediastreamerActivity.java found: please either remove it or move it to MediastreamActivity.java.ignored before continuing.) $(error ./submodules/linphone/mediastreamer2/java/src/org/linphone/mediastream/MediastreamerActivity.java found: please either remove it or move it to MediastreamActivity.java.ignored before continuing.)
endif endif
ifeq ($(BUILD_NON_FREE_CODECS), 0)
BUILD_OPENH264=0
ENABLE_OPENH264_DECODER=0
BUILD_AMRNB=0
BUILD_AMRWB=0
BUILD_G729=0
BUILD_X264=0
endif
all: update-project generate-apk all: update-project generate-apk
ifeq ($(ENABLE_GPL_THIRD_PARTIES),1) ifeq ($(ENABLE_GPL_THIRD_PARTIES),1)
@echo "***************************************************************************" @echo "***************************************************************************"
@ -164,8 +173,8 @@ $(FFMPEG_SRC_DIR)/non_versioned_soname_patch_applied.txt:
$(FFMPEG_BUILD_DIR)/arm/config.h: $(FFMPEG_BUILD_DIR)/arm/config.h:
mkdir -p $(FFMPEG_BUILD_DIR)/arm && \ mkdir -p $(FFMPEG_BUILD_DIR)/arm && \
cd $(FFMPEG_BUILD_DIR)/arm && \ cd $(FFMPEG_BUILD_DIR)/arm && \
$(FFMPEG_SRC_DIR)/configure $(FFMPEG_CONFIGURE_OPTIONS) $(FFMPEG_ARM_CONFIGURE_OPTIONS) $(FFMPEG_SRC_DIR)/configure $(FFMPEG_CONFIGURE_OPTIONS) $(FFMPEG_ARM_CONFIGURE_OPTIONS)
sed -i.bak 's/#define HAVE_SYSCTL 1/#define HAVE_SYSCTL 0/g' $(FFMPEG_BUILD_DIR)/arm/config.h sed -i.bak 's/#define HAVE_SYSCTL 1/#define HAVE_SYSCTL 0/g' $(FFMPEG_BUILD_DIR)/arm/config.h
sed -i.bak 's/#define HAVE_GETHRTIME 1/#define HAVE_GETHRTIME 0/g' $(FFMPEG_BUILD_DIR)/arm/config.h sed -i.bak 's/#define HAVE_GETHRTIME 1/#define HAVE_GETHRTIME 0/g' $(FFMPEG_BUILD_DIR)/arm/config.h
@ -181,8 +190,8 @@ $(FFMPEG_BUILD_DIR)/arm/libffmpeg-linphone-arm.so: $(FFMPEG_BUILD_DIR)/arm/libav
$(FFMPEG_BUILD_DIR)/x86/config.h: $(FFMPEG_BUILD_DIR)/x86/config.h:
mkdir -p $(FFMPEG_BUILD_DIR)/x86 && \ mkdir -p $(FFMPEG_BUILD_DIR)/x86 && \
cd $(FFMPEG_BUILD_DIR)/x86 && \ cd $(FFMPEG_BUILD_DIR)/x86 && \
$(FFMPEG_SRC_DIR)/configure $(FFMPEG_CONFIGURE_OPTIONS) $(FFMPEG_X86_CONFIGURE_OPTIONS) $(FFMPEG_SRC_DIR)/configure $(FFMPEG_CONFIGURE_OPTIONS) $(FFMPEG_X86_CONFIGURE_OPTIONS)
sed -i.bak 's/#define HAVE_SYSCTL 1/#define HAVE_SYSCTL 0/g' $(FFMPEG_BUILD_DIR)/x86/config.h sed -i.bak 's/#define HAVE_SYSCTL 1/#define HAVE_SYSCTL 0/g' $(FFMPEG_BUILD_DIR)/x86/config.h
sed -i.bak 's/#define HAVE_GETHRTIME 1/#define HAVE_GETHRTIME 0/g' $(FFMPEG_BUILD_DIR)/x86/config.h sed -i.bak 's/#define HAVE_GETHRTIME 1/#define HAVE_GETHRTIME 0/g' $(FFMPEG_BUILD_DIR)/x86/config.h
@ -462,10 +471,8 @@ install-apk:
release: update-project release: update-project
$(ANT) clean $(ANT) clean
echo "What is the version name for the release ?"; \
read version; \
echo "version.name=$$version" > default.properties
patch -p1 < release.patch patch -p1 < release.patch
cat ant.properties | grep version.name > default.properties
$(ANT) release $(ANT) release
git checkout HEAD AndroidManifest.xml git checkout HEAD AndroidManifest.xml

8
README
View file

@ -25,9 +25,11 @@ To build liblinphone for Android, you must:
$ make mediastreamer2-sdk $ make mediastreamer2-sdk
7) (Optional) To generate a signed apk to publish on the Google Play, run 7) (Optional) To generate a signed apk to publish on the Google Play, run
$ make release $ make release
It will ask you for the version number that will be displayed in the about page of the app. Make sure you filled the ant.properties values for version.name, key.store and key.alias in order to correctly sign the generated apk.
Make sure you filled the ant.properties values for key.store and key.alias in order to correctly You also may want to create a file name ant_password.properties with the following:
sign the generated apk (it will ask you the password during the process) key.store.password=[your_password]
key.alias.password=[your_password]
If you don't, the passwords will be asked at the signing phase.
To run the tutorials: To run the tutorials:
-------------------- --------------------

View file

@ -1,3 +1,4 @@
source.dir=src:submodules/linphone/mediastreamer2/java/src:submodules/linphone/java/j2se:submodules/linphone/java/common:submodules/linphone/java/impl:submodules/linphone/coreapi/help/java:submodules/externals/axmlrpc/src/main/java source.dir=src:submodules/linphone/mediastreamer2/java/src:submodules/linphone/java/j2se:submodules/linphone/java/common:submodules/linphone/java/impl:submodules/linphone/coreapi/help/java:submodules/externals/axmlrpc/src/main/java
key.store=bc-android.keystore key.store=bc-android.keystore
key.alias=nw8000 key.alias=nw8000
version.name=2.4.0

View file

@ -26,8 +26,9 @@
application and should be checked into Version Control Systems. application and should be checked into Version Control Systems.
--> -->
<property file="ant.properties" />
<property file="default.properties" /> <property file="default.properties" />
<property file="ant.properties" />
<property file="ant_password.properties" />
<!-- if sdk.dir was not set from one of the property file, then <!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var. get it from the ANDROID_HOME env var.

View file

@ -1,5 +1,7 @@
package org.linphone.tester; package org.linphone.tester;
import java.util.List;
import org.linphone.core.LinphoneCoreFactory; import org.linphone.core.LinphoneCoreFactory;
import org.linphone.mediastream.Version; import org.linphone.mediastream.Version;
@ -23,25 +25,35 @@ public class Tester {
} }
static { static {
List<String> cpuabis=Version.getCpuAbis();
LinphoneCoreFactory.instance(); String ffmpegAbi;
boolean libLoaded=false;
System.loadLibrary("cunit"); Throwable firstException=null;
String eabi = "armeabi"; for (String abi : cpuabis){
if (Version.isX86()) { Log.i("LinphoneCoreFactoryImpl","Trying to load liblinphone for " + abi);
eabi = "x86"; ffmpegAbi=abi;
} else if (Version.isArmv7()) { // FFMPEG (audio/video)
eabi = "armeabi-v7a"; if (abi.startsWith("armeabi")) {
ffmpegAbi="arm";
}
loadOptionalLibrary("ffmpeg-linphone-"+ffmpegAbi);
//Main library
try {
System.loadLibrary("linphone-" + abi);
Log.i("LinphoneCoreFactoryImpl","Loading done with " + abi);
libLoaded=true;
break;
}catch(Throwable e) {
if (firstException == null) firstException=e;
}
} }
try {
System.loadLibrary("linphone_tester-"+eabi); if (!libLoaded){
throw new RuntimeException(firstException);
} catch (UnsatisfiedLinkError ule) {
Log.w("linphone", "Failed to load liblinphone_tester-"+eabi); }else{
System.loadLibrary("linphone_tester"); Version.dumpCapabilities();
} }
Version.dumpCapabilities();
} }
public native int run(String args[]); public native int run(String args[]);

View file

@ -78,35 +78,51 @@
android:singleLine="true" android:singleLine="true"
android:textColor="@android:color/black" android:textColor="@android:color/black"
android:background="@drawable/setup_field_background" /> android:background="@drawable/setup_field_background" />
<EditText <ImageView
android:textCursorDrawable="@null" android:contentDescription="@string/content_description_setup_ok"
android:id="@+id/setup_password_confirm" android:id="@+id/setup_password_ok"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/setup_password" android:paddingRight="5dp"
android:hint="@string/setup_password_confirm_hint" android:layout_alignParentRight="true"
android:singleLine="true" android:layout_centerVertical="true"
android:lines="1" android:src="@drawable/wizard_notok"/>
android:maxLines="1"
android:inputType="textPassword"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:ellipsize="end"
android:textColor="@android:color/black"
android:background="@drawable/setup_field_background" />
<ImageView
android:contentDescription="@string/content_description_setup_ok"
android:id="@+id/setup_password_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/wizard_notok"/>
</RelativeLayout> </RelativeLayout>
<RelativeLayout
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:textCursorDrawable="@null"
android:id="@+id/setup_password_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/setup_password_confirm_hint"
android:singleLine="true"
android:lines="1"
android:maxLines="1"
android:inputType="textPassword"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:ellipsize="end"
android:textColor="@android:color/black"
android:background="@drawable/setup_field_background" />
<ImageView
android:contentDescription="@string/content_description_setup_ok"
android:id="@+id/setup_confirm_password_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/wizard_notok"/>
</RelativeLayout>
<RelativeLayout <RelativeLayout
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
@ -159,13 +175,7 @@
android:textColor="@android:color/black"/> android:textColor="@android:color/black"/>
</RelativeLayout> </RelativeLayout>
<View </LinearLayout>
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:paddingRight="10dp" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -16,7 +16,7 @@
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="75dp">
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -33,7 +33,7 @@
android:paddingLeft="20dp" android:paddingLeft="20dp"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="22dp" /> android:textSize="22dp" />
</RelativeLayout> </RelativeLayout>
<LinearLayout <LinearLayout

View file

@ -13,7 +13,7 @@
<string name="notification_registered">مُسجَّل في %s</string> <string name="notification_registered">مُسجَّل في %s</string>
<string name="notification_register_failure">فشِل التسجيل في %s</string> <string name="notification_register_failure">فشِل التسجيل في %s</string>
<string name="about_text">لِنْفُونْ %s الهاتف الموافق لـ SIP (rfc 3261) برخصة جْنُو العمومية الإصدار 2</string> <string name="about_text">لِنْفُونْ %s الهاتف الموافق لـ SIP (rfc 3261) برخصة جْنُو العمومية الإصدار 2</string>
<string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications</string>
<string name="setup_welcome">سيمكنك هذا المرشد من إعداد حسابك SIP لإجراء المكالمات.</string> <string name="setup_welcome">سيمكنك هذا المرشد من إعداد حسابك SIP لإجراء المكالمات.</string>
<string name="setup_create_account">إنشاء حساب في linphone.org</string> <string name="setup_create_account">إنشاء حساب في linphone.org</string>
<string name="setup_login_linphone">أتوفر على حساب في linphone.org</string> <string name="setup_login_linphone">أتوفر على حساب في linphone.org</string>

View file

@ -13,7 +13,7 @@
<string name="notification_registered">Enregistré sur %s</string> <string name="notification_registered">Enregistré sur %s</string>
<string name="notification_register_failure">Échec d\'enregistrement sur %s</string> <string name="notification_register_failure">Échec d\'enregistrement sur %s</string>
<string name="about_text">Linphone %s SIP (rfc 3261) compatible téléphone, sous licence GNU Public License V2</string> <string name="about_text">Linphone %s SIP (rfc 3261) compatible téléphone, sous licence GNU Public License V2</string>
<string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications</string>
<string name="setup_welcome">Cet assistant va vous guider pour réaliser des appels à l\'aide d\'un compte SIP.</string> <string name="setup_welcome">Cet assistant va vous guider pour réaliser des appels à l\'aide d\'un compte SIP.</string>
<string name="setup_create_account">Créer un compte sur linphone.org</string> <string name="setup_create_account">Créer un compte sur linphone.org</string>
<string name="setup_login_linphone">J\'ai déjà un compte sur linphone.org</string> <string name="setup_login_linphone">J\'ai déjà un compte sur linphone.org</string>

View file

@ -13,7 +13,7 @@
<string name="notification_registered">%s に登録しました</string> <string name="notification_registered">%s に登録しました</string>
<string name="notification_register_failure">%s への登録に失敗しました</string> <string name="notification_register_failure">%s への登録に失敗しました</string>
<string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2</string> <string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2</string>
<string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications</string>
<string name="setup_welcome">アシスタントがSIPアカウントを使ってあなたの通話を助けます。</string> <string name="setup_welcome">アシスタントがSIPアカウントを使ってあなたの通話を助けます。</string>
<string name="setup_create_account">linphone.orgのアカウントを作成する</string> <string name="setup_create_account">linphone.orgのアカウントを作成する</string>
<string name="setup_login_linphone">linphone.orgのアカウントをすでに持っている</string> <string name="setup_login_linphone">linphone.orgのアカウントをすでに持っている</string>

View file

@ -13,7 +13,7 @@
<string name="notification_registered">Geregistreerd naar %s</string> <string name="notification_registered">Geregistreerd naar %s</string>
<string name="notification_register_failure">Het registreren naar %s is mislukt</string> <string name="notification_register_failure">Het registreren naar %s is mislukt</string>
<string name="about_text">Linphone %s SIP (rfc 3261)-compatibele telefoonapp onder de licentie van GNU Public License V2</string> <string name="about_text">Linphone %s SIP (rfc 3261)-compatibele telefoonapp onder de licentie van GNU Public License V2</string>
<string name="about_link">http://www.linphone.org\n\nGebruikershandleidingen\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_link">http://www.linphone.org\n\nGebruikershandleidingen\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications</string>
<string name="setup_welcome">Deze wizard zal u helpen bij het gebruiken van een SIP-account voor uw oproepen.</string> <string name="setup_welcome">Deze wizard zal u helpen bij het gebruiken van een SIP-account voor uw oproepen.</string>
<string name="setup_create_account">Creëer een account op linphone.org</string> <string name="setup_create_account">Creëer een account op linphone.org</string>
<string name="setup_login_linphone">Ik heb al een linphone.org-account</string> <string name="setup_login_linphone">Ik heb al een linphone.org-account</string>

View file

@ -8,7 +8,7 @@
<string name="notification_registered">Зарегистрирован в %s </string> <string name="notification_registered">Зарегистрирован в %s </string>
<string name="notification_register_failure">Ошибка регистрации в %s</string> <string name="notification_register_failure">Ошибка регистрации в %s</string>
<string name="about_text">Linphone %s SIP (rfc 3261) совместимый телефон под GPL V2 лицензией</string> <string name="about_text">Linphone %s SIP (rfc 3261) совместимый телефон под GPL V2 лицензией</string>
<string name="about_link">http://www.linphone.org\n\nИнструкции\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_link">http://www.linphone.org\n\nИнструкции\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications</string>
<string name="setup_welcome">Этот помощник поможет Вам настроить учётную запись SIP для звонков.</string> <string name="setup_welcome">Этот помощник поможет Вам настроить учётную запись SIP для звонков.</string>
<string name="setup_create_account">Создать учётную запись на linphone.org</string> <string name="setup_create_account">Создать учётную запись на linphone.org</string>
<string name="setup_login_linphone">Уже есть учётная запись на linphone.org</string> <string name="setup_login_linphone">Уже есть учётная запись на linphone.org</string>

View file

@ -13,7 +13,7 @@
<string name="notification_registered">Уписан на „%s“ </string> <string name="notification_registered">Уписан на „%s“ </string>
<string name="notification_register_failure">Нисам успео да се упишем на „%s“</string> <string name="notification_register_failure">Нисам успео да се упишем на „%s“</string>
<string name="about_text">Линфон %s телефон сагласан са СИП-ом (rfc 3261) под Гнуовом Јавном Лиценцом и2</string> <string name="about_text">Линфон %s телефон сагласан са СИП-ом (rfc 3261) под Гнуовом Јавном Лиценцом и2</string>
<string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications</string>
<string name="setup_welcome">Овај помоћник ће вам помоћи да користите СИП налог за ваше позиве.</string> <string name="setup_welcome">Овај помоћник ће вам помоћи да користите СИП налог за ваше позиве.</string>
<string name="setup_create_account">Направи налог на линфон.орг-у</string> <string name="setup_create_account">Направи налог на линфон.орг-у</string>
<string name="setup_login_linphone">Већ имам налог линфон.орг-а</string> <string name="setup_login_linphone">Већ имам налог линфон.орг-а</string>

View file

@ -17,7 +17,7 @@
<string name="notification_registered">Registered to %s </string> <string name="notification_registered">Registered to %s </string>
<string name="notification_register_failure">Fails to register to %s</string> <string name="notification_register_failure">Fails to register to %s</string>
<string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2</string> <string name="about_text">Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2</string>
<string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications</string> <string name="about_link">http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications</string>
<string name="setup_welcome">This assistant will help you to use a SIP account for your calls.</string> <string name="setup_welcome">This assistant will help you to use a SIP account for your calls.</string>
<string name="setup_create_account">Create an account on linphone.org</string> <string name="setup_create_account">Create an account on linphone.org</string>

View file

@ -33,7 +33,7 @@
<bool name="hide_accounts">false</bool> <bool name="hide_accounts">false</bool>
<bool name="display_account_wizard_at_first_start">true</bool> <bool name="display_account_wizard_at_first_start">true</bool>
<bool name="use_linphone_server_ports">true</bool> <bool name="use_linphone_server_ports">true</bool>
<bool name="allow_only_phone_numbers_in_wizard">true</bool> <bool name="allow_only_phone_numbers_in_wizard">false</bool>
<bool name="use_android_native_contact_edit_interface">false</bool> <bool name="use_android_native_contact_edit_interface">false</bool>
<!-- The following settings are only usefull if use_android_native_contact_edit_interface = false --> <!-- The following settings are only usefull if use_android_native_contact_edit_interface = false -->

View file

@ -2,7 +2,7 @@
<account-authenticator <account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="org.linphone" android:accountType="@string/sync_account_type"
android:icon="@drawable/logo_linphone_57x57" android:icon="@drawable/logo_linphone_57x57"
android:smallIcon="@drawable/logo_linphone_57x57" android:smallIcon="@drawable/logo_linphone_57x57"
android:label="@string/app_name"/> android:label="@string/app_name"/>

View file

@ -20,11 +20,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
/** /**
* @author Margaux Clerc * @author Margaux Clerc
*/ */
public class ChatActivity extends FragmentActivity { public class ChatActivity extends FragmentActivity {
private static final String CHAT_FRAGMENT = "chatFragment";
private ChatFragment chatFragment;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -39,6 +43,17 @@ public class ChatActivity extends FragmentActivity {
ChatFragment fragment = new ChatFragment(); ChatFragment fragment = new ChatFragment();
fragment.setArguments(extras); fragment.setArguments(extras);
getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, fragment, "ChatFragment").commit(); getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, fragment, "ChatFragment").commit();
FragmentManager fm = getSupportFragmentManager();
chatFragment = (ChatFragment) fm.findFragmentByTag(CHAT_FRAGMENT);
// If the Fragment is non-null, then it is currently being
// retained across a configuration change.
if (chatFragment == null) {
chatFragment = new ChatFragment();
chatFragment.setArguments(extras);
fm.beginTransaction().add(R.id.fragmentContainer, chatFragment, CHAT_FRAGMENT).commit();
}
} }
} }

View file

@ -124,6 +124,9 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
instance = this; instance = this;
View view = inflater.inflate(R.layout.chat, container, false); View view = inflater.inflate(R.layout.chat, container, false);
// Retain the fragment across configuration changes
setRetainInstance(true);
//Retrieve parameter from intent //Retrieve parameter from intent
sipUri = getArguments().getString("SipUri"); sipUri = getArguments().getString("SipUri");
@ -438,12 +441,16 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
LinphoneService.instance().removeMessageNotification(); LinphoneService.instance().removeMessageNotification();
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().updateChatFragment(null);
}
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) { if (lc != null) {
lc.removeListener(mListener); lc.removeListener(mListener);
} }
getActivity().getIntent().putExtra("messageDraft", message.getText().toString()); onSaveInstanceState(getArguments());
super.onPause(); super.onPause();
} }
@ -462,6 +469,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) { if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
LinphoneActivity.instance().hideStatusBar(); LinphoneActivity.instance().hideStatusBar();
} }
LinphoneActivity.instance().updateChatFragment(this);
} }
String draft = getArguments().getString("messageDraft"); String draft = getArguments().getString("messageDraft");
@ -557,7 +565,9 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
@Override @Override
protected void onPostExecute(byte[] result) { protected void onPostExecute(byte[] result) {
progressDialog.dismiss(); if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
mUploadingImageStream = new ByteArrayInputStream(result); mUploadingImageStream = new ByteArrayInputStream(result);

View file

@ -47,7 +47,7 @@ public class ChatStorage {
private static final int OUTGOING = 0; private static final int OUTGOING = 0;
private static final int READ = 1; private static final int READ = 1;
private static final int NOT_READ = 0; private static final int NOT_READ = 0;
private static ChatStorage instance; private static ChatStorage instance;
private Context context; private Context context;
private SQLiteDatabase db; private SQLiteDatabase db;
@ -66,7 +66,7 @@ public class ChatStorage {
instance.close(); instance.close();
instance = new ChatStorage(LinphoneService.instance().getApplicationContext()); instance = new ChatStorage(LinphoneService.instance().getApplicationContext());
} }
private boolean isVersionUsingNewChatStorage() { private boolean isVersionUsingNewChatStorage() {
try { try {
return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode >= 2200; return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode >= 2200;
@ -75,7 +75,7 @@ public class ChatStorage {
} }
return true; return true;
} }
private ChatStorage(Context c) { private ChatStorage(Context c) {
context = c; context = c;
boolean useLinphoneStorage = c.getResources().getBoolean(R.bool.use_linphone_chat_storage); boolean useLinphoneStorage = c.getResources().getBoolean(R.bool.use_linphone_chat_storage);
@ -84,24 +84,24 @@ public class ChatStorage {
updateNeeded = updateNeeded && !isVersionUsingNewChatStorage(); updateNeeded = updateNeeded && !isVersionUsingNewChatStorage();
useNativeAPI = useLinphoneStorage && !updateNeeded; useNativeAPI = useLinphoneStorage && !updateNeeded;
Log.d("Using native API: " + useNativeAPI); Log.d("Using native API: " + useNativeAPI);
if (!useNativeAPI) { if (!useNativeAPI) {
ChatHelper chatHelper = new ChatHelper(context); ChatHelper chatHelper = new ChatHelper(context);
db = chatHelper.getWritableDatabase(); db = chatHelper.getWritableDatabase();
} }
} }
public void close() { public void close() {
if (!useNativeAPI) { if (!useNativeAPI) {
db.close(); db.close();
} }
} }
public void updateMessageStatus(String to, String message, int status) { public void updateMessageStatus(String to, String message, int status) {
if (useNativeAPI) { if (useNativeAPI) {
return; return;
} }
String[] whereArgs = { String.valueOf(OUTGOING), to, message }; String[] whereArgs = { String.valueOf(OUTGOING), to, message };
Cursor c = db.query(TABLE_NAME, null, "direction LIKE ? AND remoteContact LIKE ? AND message LIKE ?", whereArgs, null, null, "id DESC"); Cursor c = db.query(TABLE_NAME, null, "direction LIKE ? AND remoteContact LIKE ? AND message LIKE ?", whereArgs, null, null, "id DESC");
@ -114,29 +114,29 @@ public class ChatStorage {
} }
} }
c.close(); c.close();
if (id != null && id.length() > 0) { if (id != null && id.length() > 0) {
int intID = Integer.parseInt(id); int intID = Integer.parseInt(id);
updateMessageStatus(to, intID, status); updateMessageStatus(to, intID, status);
} }
} }
public void updateMessageStatus(String to, int id, int status) { public void updateMessageStatus(String to, int id, int status) {
if (useNativeAPI) { if (useNativeAPI) {
return; return;
} }
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put("status", status); values.put("status", status);
db.update(TABLE_NAME, values, "id LIKE " + id, null); db.update(TABLE_NAME, values, "id LIKE " + id, null);
} }
public int saveTextMessage(String from, String to, String message, long time) { public int saveTextMessage(String from, String to, String message, long time) {
if (useNativeAPI) { if (useNativeAPI) {
return -1; return -1;
} }
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
if (from.equals("")) { if (from.equals("")) {
values.put("localContact", from); values.put("localContact", from);
@ -155,12 +155,12 @@ public class ChatStorage {
values.put("time", time); values.put("time", time);
return (int) db.insert(TABLE_NAME, null, values); return (int) db.insert(TABLE_NAME, null, values);
} }
public int saveImageMessage(String from, String to, Bitmap image, String url, long time) { public int saveImageMessage(String from, String to, Bitmap image, String url, long time) {
if (useNativeAPI) { if (useNativeAPI) {
return -1; return -1;
} }
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
if (from.equals("")) { if (from.equals("")) {
values.put("localContact", from); values.put("localContact", from);
@ -176,73 +176,73 @@ public class ChatStorage {
values.put("status", LinphoneChatMessage.State.Idle.toInt()); values.put("status", LinphoneChatMessage.State.Idle.toInt());
} }
values.put("url", url); values.put("url", url);
if (image != null) { if (image != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(CompressFormat.JPEG, 100, baos); image.compress(CompressFormat.JPEG, 100, baos);
values.put("image", baos.toByteArray()); values.put("image", baos.toByteArray());
} }
values.put("time", time); values.put("time", time);
return (int) db.insert(TABLE_NAME, null, values); return (int) db.insert(TABLE_NAME, null, values);
} }
public void saveImage(int id, Bitmap image) { public void saveImage(int id, Bitmap image) {
if (useNativeAPI) { if (useNativeAPI) {
//Handled before this point //Handled before this point
return; return;
} }
if (image == null) if (image == null)
return; return;
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(CompressFormat.JPEG, 100, baos); image.compress(CompressFormat.JPEG, 100, baos);
values.put("image", baos.toByteArray()); values.put("image", baos.toByteArray());
db.update(TABLE_NAME, values, "id LIKE " + id, null); db.update(TABLE_NAME, values, "id LIKE " + id, null);
} }
public int saveDraft(String to, String message) { public int saveDraft(String to, String message) {
if (useNativeAPI) { if (useNativeAPI) {
//TODO //TODO
return -1; return -1;
} }
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put("remoteContact", to); values.put("remoteContact", to);
values.put("message", message); values.put("message", message);
return (int) db.insert(DRAFT_TABLE_NAME, null, values); return (int) db.insert(DRAFT_TABLE_NAME, null, values);
} }
public void updateDraft(String to, String message) { public void updateDraft(String to, String message) {
if (useNativeAPI) { if (useNativeAPI) {
//TODO //TODO
return; return;
} }
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put("message", message); values.put("message", message);
db.update(DRAFT_TABLE_NAME, values, "remoteContact LIKE \"" + to + "\"", null); db.update(DRAFT_TABLE_NAME, values, "remoteContact LIKE \"" + to + "\"", null);
} }
public void deleteDraft(String to) { public void deleteDraft(String to) {
if (useNativeAPI) { if (useNativeAPI) {
//TODO //TODO
return; return;
} }
db.delete(DRAFT_TABLE_NAME, "remoteContact LIKE \"" + to + "\"", null); db.delete(DRAFT_TABLE_NAME, "remoteContact LIKE \"" + to + "\"", null);
} }
public String getDraft(String to) { public String getDraft(String to) {
if (useNativeAPI) { if (useNativeAPI) {
//TODO //TODO
return ""; return "";
} }
Cursor c = db.query(DRAFT_TABLE_NAME, null, "remoteContact LIKE \"" + to + "\"", null, null, null, "id ASC"); Cursor c = db.query(DRAFT_TABLE_NAME, null, "remoteContact LIKE \"" + to + "\"", null, null, null, "id ASC");
String message = null; String message = null;
@ -254,13 +254,13 @@ public class ChatStorage {
} }
} }
c.close(); c.close();
return message; return message;
} }
public List<String> getDrafts() { public List<String> getDrafts() {
List<String> drafts = new ArrayList<String>(); List<String> drafts = new ArrayList<String>();
if (useNativeAPI) { if (useNativeAPI) {
//TODO //TODO
} else { } else {
@ -276,16 +276,16 @@ public class ChatStorage {
} }
c.close(); c.close();
} }
return drafts; return drafts;
} }
public List<ChatMessage> getMessages(String correspondent) { public List<ChatMessage> getMessages(String correspondent) {
List<ChatMessage> chatMessages = new ArrayList<ChatMessage>(); List<ChatMessage> chatMessages = new ArrayList<ChatMessage>();
if (!useNativeAPI) { if (!useNativeAPI) {
Cursor c = db.query(TABLE_NAME, null, "remoteContact LIKE \"" + correspondent + "\"", null, null, null, "id ASC"); Cursor c = db.query(TABLE_NAME, null, "remoteContact LIKE \"" + correspondent + "\"", null, null, null, "id ASC");
while (c.moveToNext()) { while (c.moveToNext()) {
try { try {
String message, timestamp, url; String message, timestamp, url;
@ -297,7 +297,7 @@ public class ChatStorage {
byte[] rawImage = c.getBlob(c.getColumnIndex("image")); byte[] rawImage = c.getBlob(c.getColumnIndex("image"));
int read = c.getInt(c.getColumnIndex("read")); int read = c.getInt(c.getColumnIndex("read"));
url = c.getString(c.getColumnIndex("url")); url = c.getString(c.getColumnIndex("url"));
ChatMessage chatMessage = new ChatMessage(id, message, rawImage, timestamp, direction == INCOMING, status, read == READ); ChatMessage chatMessage = new ChatMessage(id, message, rawImage, timestamp, direction == INCOMING, status, read == READ);
chatMessage.setUrl(url); chatMessage.setUrl(url);
chatMessages.add(chatMessage); chatMessages.add(chatMessage);
@ -311,26 +311,26 @@ public class ChatStorage {
LinphoneChatMessage[] history = room.getHistory(); LinphoneChatMessage[] history = room.getHistory();
for (int i = 0; i < history.length; i++) { for (int i = 0; i < history.length; i++) {
LinphoneChatMessage message = history[i]; LinphoneChatMessage message = history[i];
Bitmap bm = null; Bitmap bm = null;
String url = message.getExternalBodyUrl(); String url = message.getExternalBodyUrl();
if (url != null && !url.startsWith("http")) { if (url != null && !url.startsWith("http")) {
bm = BitmapFactory.decodeFile(url); bm = BitmapFactory.decodeFile(url);
} }
ChatMessage chatMessage = new ChatMessage(i+1, message.getText(), bm, ChatMessage chatMessage = new ChatMessage(i+1, message.getText(), bm,
String.valueOf(message.getTime()), !message.isOutgoing(), String.valueOf(message.getTime()), !message.isOutgoing(),
message.getStatus().toInt(), message.isRead()); message.getStatus().toInt(), message.isRead());
chatMessage.setUrl(url); chatMessage.setUrl(url);
chatMessages.add(chatMessage); chatMessages.add(chatMessage);
} }
} }
return chatMessages; return chatMessages;
} }
public String getTextMessageForId(LinphoneChatRoom chatroom, int id) { public String getTextMessageForId(LinphoneChatRoom chatroom, int id) {
String message = null; String message = null;
if (useNativeAPI) { if (useNativeAPI) {
LinphoneChatMessage[] history = chatroom.getHistory(); LinphoneChatMessage[] history = chatroom.getHistory();
for (LinphoneChatMessage msg : history) { for (LinphoneChatMessage msg : history) {
@ -341,7 +341,7 @@ public class ChatStorage {
} }
} else { } else {
Cursor c = db.query(TABLE_NAME, null, "id LIKE " + id, null, null, null, null); Cursor c = db.query(TABLE_NAME, null, "id LIKE " + id, null, null, null, null);
if (c.moveToFirst()) { if (c.moveToFirst()) {
try { try {
message = c.getString(c.getColumnIndex("message")); message = c.getString(c.getColumnIndex("message"));
@ -351,10 +351,10 @@ public class ChatStorage {
} }
c.close(); c.close();
} }
return message; return message;
} }
public LinphoneChatMessage getMessage(LinphoneChatRoom chatroom, int id) { public LinphoneChatMessage getMessage(LinphoneChatRoom chatroom, int id) {
if (useNativeAPI) { if (useNativeAPI) {
LinphoneChatMessage[] history = chatroom.getHistory(); LinphoneChatMessage[] history = chatroom.getHistory();
@ -366,7 +366,7 @@ public class ChatStorage {
} }
return null; return null;
} }
public void removeDiscussion(String correspondent) { public void removeDiscussion(String correspondent) {
if (useNativeAPI) { if (useNativeAPI) {
LinphoneChatRoom chatroom = LinphoneManager.getLc().getOrCreateChatRoom(correspondent); LinphoneChatRoom chatroom = LinphoneManager.getLc().getOrCreateChatRoom(correspondent);
@ -375,30 +375,29 @@ public class ChatStorage {
db.delete(TABLE_NAME, "remoteContact LIKE \"" + correspondent + "\"", null); db.delete(TABLE_NAME, "remoteContact LIKE \"" + correspondent + "\"", null);
} }
} }
public ArrayList<String> getChatList() { public ArrayList<String> getChatList() {
ArrayList<String> chatList = new ArrayList<String>(); ArrayList<String> chatList = new ArrayList<String>();
if (useNativeAPI) { if (useNativeAPI) {
LinphoneChatRoom[] chats = LinphoneManager.getLc().getChatRooms(); LinphoneChatRoom[] chats = LinphoneManager.getLc().getChatRooms();
List<LinphoneChatRoom> rooms = new ArrayList<LinphoneChatRoom>(); List<LinphoneChatRoom> rooms = new ArrayList<LinphoneChatRoom>();
for (LinphoneChatRoom chatroom : chats) { for (LinphoneChatRoom chatroom : chats) {
if (chatroom.getHistory(1).length > 0) { if (chatroom.getHistory(1).length > 0) {
rooms.add(chatroom); rooms.add(chatroom);
} }
} }
if (rooms.size() > 1) { if (rooms.size() > 1) {
Collections.sort(rooms, new Comparator<LinphoneChatRoom>() { Collections.sort(rooms, new Comparator<LinphoneChatRoom>() {
@Override @Override
public int compare(LinphoneChatRoom a, LinphoneChatRoom b) { public int compare(LinphoneChatRoom a, LinphoneChatRoom b) {
LinphoneChatMessage[] messagesA = a.getHistory(1); LinphoneChatMessage[] messagesA = a.getHistory(1);
LinphoneChatMessage[] messagesB = b.getHistory(1); LinphoneChatMessage[] messagesB = b.getHistory(1);
long atime, btime; long atime = messagesA[0].getTime();
// /!\ Warning: Have to take the second element because it returns two even when asking for only one... long btime = messagesB[0].getTime();
atime = messagesA.length > 1 ? messagesA[1].getTime() : messagesA[0].getTime();
btime = messagesA.length > 1 ? messagesB[1].getTime() : messagesB[0].getTime();
if (atime > btime) if (atime > btime)
return -1; return -1;
else if (btime > atime) else if (btime > atime)
@ -408,7 +407,7 @@ public class ChatStorage {
} }
}); });
} }
for (LinphoneChatRoom chatroom : rooms) { for (LinphoneChatRoom chatroom : rooms) {
chatList.add(chatroom.getPeerAddress().asStringUriOnly()); chatList.add(chatroom.getPeerAddress().asStringUriOnly());
} }
@ -423,7 +422,7 @@ public class ChatStorage {
} }
c.close(); c.close();
} }
return chatList; return chatList;
} }
@ -440,7 +439,7 @@ public class ChatStorage {
db.delete(TABLE_NAME, "id LIKE " + id, null); db.delete(TABLE_NAME, "id LIKE " + id, null);
} }
} }
public void markMessageAsRead(int id) { public void markMessageAsRead(int id) {
if (!useNativeAPI) { if (!useNativeAPI) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
@ -448,13 +447,13 @@ public class ChatStorage {
db.update(TABLE_NAME, values, "id LIKE " + id, null); db.update(TABLE_NAME, values, "id LIKE " + id, null);
} }
} }
public void markConversationAsRead(LinphoneChatRoom chatroom) { public void markConversationAsRead(LinphoneChatRoom chatroom) {
if (useNativeAPI) { if (useNativeAPI) {
chatroom.markAsRead(); chatroom.markAsRead();
} }
} }
public int getUnreadMessageCount() { public int getUnreadMessageCount() {
int count; int count;
if (!useNativeAPI) { if (!useNativeAPI) {
@ -489,10 +488,10 @@ public class ChatStorage {
//Handled before this point //Handled before this point
return null; return null;
} }
String[] columns = { "image" }; String[] columns = { "image" };
Cursor c = db.query(TABLE_NAME, columns, "id LIKE " + id + "", null, null, null, null); Cursor c = db.query(TABLE_NAME, columns, "id LIKE " + id + "", null, null, null, null);
if (c.moveToFirst()) { if (c.moveToFirst()) {
byte[] rawImage = c.getBlob(c.getColumnIndex("image")); byte[] rawImage = c.getBlob(c.getColumnIndex("image"));
c.close(); c.close();
@ -504,20 +503,20 @@ public class ChatStorage {
} }
class ChatHelper extends SQLiteOpenHelper { class ChatHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 15; private static final int DATABASE_VERSION = 15;
private static final String DATABASE_NAME = "linphone-android"; private static final String DATABASE_NAME = "linphone-android";
ChatHelper(Context context) { ChatHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
} }
@Override @Override
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, image BLOB, url TEXT, time NUMERIC, read INTEGER, status INTEGER);"); db.execSQL("CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, image BLOB, url TEXT, time NUMERIC, read INTEGER, status INTEGER);");
db.execSQL("CREATE TABLE " + DRAFT_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, remoteContact TEXT NOT NULL, message TEXT);"); db.execSQL("CREATE TABLE " + DRAFT_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, remoteContact TEXT NOT NULL, message TEXT);");
} }
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + ";"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + ";");
@ -525,4 +524,4 @@ public class ChatStorage {
onCreate(db); onCreate(db);
} }
} }
} }

View file

@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.linphone.compatibility.Compatibility; import org.linphone.compatibility.Compatibility;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneFriend; import org.linphone.core.LinphoneFriend;
import android.content.ContentResolver; import android.content.ContentResolver;
@ -104,10 +105,13 @@ public class Contact implements Serializable {
public void refresh(ContentResolver cr) { public void refresh(ContentResolver cr) {
this.numbersOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr); this.numbersOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr);
for(LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) { LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (friend.getRefKey().equals(id)) { if(lc != null && lc.getFriendList() != null) {
hasFriends = true; for (LinphoneFriend friend :lc.getFriendList()){
this.numbersOrAddresses.add(friend.getAddress().asStringUriOnly()); if (friend.getRefKey().equals(id)) {
hasFriends = true;
this.numbersOrAddresses.add(friend.getAddress().asStringUriOnly());
}
} }
} }
this.name = Compatibility.refreshContactName(cr, id); this.name = Compatibility.refreshContactName(cr, id);

View file

@ -79,8 +79,9 @@ public class ContactFragment extends Fragment implements OnClickListener {
private OnClickListener chatListener = new OnClickListener() { private OnClickListener chatListener = new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (LinphoneActivity.isInstanciated()) if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayChat(v.getTag().toString()); LinphoneActivity.instance().displayChat(v.getTag().toString());
}
} }
}; };
@ -147,6 +148,7 @@ public class ContactFragment extends Fragment implements OnClickListener {
v.findViewById(R.id.start_chat).setOnClickListener(chatListener); v.findViewById(R.id.start_chat).setOnClickListener(chatListener);
LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig(); LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
if (lpc != null) { if (lpc != null) {
displayednumberOrAddress = lpc.normalizePhoneNumber(displayednumberOrAddress);
if (!displayednumberOrAddress.startsWith("sip:")) { if (!displayednumberOrAddress.startsWith("sip:")) {
numberOrAddress = "sip:" + displayednumberOrAddress; numberOrAddress = "sip:" + displayednumberOrAddress;
} }

View file

@ -593,9 +593,8 @@ public class ContactsManager {
c.close(); c.close();
return address; return address;
} }
c.close();
} }
c.close();
return null; return null;
} }

View file

@ -199,7 +199,7 @@ public class DialerFragment extends Fragment {
mAddress.setText(intent.getData().getSchemeSpecificPart()); mAddress.setText(intent.getData().getSchemeSpecificPart());
} else { } else {
Uri contactUri = intent.getData(); Uri contactUri = intent.getData();
String address = ContactsManager.getInstance().queryAddressOrNumber(getActivity().getContentResolver(),contactUri); String address = ContactsManager.getInstance().queryAddressOrNumber(LinphoneService.instance().getContentResolver(),contactUri);
if(address != null) { if(address != null) {
mAddress.setText(address); mAddress.setText(address);
} else { } else {

View file

@ -53,8 +53,11 @@ public class EditContactFragment extends Fragment {
isNewContact = false; isNewContact = false;
contactID = Integer.parseInt(contact.getID()); contactID = Integer.parseInt(contact.getID());
contact.refresh(getActivity().getContentResolver()); contact.refresh(getActivity().getContentResolver());
} if (getArguments().getString("NewSipAdress") != null) {
if (getArguments().getString("NewSipAdress") != null) { newSipOrNumberToAdd = getArguments().getString("NewSipAdress");
}
} else if (getArguments().getString("NewSipAdress") != null) {
newSipOrNumberToAdd = getArguments().getString("NewSipAdress"); newSipOrNumberToAdd = getArguments().getString("NewSipAdress");
isNewContact = true; isNewContact = true;
} }
@ -257,7 +260,7 @@ public class EditContactFragment extends Fragment {
if (forceAddNumber) { if (forceAddNumber) {
tempNounoa = new NewOrUpdatedNumberOrAddress(isSip); tempNounoa = new NewOrUpdatedNumberOrAddress(isSip);
} else { } else {
if(isNewContact) { if(isNewContact || newSipOrNumberToAdd != null) {
tempNounoa = new NewOrUpdatedNumberOrAddress(isSip, numberOrAddress); tempNounoa = new NewOrUpdatedNumberOrAddress(isSip, numberOrAddress);
} else { } else {
tempNounoa = new NewOrUpdatedNumberOrAddress(numberOrAddress, isSip); tempNounoa = new NewOrUpdatedNumberOrAddress(numberOrAddress, isSip);

View file

@ -92,6 +92,7 @@ public class InCallActivity extends FragmentActivity implements OnClickListener
private Animation slideOutLeftToRight, slideInRightToLeft, slideInBottomToTop, slideInTopToBottom, slideOutBottomToTop, slideOutTopToBottom; private Animation slideOutLeftToRight, slideInRightToLeft, slideInBottomToTop, slideInTopToBottom, slideOutBottomToTop, slideOutTopToBottom;
private CountDownTimer timer; private CountDownTimer timer;
private boolean isVideoCallPaused = false; private boolean isVideoCallPaused = false;
AcceptCallUpdateDialogFragment callUpdateDialog;
private TableLayout callsList; private TableLayout callsList;
private LayoutInflater inflater; private LayoutInflater inflater;
@ -192,6 +193,8 @@ public class InCallActivity extends FragmentActivity implements OnClickListener
timer = new CountDownTimer(SECONDS_BEFORE_DENYING_CALL_UPDATE, 1000) { timer = new CountDownTimer(SECONDS_BEFORE_DENYING_CALL_UPDATE, 1000) {
public void onTick(long millisUntilFinished) { } public void onTick(long millisUntilFinished) { }
public void onFinish() { public void onFinish() {
if (callUpdateDialog != null)
callUpdateDialog.dismiss();
acceptCallUpdate(false); acceptCallUpdate(false);
} }
}.start(); }.start();
@ -1140,7 +1143,7 @@ public class InCallActivity extends FragmentActivity implements OnClickListener
private void showAcceptCallUpdateDialog() { private void showAcceptCallUpdateDialog() {
FragmentManager fm = getSupportFragmentManager(); FragmentManager fm = getSupportFragmentManager();
AcceptCallUpdateDialogFragment callUpdateDialog = new AcceptCallUpdateDialogFragment(); callUpdateDialog = new AcceptCallUpdateDialogFragment();
callUpdateDialog.show(fm, "Accept Call Update Dialog"); callUpdateDialog.show(fm, "Accept Call Update Dialog");
} }

View file

@ -102,6 +102,7 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
private FragmentsAvailable currentFragment, nextFragment; private FragmentsAvailable currentFragment, nextFragment;
private List<FragmentsAvailable> fragmentsHistory; private List<FragmentsAvailable> fragmentsHistory;
private Fragment dialerFragment, messageListFragment, friendStatusListenerFragment; private Fragment dialerFragment, messageListFragment, friendStatusListenerFragment;
private ChatFragment chatFragment;
private SavedState dialerSavedState; private SavedState dialerSavedState;
private boolean isAnimationDisabled = false, preferLinphoneContacts = false; private boolean isAnimationDisabled = false, preferLinphoneContacts = false;
private OrientationEventListener mOrientationHelper; private OrientationEventListener mOrientationHelper;
@ -177,6 +178,9 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
mListener = new LinphoneCoreListenerBase(){ mListener = new LinphoneCoreListenerBase(){
@Override @Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) { public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
if(!displayChatMessageNotification(message.getFrom().asStringUriOnly())) {
cr.markAsRead();
}
displayMissedChats(getChatStorage().getUnreadMessageCount()); displayMissedChats(getChatStorage().getUnreadMessageCount());
if (messageListFragment != null && messageListFragment.isVisible()) { if (messageListFragment != null && messageListFragment.isVisible()) {
((ChatListFragment) messageListFragment).refresh(); ((ChatListFragment) messageListFragment).refresh();
@ -597,6 +601,16 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
public void displayAbout() { public void displayAbout() {
changeCurrentFragment(FragmentsAvailable.ABOUT, null); changeCurrentFragment(FragmentsAvailable.ABOUT, null);
settings.setSelected(true);
}
public boolean displayChatMessageNotification(String address){
if(chatFragment != null) {
if(chatFragment.getSipUri().equals(address)){
return false;
}
}
return true;
} }
public void displayChat(String sipUri) { public void displayChat(String sipUri) {
@ -641,6 +655,9 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
changeCurrentFragment(FragmentsAvailable.CHATLIST, null); changeCurrentFragment(FragmentsAvailable.CHATLIST, null);
displayChat(sipUri); displayChat(sipUri);
} }
if (messageListFragment != null && messageListFragment.isVisible()) {
((ChatListFragment) messageListFragment).refresh();
}
} else { } else {
Intent intent = new Intent(this, ChatActivity.class); Intent intent = new Intent(this, ChatActivity.class);
intent.putExtra("SipUri", sipUri); intent.putExtra("SipUri", sipUri);
@ -744,6 +761,10 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
} }
public void updateChatFragment(ChatFragment fragment) {
chatFragment = fragment;
}
public void updateChatListFragment(ChatListFragment fragment) { public void updateChatListFragment(ChatListFragment fragment) {
messageListFragment = fragment; messageListFragment = fragment;
} }

View file

@ -717,10 +717,12 @@ public class LinphoneManager implements LinphoneCoreListener {
try { try {
Contact contact = ContactsManager.getInstance().findContactWithAddress(mServiceContext.getContentResolver(),from); Contact contact = ContactsManager.getInstance().findContactWithAddress(mServiceContext.getContentResolver(),from);
if (!mServiceContext.getResources().getBoolean(R.bool.disable_chat__message_notification)) { if (!mServiceContext.getResources().getBoolean(R.bool.disable_chat__message_notification)) {
if(contact != null) { if(LinphoneActivity.isInstanciated() && LinphoneActivity.instance().displayChatMessageNotification(from.asStringUriOnly())) {
LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), contact.getName(), textMessage); if (contact != null) {
} else { LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), contact.getName(), textMessage);
LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), from.getUserName(), textMessage); } else {
LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), from.getUserName(), textMessage);
}
} }
} }
} catch (Exception e) { } catch (Exception e) {

View file

@ -965,8 +965,8 @@ public class LinphonePreferences {
// Advanced settings // Advanced settings
public void setDebugEnabled(boolean enabled) { public void setDebugEnabled(boolean enabled) {
getConfig().setBool("app", "debug", enabled); getConfig().setBool("app", "debug", enabled);
LinphoneCoreFactory.instance().setDebugMode(enabled, getString(R.string.app_name));
LinphoneCoreFactory.instance().enableLogCollection(enabled); LinphoneCoreFactory.instance().enableLogCollection(enabled);
LinphoneCoreFactory.instance().setDebugMode(enabled, getString(R.string.app_name));
} }
public boolean isDebugEnabled() { public boolean isDebugEnabled() {

View file

@ -494,7 +494,7 @@ public final class LinphoneService extends Service {
//MANUFACTURER doesn't exist in android 1.5. //MANUFACTURER doesn't exist in android 1.5.
//sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n"); //sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
sb.append("SDK=").append(Build.VERSION.SDK_INT).append("\n"); sb.append("SDK=").append(Build.VERSION.SDK_INT).append("\n");
sb.append("EABI=").append(Build.CPU_ABI).append("\n"); sb.append("EABI=").append(Version.getCpuAbis().get(0)).append("\n");
Log.i(sb.toString()); Log.i(sb.toString());
} }

View file

@ -50,6 +50,7 @@ public class ApiTwentyOnePlus {
.setSmallIcon(R.drawable.chat_icon_over) .setSmallIcon(R.drawable.chat_icon_over)
.setAutoCancel(true) .setAutoCancel(true)
.setContentIntent(intent) .setContentIntent(intent)
.setDefaults(Notification.DEFAULT_ALL)
.setLargeIcon(contactIcon) .setLargeIcon(contactIcon)
.setCategory(Notification.CATEGORY_MESSAGE) .setCategory(Notification.CATEGORY_MESSAGE)
.setVisibility(Notification.VISIBILITY_PRIVATE) .setVisibility(Notification.VISIBILITY_PRIVATE)

View file

@ -381,8 +381,9 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
back.setVisibility(View.GONE); back.setVisibility(View.GONE);
} }
public void isAccountVerified() { public void isAccountVerified(String username) {
Toast.makeText(this, getString(R.string.setup_account_validated), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.setup_account_validated), Toast.LENGTH_LONG).show();
LinphoneManager.getLcIfManagerNotDestroyedOrNull().refreshRegisters();
launchEchoCancellerCalibration(true); launchEchoCancellerCalibration(true);
} }

View file

@ -59,7 +59,7 @@ public class WizardConfirmFragment extends Fragment {
return view; return view;
} }
private void isAccountVerified(String username) { private void isAccountVerified(final String username) {
final Runnable runNotReachable = new Runnable() { final Runnable runNotReachable = new Runnable() {
public void run() { public void run() {
Toast.makeText(getActivity(), getString(R.string.wizard_server_unavailable), Toast.LENGTH_LONG).show(); Toast.makeText(getActivity(), getString(R.string.wizard_server_unavailable), Toast.LENGTH_LONG).show();
@ -78,7 +78,7 @@ public class WizardConfirmFragment extends Fragment {
Runnable runOk = new Runnable() { Runnable runOk = new Runnable() {
public void run() { public void run() {
SetupActivity.instance().isAccountVerified(); SetupActivity.instance().isAccountVerified(username);
} }
}; };

View file

@ -157,7 +157,8 @@ public class WizardFragment extends Fragment {
private boolean isUsernameCorrect(String username) { private boolean isUsernameCorrect(String username) {
if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) { if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) {
return username.matches("^(\\+)?(\\d-)?(\\d{3}-)?(\\d{3}-)?\\d{4,}$"); LinphoneProxyConfig lpc = LinphoneManager.getLc().createProxyConfig();
return lpc.isPhoneNumber(username);
} else { } else {
return username.matches("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{2,}$"); return username.matches("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{2,}$");
} }

View file

@ -155,8 +155,8 @@ public class Digit extends Button implements AddressAware {
if(id == R.id.Digit1 && lc.getCalls().length == 0){ if(id == R.id.Digit1 && lc.getCalls().length == 0){
String voiceMail = LinphonePreferences.instance().getVoiceMailUri(); String voiceMail = LinphonePreferences.instance().getVoiceMailUri();
mAddress.getEditableText().clear(); mAddress.getEditableText().clear();
mAddress.getEditableText().append(voiceMail);
if(voiceMail != null){ if(voiceMail != null){
mAddress.getEditableText().append(voiceMail);
LinphoneManager.getInstance().newOutgoingCall(mAddress); LinphoneManager.getInstance().newOutgoingCall(mAddress);
} }
return true; return true;

@ -1 +1 @@
Subproject commit 7d27eb87c5dbd530e1c0a95cd0da2e233fb4d6b5 Subproject commit 6fd479005cf9e9be15449cab34717fe17bda6dc5

@ -1 +1 @@
Subproject commit ebe07ed33ef00f8ec133374977a5cadf42044fee Subproject commit 4a4f757f66b02cf8834fd8d7a939bf54b245ad7e

@ -1 +1 @@
Subproject commit 5a0c92bac32d086e176e2b10d13c7fd5bb4c1032 Subproject commit 7a5f881221815f2621e876d3a677840053969d54

View file

@ -4,6 +4,7 @@ import junit.framework.Assert;
import org.linphone.ContactsFragment; import org.linphone.ContactsFragment;
import org.linphone.LinphoneActivity; import org.linphone.LinphoneActivity;
import org.linphone.R;
import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.MediumTest;
@ -34,6 +35,8 @@ public class Contacts extends SampleTest {
solo.clickOnText(iContext.getString(org.linphone.test.R.string.contact_name)); solo.clickOnText(iContext.getString(org.linphone.test.R.string.contact_name));
solo.clickOnText(aContext.getString(org.linphone.R.string.delete_contact)); solo.clickOnText(aContext.getString(org.linphone.R.string.delete_contact));
solo.sleep(1000);
solo.clickOnText(aContext.getString(R.string.button_ok));
Assert.assertFalse(solo.searchText(iContext.getString(org.linphone.test.R.string.contact_name))); Assert.assertFalse(solo.searchText(iContext.getString(org.linphone.test.R.string.contact_name)));
} }
@ -70,6 +73,7 @@ public class Contacts extends SampleTest {
@LargeTest @LargeTest
public void testDEditContactAddSipAddressAndRemoveNumber() { public void testDEditContactAddSipAddressAndRemoveNumber() {
goToContacts(); goToContacts();
solo.clickOnText(aContext.getString(org.linphone.R.string.button_all_contacts));
solo.clickOnText(iContext.getString(org.linphone.test.R.string.contact_name)); solo.clickOnText(iContext.getString(org.linphone.test.R.string.contact_name));
solo.clickOnText(aContext.getString(org.linphone.R.string.button_edit)); solo.clickOnText(aContext.getString(org.linphone.R.string.button_edit));
@ -110,6 +114,8 @@ public class Contacts extends SampleTest {
solo.clickOnText(iContext.getString(org.linphone.test.R.string.contact_name)); solo.clickOnText(iContext.getString(org.linphone.test.R.string.contact_name));
solo.clickOnText(aContext.getString(org.linphone.R.string.delete_contact)); solo.clickOnText(aContext.getString(org.linphone.R.string.delete_contact));
solo.sleep(1000);
solo.clickOnText(aContext.getString(R.string.button_ok));
Assert.assertFalse(solo.searchText(iContext.getString(org.linphone.test.R.string.contact_name))); Assert.assertFalse(solo.searchText(iContext.getString(org.linphone.test.R.string.contact_name)));
} }