From 5b8aeacd864922ffb3923db799e61a1024e25655 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 4 Jan 2021 10:26:19 +0100 Subject: [PATCH 01/32] Add dedicated notification channel for missed calls --- .../compatibility/ApiTwentySixPlus.java | 21 +++++++++++++++++-- .../linphone/compatibility/Compatibility.java | 1 + .../res/values/non_localizable_custom.xml | 1 + app/src/main/res/values/strings.xml | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java index 91b6598a9..b5b8e8ce7 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java @@ -107,6 +107,23 @@ class ApiTwentySixPlus { notificationManager.createNotificationChannel(channel); } + public static void createMissedCallChannel(Context context) { + NotificationManager notificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + // Create missed call notification channel + String id = context.getString(R.string.notification_missed_call_channel_id); + String name = context.getString(R.string.content_title_notification_missed_call); + String description = context.getString(R.string.content_title_notification_missed_call); + NotificationChannel channel = + new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW); + channel.setDescription(description); + channel.setLightColor(context.getColor(R.color.notification_led_color)); + channel.enableLights(true); + channel.enableVibration(true); + channel.setShowBadge(true); + notificationManager.createNotificationChannel(channel); + } + public static Notification createMessageNotification( Context context, Notifiable notif, Bitmap contactIcon, PendingIntent intent) { @@ -262,14 +279,14 @@ class ApiTwentySixPlus { public static Notification createMissedCallNotification( Context context, String title, String text, PendingIntent intent, int count) { return new Notification.Builder( - context, context.getString(R.string.notification_channel_id)) + context, context.getString(R.string.notification_missed_call_channel_id)) .setContentTitle(title) .setContentText(text) .setSmallIcon(R.drawable.call_status_missed) .setAutoCancel(true) .setContentIntent(intent) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE) - .setCategory(Notification.CATEGORY_EVENT) + //.setCategory(Notification.CATEGORY_EVENT) No one really matches "missed call" .setVisibility(Notification.VISIBILITY_PRIVATE) .setPriority(Notification.PRIORITY_HIGH) .setWhen(System.currentTimeMillis()) diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.java b/app/src/main/java/org/linphone/compatibility/Compatibility.java index 587eb8dc8..2749e5cf2 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.java +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.java @@ -71,6 +71,7 @@ public class Compatibility { if (Version.sdkAboveOrEqual(Version.API26_O_80)) { ApiTwentySixPlus.createServiceChannel(context); ApiTwentySixPlus.createMessageChannel(context); + ApiTwentySixPlus.createMissedCallChannel(context); } } diff --git a/app/src/main/res/values/non_localizable_custom.xml b/app/src/main/res/values/non_localizable_custom.xml index 6245f96f5..590768902 100644 --- a/app/src/main/res/values/non_localizable_custom.xml +++ b/app/src/main/res/values/non_localizable_custom.xml @@ -22,6 +22,7 @@ linphone-android@belledonne-communications.com linphone_notification_service_id linphone_notification_id + linphone_notification_missed_call_id true diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b80d51490..018740105 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -644,6 +644,7 @@ Exit conference Linphone service notification Linphone instant messages notifications + Linphone missed calls notifications Group chat room subject Group chat room info Record call From afe2725d59dc8cd2d80dce324b85a8591b42e3e8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 5 Jan 2021 15:34:14 +0100 Subject: [PATCH 02/32] Fixed issue with call video update dialog --- app/src/main/java/org/linphone/call/CallManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/linphone/call/CallManager.java b/app/src/main/java/org/linphone/call/CallManager.java index 87c06a9f9..26587029f 100644 --- a/app/src/main/java/org/linphone/call/CallManager.java +++ b/app/src/main/java/org/linphone/call/CallManager.java @@ -144,6 +144,8 @@ public class CallManager { params.enableVideo(true); core.enableVideoCapture(true); core.enableVideoDisplay(true); + } else { + params.enableVideo(false); } call.acceptUpdate(params); From 042c25ca4532b264805079f9b552c6392f220d90 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 7 Jan 2021 15:16:58 +0100 Subject: [PATCH 03/32] Updated translations --- app/build.gradle | 2 +- .../compatibility/ApiTwentySixPlus.java | 2 +- app/src/main/res/values-ar/strings.xml | 33 ++++ app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-hu/strings.xml | 10 +- app/src/main/res/values-ka/strings.xml | 139 ++++++++++++++++ app/src/main/res/values-zh-rCN/strings.xml | 153 ++++++++++++++++++ app/src/main/res/values-zh-rTW/strings.xml | 6 +- 8 files changed, 336 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 681d9e2b5..ea3d9826f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -81,7 +81,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4300 + versionCode 4311 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java index b5b8e8ce7..8d58f9e71 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentySixPlus.java @@ -286,7 +286,7 @@ class ApiTwentySixPlus { .setAutoCancel(true) .setContentIntent(intent) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE) - //.setCategory(Notification.CATEGORY_EVENT) No one really matches "missed call" + // .setCategory(Notification.CATEGORY_EVENT) No one really matches "missed call" .setVisibility(Notification.VISIBILITY_PRIVATE) .setPriority(Notification.PRIORITY_HIGH) .setWhen(System.currentTimeMillis()) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 066743041..e073c6cea 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -6,15 +6,25 @@ لِنْفُونْ لِنْفُونْ يجري التشغيل + %s متصل + %s فشل في الاتصال لِنْفُونْ أندرويد %s Linphone Core %s + زُر سياسة خصوصيتنا جهات اتصال لِنْفُونْ + أجبْ + الجواب المُرسَل : %s + أنْهِ المكالمة + أجبْ + حدِّد كمقروءة اسم المستخدم معرِّف المستخدم (اختياري) رقم الهاتف + رمز التأكيد + بادِئَة رقم الهاتف الدولي الاسم المعروض كلمة السر تأكيد كلمة السر @@ -26,6 +36,7 @@ إعادة المحاولة إلغاء قبول + افتح استمرار حول رفض @@ -39,12 +50,15 @@ رفض اجتماع الرابط + أ تريد ربط الحساب %s مع رقم هاتفك ؟ ربما لاحقا لاحقا لا حسنا نعم اربط حسابك + هناك تحديث متاح + لا تظهر مجددا ‫الزبون SIP الحر @@ -75,10 +89,12 @@ استخدم حساب SIP اجذب التهيئة البعيدة اجذبْ وطبِّق + الرمز المربع الولوج معايرة مزيل الصدى في طور الإنجاز أدخل اسم الولوج لم يتم تأكيد حسابك بعد. + رمز التأكيد باطل.\nيُرجى إعادة المحاولة. تم تأكيد حسابك. اسم المسخدم أو كلمة السر غير صحيحة أأنت موافق على تنزيل مرماز الفيديو OpenH264 المُقدَّم من طرف شركة Cisco Systems, Inc. ؟ @@ -88,6 +104,7 @@ انتهى تنزيل مرماز الفيديو OpenH264 المُقدَّم من طرف شركة Cisco Systems, Inc. حدث خطأ، حاول لاحقا. انعدام الوصول للخادم، تأكد من اتصالك بالشبكة. + إسم المستخدم هذا محجوز مسبقا. اسم المستخدم غير صحيح. رقم هاتفك غير صحيح. عنوانك الإلكتروني غير صحيح. @@ -106,6 +123,7 @@ \nسيجدك أصدقاؤك بسهولة إن ربطت حسابك برقم هاتفك\\n\nسوف تجد في دفتر عناوينك من يستخدم لِنْفُونْ وسيتمكن أصدقاؤك من الوصول إليك بواسطة لِنْفُونْ كذلك.لِنْفُونْ.\n يمكنك استخدام رقم هاتفي واحد مع حساب لنفون واحد.\n\nإن ربطت رقم هاتفك مع حساب آخر لكنك تود استخدام هذا الحساب، يمكنك ببساطة ربطه مع رقم هاتفك تلقائيا وسيُنقَل هذا الأخير إلى هذا الحساب. + الحساب غير موجود البريد الإلكتروني غير صحيح الحساب موجود مسبقا @@ -120,11 +138,13 @@ رقم الهاتف طويل جدا رقم الهاتف قصير جدا رقم الهاتف غير صحيح + رمز التفعيل باطل كلمة السر قصيرة جدا كلمة السر طويلة جدا فشل في استعلام الخادم. يُرجى إعادة المحاولة لاحقا. النقل غير مدعوم رمز البلد غير صحيح + هناك حرف أو حروف غير صالحة التبضع المحمول شراء بالتبضع محمول @@ -137,6 +157,7 @@ أتود حذف سجل المكالمات المحددة ؟ اليوم اﻷمس + المكالمات لا وجود لأي جهة اتصال في دفتر عناوينك. لا وجود لأي جهة اتصال SIP في دفتر عناوينك. @@ -146,10 +167,16 @@ اﻹسم اللقب المنظمة + ادعُ + أهلا، انضم معي إلى لِنْفُونْ ! يمكنك تنزيله مجانا من %s + اختر جهة الاتصال أو قم بإنشاء واحدة لا وجود لأي محادثة أتود حذف المحادثات المحددة ؟ أتود حذف الرسالة المحددة ؟ + المُراسِل يكتب... + %s يكتب... + %s يكتبون... صغيرة متوسطة كبيرة @@ -159,6 +186,7 @@ اختر المصدر حُفظَت الصورة خطأ، لم تُحفَظ الصورة + يُرجى الانتظار... حدث خطأ أثناء نقل الملف إن الرسالة ليست مُعمَّاة لقد استلمت رسالة مُعمَّاة لم تتمكن من فك تعميتها من %s\nيجب عليك الاتصال بمخاطبك لتبادل مفاتيح ZRTP إذا أردت فك تعمية الرسائل اللاحقة التي ستستلمها. @@ -167,7 +195,12 @@ قد تستلزم معالجة الصور بضع ثوان حسب حجم الملف. قُرِأ سُلِّم + غير مُستلَم + أُرسل أعد اﻹرسال + حدث خطأ خلال فتح هذا الملف. + معلومات + معلومات إضافة إلى جهات الاتصال تنزيل غير مفعلة diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index d9d0c13d3..6fd42de61 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -615,6 +615,7 @@ Disponible gratuitement ici : %s Quitter la conférence Notification de service Linphone Notifications des messages Linphone + Notifications d\'appels Linphone manqués Sujet de la conversation de groupe Informations de la conversation de groupe Enregistrer l\'appel diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 81a1ac525..594290fd9 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -70,7 +70,7 @@ Fiók létrehozása Fiók összekapcsolása Folytatás - A fiók aktiválása + A fiók indítása A konfiguráció befejezése A felhasználói fiókja elkészült. Kérjük, ellenőrizze e-mailjét, hogy érvényesítse a fiókját: Ha ez megtörtént, térjen vissza ide és kattintson a gombra. @@ -125,7 +125,7 @@ Használjon e-mail címet a fiók érvényesítéséhez A telefonszám helyett használja a felhasználónevét és jelszavát Mire fogják használni a telefonszámomat? - \nTelefonszámának köszönhetően barátai könnyebben megtalálják Önt.\n\n A címjegyzékben látni fogja, hogy ki használja a Linphone-t és a barátai tudni fogják, hogy Linphone-on is elérhetik Önt.\n + \nTelefonszámának köszönhetően barátai könnyebben megtalálják Önt.\n\nA címjegyzékben látni fogja, hogy ki használja a Linphone-t és a barátai tudni fogják, hogy Linphone-on is elérhetik Önt.\n \nBarátai könnyebben megtalálják Önt, ha összekapcsolja fiókját a telefonszámával\n\nA címjegyzékben látni fogja, hogy ki használja a Linphone-t, és a barátaid tudni fogják, hogy Linphone-on is elérhetik Önt.\n A telefonszámát csak egy Linphone-fiókkal használhatja.\n\nHa már összekapcsolta telefonszámát egy másik fiókkal, de inkább ezt használja, egyszerűen kapcsolja össze, és a telefonszám önműködően átkerül ebbe a fiókba. Túl sok SMS-t küldtek erre a számra rövid idő alatt. Kérjük, várjon 24 órát, mielőtt újra megpróbálja. @@ -144,7 +144,7 @@ Túl hosszú a telefonszám Túl rövid a telefonszám Érvénytelen telefonszám - Érvénytelen aktiválási kód + Érvénytelen indítási kód Jelszó túl rövid Jelszó túl hosszú Nem sikerült lekérdezni a kiszolgálót. Kérjük, próbálja újra később. @@ -284,7 +284,7 @@ Bejövő hívás Kimenő hívás A hívó be szeretné kapcsolni a videót - Nincs aktív hívás + Nincs jelenlegi hívás Távoli felhasználó várakoztatja a hívását. Hiba történt a hívás elfogadása közben Mond: @@ -466,7 +466,7 @@ Tiltva Kötelező Elsődleges - LIME ZRTP titkosítást igényel. \ LIME aktiválásával automatikusan aktiválja a ZRTP adathordozó titkosítást. + LIME ZRTP titkosítást igényel.\nLIME indításával önműködően indítja a ZRTP adathordozó titkosítást. A bejövő fájlok önműködő letöltése szabályzat Max. méret (bájtban) Soha diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index cc9ed08ff..a492002e9 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -6,15 +6,26 @@ Linphone Linphone მიმდინარეობს გაშვება + %s დაკავშირებულია + %s ვერ დაკავშირდა Linphone Android %s Linphone ბირთვი %s + Linphone SDK %s + ნახეთ ჩვენი პირადი უსაფრთხოების პოლიტიკა linphone კონტაქტები + პასუხი + პასუხის გაგზავნა: %s + დაკიდება + პასუხი + წაკითხულად მონიშვნა მომხმარებლის სახელი User-id (არასავალდებულო) ტელეფონის ნომერი + დადასტურების კოდი + საერთაშორისო ტელეფონის ნომერის პრეფიქსი სახელი პაროლი პრაოლის დასტური @@ -40,6 +51,7 @@ უარყოფა კონფერენცია ბმული + გსურთ მიაბათ ანგარიში %s თქვენს ტელეფონის ნომერს? შესაძლოა მოგვიანებით მოგვიანებით არა @@ -47,6 +59,9 @@ დიახ ანგარიშის მიბმა ხელმისაწვდომია განახლება + აღარ მაჩვენო + დარწმუნებილი ხართ, რომ გსურთ ამ კონტაქტების წაშლა?\nისინი თქვენი ტელეფონიდანაც წაიშელბა! + ჟურნალების ბმული კოპირებულია ბუფერში თავისუფალი SIP კლიენტი @@ -77,24 +92,30 @@ SIP ანგარიშის გამოყენება დაშორებული კონფიგურაციის მიღება გადმოწერა და მიღება + QRკოდი შესვლა მიმდინარეობს ექოს გამაუქმებელის კალიბრაცია შეიყვანეთ თქვენი მომხმარებლის სახელი თქვენი ანგარიში ჯერ არ იქნა დადასტურებული. + დადასტურების კოდი არასწორია.\nსცადეთ თავიდან. თქვენი ანგარიში იქნა დადასტურებული არასწორი მომხმარებლის სახელი ან პაროლი ეთანხმებით Cisco Systems, Inc. მოერ მოწოდებული OpenH264 ვიდეო კოდეკის გადმოწერას? მიმდინარეობს Cisco Systems, Inc. მიერ მოწოდებული OpenH264 ვიდეო კოდეკის გადმოწერა მიმდინარეობს OpenH264-ს გადმოწერა + სანამ შეძლებთ OpenH264 კოდეკის გამოყენებას, უნდა გადატვირთოთ %s. ბოდიში, მოხდა შეცდომა. Cisco Systems, Inc. მიერ მოწოდებული OpenH264 ვიდეო კოდეკის იქნა გადმოწერილი. მოხდა შეცდომა, გთხოვთ, სცადოთ მოგვიანებით. სერვისი მიუეწვდომელია, შეამოწმეთ თქვენი ქსელური კავშირი. + ეს მომხმარებლის სახელი უკვე დაკავებულია. + ტელეფონის ნომერი უკვე გამოიყენება.\nგთხოვთ, აკრიფოთ სხვა ნომერი.\nშეგიძლიათ წაშალოთ თქვენი არსებული ანგარიში, თუ გსურთ თქვენი ტელეფონის ნომრის ისევ გამოყენება. თქვენი მომხმარებლის სახელი არასწორია. თქვენი ტელეფონის ნომერი არასწორია. თქვენი ელფოსტა არასწორია. თქვენი პაროლი არასწორია პაროლები არ ემთხვევა. + თქვენი მომხმარებლის სახელი იქნება %s.\n\nიგი შეიძლება იყოს თქვენს მიერ შეყვანილისგან განსხვავებული, რომ დაემთხვეს მოთხოვნებს.\nეთანხმებით? გთხოვთ, შეიყვანოთ თქვენი მომხმარებლის სახელი და პაროლი დაგავიწყდათ პაროლი? აირჩიეთ ქვეყანა @@ -107,6 +128,8 @@ \nთქვენი ტელეფონის ნომრის დახმარებით, თქვენი მეგობრები შეძლებენ გიპოვონ უფრო მარტივად.\n\nთქვენ დაინახავთ თქვენს მისამართები წიგნში ვინ იყენებს Linphone-ს და თქვენს მეგობრებს ეცოდინებათ, რომ შეუძლიათ ასევე დაგიკავშირდნენ Linphone-ით.\n \nთქვენი მეგობრები გიპოვიან უფრო მარტივად, თუ მიაბამთ თქვენს ანგარიშს თქვენს ტელფონის ნომერზე.\n\nთქვენ დაინახავთ თქვენს მისამართები წიგნში ვინ იყენებს Linphone-ს და თქვენს მეგობრებს ეცოდინებათ, რომ შეუძლიათ ასევე დაგიკავშირდნენ Linphone-ით.\n თქვენ შეგიძლიათ გამოიყენოთ თქვენი ტელეფონის ნომერი მხოლოდ ერთ Linphone ანგარიშთან.\n\nთუ უკვე მიბმული გაქვთ თქვენი ნომერი სხვა ანგარიშზე, მაგრამ გსურთ ამის გამოყენება, უბრალოდ მიაბით იგი ახლა და თქვენი ნომერი იქნება ავტომატურად გადმოტანილი ამ ანგარიშზე. + ნამეტანი ბევრი სმს იყო გამოგზავნილი ამ ნომერზე მოკლე დროის განმავლობაში, სცადეთ თავიდან 24 საათში. + ანგარიში არ არსებობს არასწორი ელფოსტა ანგარიში უკვე არსებობს @@ -121,14 +144,17 @@ ტელეფონის ნომერი ნამეტანი გრძელია ტელეფონის ნომერი ნამეტანი მოკლეა არასწორი ტელეფონის ნომერი + არასწორი აქტივაციის კოდი პაროლი ნამეტანი მოკლეა პაროლი ნამეტანი გრძელია სერვერის გამოკითხვა ვერ მოხერხდა. გთხოვთ, სცადოთ მოგვიანებით ტრანსპორტი არ არის მხარდაჭერილი ქვეყნის კოდი არასწორი + მოიძებნა არასწორი სიმბოლო პროგრამის-შიდა პროგრამის-შიდა შესყიდვა + საცდელ პერიოდს გასდის ვადა %s გამოწერის პერიოდი მთავრდება %s-ს შეიყვანეთ ნომერი ან მისამართი @@ -138,6 +164,7 @@ გსურთ არჩეული ზარების ჟურნალის წაშლა? დღეს გუშინ + ზარები თქვენს მისამართების წიგნში არ არის კონტაქტები თქვენს მისამართების წიგნში არ არის SIP კონტაქტები @@ -147,10 +174,16 @@ სახელი გვარი ორგანიზაცია + მოწვევა + გამარჯობა, შემომიერთდი Linphone-ზე! შეგიძლია გადმოიწერო უფასოდ აქ %s + აირჩიეთ კონტაქტი ან შექმენით ახალი მიმოწერა არ არის გსურთ არჩეული მიმოწერის წაშლა? გსურთ არჩეული შეტყობინების წაშლა? + დაშორებული წერს... + %s წერს... + %s წერენ... პატარა საშუალო დიდი @@ -160,6 +193,7 @@ წყაროს არჩევა სურათი შენახულია შეცდომა, სურათი ვერ შეინახა + გთხოვთ, დაელოდოთ... ფაილისი გზავნის დროს მოხდა შეცდომა ეს შეტყობინება არ არის დაშიფრული თქვენ მიიღეთ დაშიფრული შეტყობინება, რომლის განშიფრვაც %s-დან არ შეგიძლიათ\nუნდა დაუკავშერდეთ თქვენს კორესპონდენტს იმისათვის, რომ გაცვალოთ ZRTP გასაღებები, თუ გსურთ მომავალი მიღებული შეტყობინებების განშიფრვა. @@ -171,6 +205,7 @@ არა მისული გაგზავნილი თავიდან გაგზავნა + ამ ფაილის გახსნისას მოხდა შეცდომა. ინფო ადმინი დაარქვით სახელი ჯგუფს @@ -192,16 +227,57 @@ თქვენ აწი ადმინი ხართ თქვენ აღარ ხართ ადმინი ჩატის ოთახის შექმნა ვერ მოხერხდა + გსურთ ამ საუბრის დატოვება? დატოვება + გსურთ წაშალოთ და დატოვოთ არჩეული საუბრები? მიწოდების სტატუსი + %s-ს მოწყობილობები + საუბრის მოწყობილობები კონტაქტებში დამატება + სასწრაფო შეტყობინება არის \"ბოლო ბოლოში\" დაშიფრული დაცულ საუბარში. შესაძლებელია საუბრის დაცვის დონის გაუმჯობესება მონაწილეთა აუთენტიფიკაციით. ამისათვის, დაურეკეთ კონტაქტს და მიყევით აუთენტიფიკაციის პროცესს. + LIME პირადობის გასაღები შეიცვალა %s-ზე + %s-სთვის აღმოჩენილია კაცი-შუაში თავდასხმა + დაცვის დონე დაიწია %s-ს გამო + მონაწილეთა მაქსიმალური რაოდენობა გადაჭარბებულია %s-თ + მოულოდნელი შემთხვევა %i %s-სთვის + გადმოწერა + აირჩიეთ საუბარი ან შექმენით ახალი + ნდობა უარყოფილია. წამოიწყეთ ზარი აუთენტიფიკაციის პროცეს თავიდან დასაწყებად. + ფაილის გახსნა ვერ მოხერხდა, ამ ფორმატისთვის არცერთი აპლიკაცია არ არის მისაწვდომი. + გადაგზავნილი + ჯგუფის ინფო + საუბრის მოწყობილობები + ეფემერული შეტყობინებები + შეტყობინებების წაშლა + გადაგზავნა + ეფემერული შეტყობინებები + ეს შეტყობინება იქნება წაშლილი ორივე მხარეს, როდესაც იქნება წაკითხული და არჩეული ვადის გასვლის შემდეგ. გათიშულია + 1 წუთი + 1 საათი + 1 დღე + 3 დღე + 1 კვირა + + %d დღე + %d დღე + + თქვენ გათიშეთ ეფემერული შეტყობინებები + თქვენ ჩართეთ ეფემერული შეტყობინებები: %s + ეფემერული შეტყობინებების ვადა: %s + გსურთ ამ შეტყობინების გადაგზავნა ამ ოთახში? + დაკავშირებული + არ არის დაკავშირებული + კავშირი მიმდინარეობს + დაკავშირება ვერ მოხერხდა წაუკითხავი შეტყობინება + გამოსვლა ასისტენტი პარამეტრები + ჩანაწერები შესახებ გასვლა @@ -211,6 +287,9 @@ აქტიური ზარი არ არის თქვენმა მხმობლემა შეაჩერა ზარი ზარის მიღებისას მოხდა შეცდომა + თქმა: + დაადასტურეთ, რომ თქვენი მოსაუბრე ამბობს: + კავშირის უსაფრთხოება SAS დაადასტურეთ წინა SAS კოდი თქვენს მოკავშირესთან უცნობი @@ -231,8 +310,14 @@ ჯიტერის ბუფერი: ენკოდერი: დეკოდერი: + დამკვრელის ფილტრი: + ჩვენების ფილტრი: + ჩაწერის ფილტრი: ზარი + გსურთ არჩეული ზარების ჟურნალის წაშლა? + ჩანაწერი ვერ მოიძებნა + გსურთ არჩეული ჩანაწერების წაშლა? ჟურნალის გაგზავნა ჟურნალის ჩამოგდება @@ -240,6 +325,8 @@ მიმდინარეობს აუდიო ზარი მიმდინარე ზარი შეჩერებულია მიმდინარეობს ზარის ვიდეო ჩაწერა + შემომავალი ზარი + გამავალი ზარი დაწყებულია %i წაუკითხავი შეტყობინება გამოტოვებული ზარი @@ -260,6 +347,7 @@ არაავტორიზებული ქსელის შეცდომა გადმოწერა ვერ მოხერხდა. გთხოვთ, შეამოწმოთ თქვენი ქსელური კავშირი ან სცადოთ მოგვიანებით. + დაშორებული მომარაგების ფროფილის გადმოწერა ან დაყენება ვერ მოხერხდა... დაშორებული პროვიზია გსურთ პროვიზიის URI-ს შეცვლა? @@ -286,6 +374,7 @@ სახელი შეიყვანეთ სახელი (არა სავალდებულო) პრეფიქსი + თქვენი ქვეყნის პრეფიქსი (+-ის გარეშე) ტრანსპორტი UDP TCP @@ -303,6 +392,9 @@ გვირაბი ჰოსტის სახელ პორტი + ორმაგი რეჟიმის ჩართვა + ჰოსტის სახელი (მე-2 სერვერი ორმაგი რეჟიმისთვის) + პორტი (მე-2 სერვერი ორმაგი რეჟიმისთვის) რეჟიმი @@ -313,6 +405,7 @@ არცერთი პარამეტრები + ვიდეოს ჩართვა ხმა ექოს გაუქმება @@ -325,9 +418,12 @@ ვერ მოხერხდა ადაპტიური სიხშირის კონტროლი კოდეკის ბიტრეიტის შეზღუდვა + მიკროფონის ნამატი (დბ-ში) + დაკვრის ნამატი (დბ-ში) კოდეკები ვიდეო + კამერა ვიდეოს გადაფარვა ზარის ვიდეოს გამოჩენა გადაფარვაში, როდესაც იმყოფებით პროგრამის გარეთ წინა კამერის გამოყენება @@ -338,15 +434,30 @@ ვიდეოს წინასწარი პარამეტრები არჩეული ვიდეოს ზომა არჩეული კადრი/წმ + კამერის წინასწარი ხედის ჩვენება ამკრეფში გამტარი უნარის შეზღუდვა კბიტ/წმ-ში კოდეკები + დასწრების ინფორმაცია ნატიურ კონტაქტში + ინფორმაციის იარლიყების ჩასმა Linphone-ს კონტაქტიდან Android-ს ნატიურ კონტაქტებში + კონტაქტი + კონტაქტის ორგანიზაციის ჩვენება + იარლიყის შექმნა გამშვებში ზარი მოწყობილობის რეკვის ხმის გამოყენება + ვიბრირება შემომავალი ზარის რეკვისას შემომავალ პასუხებზე ავტო-პასუხი + ავტო-პასუხის დრო (მილიწამებში) + დია[აზონის შიდა DTMF-ის (RFC2833) გაგზავნა + დიაპაზონის გარე DTMF-ის (SIP INFO) გაგზავნა + ზარის ვადა (წამებში) ხმოვანი ფოსტის URI Linphone-ის გამოყენება ნაგულისხმევი ტელეფონის აპლიკაციად + ადრინდელი მედიის მიღება + \"არ შემაწუხო\"-ს პარამეტრები + ჩვენ გვჭირდება, რომ მოგვცეთ წვდომა \"არ შემაწუხო\"-ს პარამეტრების გამოყენებაზე, რომ სწორად დავრეკოთ (ან არა), მიმდინარე პოლიტიკის მიხედვით + აუცილებებლი მედიის დაშიფრვა ჩატი მიმდინარეობს სერვერის გაზიარება @@ -356,6 +467,17 @@ სავალდებულო არჩეული LIME-ს სჭირდება ZRTP დაშიფრვა.\nLIME-ს აქტივაციით, თქვენ ავტომატურად ააქტიურებთ ZRTP მედიის დაშიფრვას. + შემომავალი ფაილების ავტომატური გადმოწერის პოლიტიკა + მაქს ზომა (ბაიტებში) + არასდროს + ყოველთვის + თუ მაქს ზომაზე მცირეა + ცარიელი ჩატის ოთახების დამალვა + პროქსის კონფიგურაციიდან ამოშლილი ჩატის ოთახების დამალვა + თუ გაქვთ გამოტოვებული ჩატის ოთახები, სცადე ამ პარამეტრის გამორთვა + გადმოწერილი სურათების ჩვენება ნატიურ გალერეაში + სურათები ეფემერულ შეტყობინებებში არ იქნება + ეფემერული შეტყობინებების ჩართვა (ბეტა) ქსელი მხოლოდ WiFi-ს გამოყენება @@ -375,22 +497,31 @@ მედია კოდირება ბიძგი შეტყობინებების ჩართვა IPv6-ის ნებართვა + დაცული ბატარეის აპების პარამეტრები + ეს აპი უნდა იყოს ჩართული, რომ მიიღოს push შეტყობინებები გაფართოებული + ბნელი რეჟიმი დებაგი დებაგი Java-ს ჟურნალის გამოყენება მეგობრების სიის გამოწერა ფონის რეჟიმი + შეტყობინების ჩვენება აპის ცოცხლად შესანარჩუნებლად + Linphone იქნა შეზღუდული ფონზე გამოყენებისგან, გთხოვთ ჯერ მისცეთ უფლება ანიმაციების ჩართვა სერვისის შეტყობინების ჩართვა დაწყება გაშვების დროს შემომავალი ზარის დაკიდება (წამებში) + მოწყობილობის სახელი + ცვლილებები იქნება მიღებული შემდეგ გაშვებაზე დაშორებული პროვიზია Android-ის პროგრამის პარამეტრები + Android-ის შეტყობინებების პარამეტრები პირველადი ანგარიში სახელი მომხმარებლის სახელი + ჟურნალების ატვირთვის სერვერი არ დაარედაკტიროთ, თუ არ იცით, რას აკეთებთ! ხმის ჰაკები @@ -399,10 +530,15 @@ მარშრუტირების API ჰაკის გამოყენება Galaxy S-ს ხმის ჰაკის გამოყენება + აღმოჩენილია კვების შემნახველი! + თითქოს თქვენს მოწყობილობას აქვს კვების შემნახველი. იმისათვის, რომ აპმა მიიღოს ზარები და შეტყობინებეი, როდესაც ფონზეა, push შეტყობინებების გამოყენებით, აპი უნდა იყოს დამატებული თეთრ სიაში. პარამეტრები მოგვიანებით დებაგი + ჟურნალების ჩართვა + ჟურნალების გათიშვა + ჟურნალების გაგზავნა უკან ამკრეფი @@ -475,6 +611,9 @@ ზარის პარამეტრები ხმის მარშრუტი კონფერენციიდან გამოსვლა + Linphone-ის სერვისის შეტყობინება + Linphone-ს სწრაფი შეტყობინებების შეტყობინებები ჯგუფური ჩატის ოთახის თემა ჯგუფური ჩატის ოთახის ინფო + ზარის ჩაწერა diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index fec87751c..7d333fdfd 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -187,10 +187,14 @@ 组织 邀请 您好,在 Linphone 上加入我吧!您可以在 %s 免费下载。 + 选择一个联系人或创建一个新的联系人 无对话 您想删除所选对话吗? 您想删除所选信息吗? + 远程正在写入... + %s 正在写 + %s 正在写 @@ -200,6 +204,7 @@ 选择源 图片已保存 错误,图片保存失败 + 请稍候... 文件传输出错 此消息未加密 您收到了一个加密的消息,但您无法从%s中解密。如果您想要解密之后的消息,需要使用ZRTP密钥。 @@ -208,14 +213,80 @@ 根据文件的大小,处理图像可能需要几秒钟的时间 读取 已发送 + 未交付 + 已发送 重发 + 打开此文件时发生错误。 + 信息 + 管理者 + 为组命名 + 信息 + 管理者 + 参与者 + 离开群组 + 搜索联系人 + 您已加入群组 + 您已离开群组 + %s 已加入 + %s 以离开 + %s 的新设备 + %s 的设备已删除 + 新主题:%s + %s 是管理者 + %s 不再是管理者 + % 1:% 2 + 您现在是管理员 + 您不再是管理员 + 聊天室创建失败 + 你想离开这个对话吗? + 离开 + 是否要删除并保留选定的对话? + + 配送状态 + %s 的设备 + 对话设备 添加联系人 + 即时消息在安全的对话中进行端到端加密。可以通过对参与者进行身份验证来升级对话的安全级别。为此,请致电联系人并按照身份验证过程进行操作。 + %s 的LIME身份密钥已更改 + %s 监测到中间人攻击 + %s 造成安全级别下降 + 参加人数上限超过 %s 人 + 下载 + 选择一个对话或创建一个新的对话 + 信任被拒绝。拨打电话以重新启动身份验证过程。 + 无法打开文件,没有适用于此格式的应用程序。 + 已转发 + 组信息 + 对话设备 + 短暂消息 + 删除信息 + 前进 + 短暂消息 + 读取此消息后和选定的超时后,将在两端删除。 已禁用 + 1 分钟 + 1 小时 + 1 天 + 3 天 + 1周 + + %d 天 + + 您禁用了短暂消息 + 您启用了短暂信息:%s + 短暂信息到期日:%s + 是否要在此会议室转发信息? + 已连接 + 未连接 + 连接正在进行 + 连接失败 未读消息 + 注销 助手 设置 + 录音 关于 退出 @@ -225,6 +296,11 @@ 没有来电 对方已结束电话 来电接通出错 + 说: + 确认您的对话者说: + 通信安全 + SAS + 与您的代理确认之前的 SAS 代码 未知 请提供您配置文件的URL地址 视频 @@ -232,16 +308,25 @@ IP Family: 上传带宽 上传带宽 + 估计下载带宽: ICE connectivity: 发送视频分辨率 接受视频分辨率 + 已发送视频 fps: + 收到的视频 fps: 发送损失率 接收损失率 回音消除校正 编码器: 解码器: + 播放器过滤器: + 显示筛选器: + 捕获过滤器: 电话 + 是否要删除选定的呼叫日志? + 无录音 + 是否要删除选定的录音? 发送日志 清除记录 @@ -249,6 +334,8 @@ 音频调用正在进行 暂停通话 视频捕获调用正在进行 + 来电 + 拨打电话 开始 %i未读消息 未接来电 @@ -256,6 +343,7 @@ 警告:服务未准备 出错 + 文件传输错误 无法从%s建立地址 未知错误 拒接来电 @@ -268,6 +356,7 @@ 未授权 网络错误 下载失败,请检查您的网络连接货稍后再试 + 无法下载或应用远程配置文件... 移除配置文件 您想更换配置文件URI吗? @@ -294,6 +383,7 @@ 显示名 输入显示名(可选) 前缀 + 您所在国家的前缀(不包含 +) 传输 UDP TCP @@ -302,6 +392,7 @@ 更换密码 默认使用 密码已更换 + 允许推送通知 SIP帐户 默认账户 @@ -310,6 +401,9 @@ Tunnel隧道 主机名 端口 + 启用双模式 + 主机名(双模式的第二台服务器) + 端口(双模式的第二台服务器) 模式 @@ -320,6 +414,7 @@ 没有 偏好 + 启用视频 音频 回声消除 @@ -332,9 +427,12 @@ 失败 自适应速率控制 编解码的比特率限制 + 麦克风增益(以 dB 为单位) + 播放增益(以 dB 为单位) 编解码器 视频 + 摄像头 Video overlay 在应用程序外显示视频 使用前置摄像头 @@ -345,14 +443,30 @@ 视频预设 视频尺寸偏好 FPS优先 + 在拨号器上显示相机预览 带宽限制在kbits/s 编解码器 + 本机联系人中的状态信息 + 从 Linphone 联系人插入信息快捷方式到本机 Android 联系人 + 联系人 + 显示联系人组织 + 在启动器中创建快捷方式 聊天 使用手机铃声 + 来电振铃时振动 来电自动回复 + 自动应答时间(以毫秒为单位) + 发送带内 DTMF (RFC2833) + 发送带外 DTMF(SIP 信息) + 呼叫超时(以秒为单位) 语音邮箱URI + 使用 Linphone 作为默认手机应用程序 + 接受早期介质 + 请勿打扰设置 + 我们需要您授予使用 “请勿打扰” 设置的访问权限,以便根据当前政策正确响铃或不响应 + 强制介质加密 聊天 分享服务器 @@ -362,11 +476,26 @@ 强制的 优先 LIME需要ZRTP加密。通过激活LIME,你可以自动激活ZRTP媒体加密 + 自动下载传入文件策略 + 最大(以字节为单位) + 永不 + 总是 + 如果比最大尺寸轻 + 隐藏空聊天室 + 隐藏已删除的代理配置中的聊天室 + 如果您有缺少聊天室,请尝试取消选中此设置 + 使下载的图像在本机图库中可见 + 短暂消息中的图像将不会 + 启用短暂消息(测试版) 网络连接 只使用WiFi 休眠模式 + 眩晕/转向服务器 启用ICE + 启用转弯 + 晕眩/转弯用户名(可选) + 眩晕/转动密码(可选) 启用UPNP 使用随机端口 SIP端口 @@ -377,30 +506,48 @@ 媒介加密 允许推送通知 允许IPv6 + 电池保护应用程序设置 + 必须启用此应用程序才能接收推送通知 高级 + 深色模式 诊断 诊断 + 使用 Java 记录器 订阅朋友列表 后台模式 + 显示通知以使应用保持活动状态 + LINphone 已被限制后台运作,请先授权 允许动画 允许服务通知 在开机时启动 挂断来电 (几秒内) + 设备名称 + 更改将在下次启动时应用 移除配置文件 安卓应用设置 + 安卓通知设置 初始帐户 显示名 用户名 + 日志上传服务器 请勿随意编辑 音频插件 使用特定的模式破解 + 0= 模式 _ 正常(默认值),2= 模式 _ 进入 _ 呼叫 + 使用路由 API 破解 + 使用银河 S 音频破解 + 检测到节电程序! + 似乎您的设备有一个节能程序。为了使应用能够在后台运作推送通知接收来电和消息,应用程序必须被列入白名单。 设置 稍后 诊断 + 启用日志 + 禁用日志 + 发送日志 返回 拨号器 @@ -416,6 +563,7 @@ 添加联系人 新的联系人 聊天 + 退格 聊天 回拨 返回拨号器 @@ -472,4 +620,9 @@ 通话选项 音频路由 退出会话 + Linphone 服务通知 + Linphone 即时简讯通知 + 群聊天室主题 + 群聊天室信息 + 通话录音 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b8841ac07..f904408ca 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -7,7 +7,7 @@ Linphone 啟動中 %s 已連線 - %s 無法連線 + %s 連線失敗 Linphone Android %s Linphone Core %s @@ -58,7 +58,7 @@ 連結你的帳號 有更新可用 不要再次顯示 - 妳確定要刪除這些聯絡人嗎?\n他們也會從您的電話中刪除! + 您確定要刪除這些聯絡人嗎?\n他們將會從您的電話中刪除! 記錄網址已複製到剪貼簿 自由的 SIP 客戶端 @@ -77,7 +77,7 @@ 請輸入您 SIP 網域的使用者名稱與密碼 請提供配置網址 傳輸 - 你的 SIP 位置是 + 你的 SIP 地址是 使用 Linphone 帳號 使用 SIP 帳號 擷取遠端設定 From 2e9c2b716087dca2cbdc8b40e929b585d848829c Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 8 Jan 2021 12:18:46 +0100 Subject: [PATCH 04/32] Show which version and maven repository is used for linphone-sdk --- app/build.gradle | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index ea3d9826f..4ebf6544b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,6 +41,22 @@ task getGitVersion() { project.version = gitVersion } +configurations { + customImpl.extendsFrom(implementation) +} + +task linphoneSdkSource() { + doLast { + configurations.customImpl.getIncoming().each { + it.getResolutionResult().allComponents.each { + if (it.id.getDisplayName().contains("linphone-sdk-android")) { + println 'Linphone SDK used is ' + it.moduleVersion.version + ' from ' + it.properties["repositoryName"] + } + } + } + } +} + ///// Exclude Files ///// def excludeFiles = [] @@ -63,14 +79,17 @@ excludePackage.add('**/LICENSE.txt') repositories { maven { + name "local linphone-sdk maven repository" url file(LinphoneSdkBuildDir + '/maven_repository/') } maven { + name "linphone.org maven repository" url "https://linphone.org/maven_repository" } } project.tasks['preBuild'].dependsOn 'getGitVersion' +project.tasks['preBuild'].dependsOn 'linphoneSdkSource' android { lintOptions { From 880bc7a4095f423c7820e1d9930487a11b02aeea Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 11 Jan 2021 16:04:34 +0100 Subject: [PATCH 05/32] Updated translation + bumped version code --- app/build.gradle | 2 +- app/src/main/res/values-sv/strings.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 4ebf6544b..1443eedd5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4311 + versionCode 4312 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index ab1e9e2df..829e503d4 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -613,6 +613,7 @@ Avsluta konferens Linphone-tjänstavisering Linphone-chattaviseringar + Missade Linphone-samtalsaviseringar Ämne för gruppchattrum Info för gruppchattrum Spela in samtal From dfb499d0734269ddb2fdbc7159f713b9adcce827 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 14 Jan 2021 13:37:55 +0100 Subject: [PATCH 06/32] Fixed push notif issue --- app/src/main/java/org/linphone/assistant/AssistantActivity.java | 2 ++ app/src/main/res/raw/default_assistant_create.rc | 1 + app/src/main/res/raw/linphone_assistant_create.rc | 1 + 3 files changed, 4 insertions(+) diff --git a/app/src/main/java/org/linphone/assistant/AssistantActivity.java b/app/src/main/java/org/linphone/assistant/AssistantActivity.java index a18883829..2f1354963 100644 --- a/app/src/main/java/org/linphone/assistant/AssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/AssistantActivity.java @@ -163,6 +163,8 @@ public abstract class AssistantActivity extends LinphoneGenericActivity LinphoneContext.instance().getNotificationManager().startForeground(); } } + LinphonePreferences.instance() + .setPushNotificationEnabled(!isGenericAccount || useLinphoneDefaultValues); if (proxyConfig == null) { Log.e("[Assistant] Account creator couldn't create proxy config"); diff --git a/app/src/main/res/raw/default_assistant_create.rc b/app/src/main/res/raw/default_assistant_create.rc index 489dfaa24..dc66cd4da 100644 --- a/app/src/main/res/raw/default_assistant_create.rc +++ b/app/src/main/res/raw/default_assistant_create.rc @@ -15,6 +15,7 @@ + 0
diff --git a/app/src/main/res/raw/linphone_assistant_create.rc b/app/src/main/res/raw/linphone_assistant_create.rc index 0c793b49e..f7561ee9b 100644 --- a/app/src/main/res/raw/linphone_assistant_create.rc +++ b/app/src/main/res/raw/linphone_assistant_create.rc @@ -15,6 +15,7 @@ nat_policy_default_values sip.linphone.org sip:conference-factory@sip.linphone.org + 1
stun.linphone.org From f55a029192532506c585da46d52951d3cbf8228a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 21 Jan 2021 14:32:30 +0100 Subject: [PATCH 07/32] Using SDK audio helper instead of app's --- app/build.gradle | 1 + .../java/org/linphone/LinphoneManager.java | 1 - ...CancellerCalibrationAssistantActivity.java | 8 +- .../linphone/call/AndroidAudioManager.java | 505 ++---------------- .../java/org/linphone/call/CallActivity.java | 8 + .../linphone/chat/ChatMessagesFragment.java | 4 + .../linphone/receivers/BluetoothReceiver.java | 145 ----- .../linphone/receivers/HeadsetReceiver.java | 67 --- .../recording/RecordingsActivity.java | 1 - .../settings/AudioSettingsFragment.java | 9 +- 10 files changed, 68 insertions(+), 681 deletions(-) delete mode 100644 app/src/main/java/org/linphone/receivers/BluetoothReceiver.java delete mode 100644 app/src/main/java/org/linphone/receivers/HeadsetReceiver.java diff --git a/app/build.gradle b/app/build.gradle index 1443eedd5..bbac598de 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -187,6 +187,7 @@ dependencies { if (firebaseEnabled()) { implementation 'com.google.firebase:firebase-messaging:19.0.1' } + implementation 'androidx.media:media:1.2.0' implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android:flexbox:1.1.0' diff --git a/app/src/main/java/org/linphone/LinphoneManager.java b/app/src/main/java/org/linphone/LinphoneManager.java index a4c965954..cd49efb0f 100644 --- a/app/src/main/java/org/linphone/LinphoneManager.java +++ b/app/src/main/java/org/linphone/LinphoneManager.java @@ -185,7 +185,6 @@ public class LinphoneManager implements SensorEventListener { if (mCore != null) { if (mCore.getCallsNb() > 0) { mCallManager.acceptCall(call); - mAudioManager.routeAudioToEarPiece(); } } } diff --git a/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java index 0936d7a34..a39dddcb0 100644 --- a/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java @@ -20,9 +20,7 @@ package org.linphone.assistant; import android.Manifest; -import android.content.Context; import android.content.pm.PackageManager; -import android.media.AudioManager; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; @@ -117,13 +115,9 @@ public class EchoCancellerCalibrationAssistantActivity extends AssistantActivity Core core, EcCalibratorStatus status, int delayMs) { if (status == EcCalibratorStatus.InProgress) return; core.removeListener(this); - LinphoneManager.getAudioManager().routeAudioToEarPiece(); goToLinphoneActivity(); - - ((AudioManager) getSystemService(Context.AUDIO_SERVICE)) - .setMode(AudioManager.MODE_NORMAL); } }); - LinphoneManager.getAudioManager().startEcCalibration(); + LinphoneManager.getCore().startEchoCancellerCalibration(); } } diff --git a/app/src/main/java/org/linphone/call/AndroidAudioManager.java b/app/src/main/java/org/linphone/call/AndroidAudioManager.java index fd98f91ea..e6931a2fd 100644 --- a/app/src/main/java/org/linphone/call/AndroidAudioManager.java +++ b/app/src/main/java/org/linphone/call/AndroidAudioManager.java @@ -19,69 +19,29 @@ */ package org.linphone.call; -import static android.media.AudioManager.MODE_RINGTONE; -import static android.media.AudioManager.STREAM_RING; import static android.media.AudioManager.STREAM_VOICE_CALL; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothHeadset; -import android.bluetooth.BluetoothProfile; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.media.AudioManager; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.Vibrator; -import android.provider.Settings; -import android.telephony.TelephonyManager; import android.view.KeyEvent; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.List; -import org.linphone.LinphoneContext; import org.linphone.LinphoneManager; import org.linphone.R; -import org.linphone.compatibility.Compatibility; -import org.linphone.core.Address; +import org.linphone.core.AudioDevice; import org.linphone.core.Call; import org.linphone.core.Core; import org.linphone.core.CoreListenerStub; -import org.linphone.core.EcCalibratorStatus; import org.linphone.core.tools.Log; -import org.linphone.receivers.BluetoothReceiver; -import org.linphone.receivers.HeadsetReceiver; -import org.linphone.settings.LinphonePreferences; public class AndroidAudioManager { private Context mContext; private AudioManager mAudioManager; - private Call mRingingCall; - private MediaPlayer mRingerPlayer; - private final Vibrator mVibrator; - private BluetoothAdapter mBluetoothAdapter; - private BluetoothHeadset mBluetoothHeadset; - private BluetoothReceiver mBluetoothReceiver; - private HeadsetReceiver mHeadsetReceiver; - private boolean mHeadsetReceiverRegistered; - - private boolean mIsRinging; - private boolean mAudioFocused; - private boolean mEchoTesterIsRunning; - private boolean mIsBluetoothHeadsetConnected; - private boolean mIsBluetoothHeadsetScoConnected; + private boolean mEchoTesterIsRunning = false; private CoreListenerStub mListener; public AndroidAudioManager(Context context) { mContext = context; mAudioManager = ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)); - mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); - mEchoTesterIsRunning = false; - mHeadsetReceiverRegistered = false; - - startBluetooth(); mListener = new CoreListenerStub() { @@ -91,36 +51,9 @@ public class AndroidAudioManager { final Call call, final Call.State state, final String message) { - if (state == Call.State.IncomingReceived - || (state == Call.State.IncomingEarlyMedia - && mContext.getResources() - .getBoolean( - R.bool.allow_ringing_while_early_media))) { - // Brighten screen for at least 10 seconds - if (core.getCallsNb() == 1) { - requestAudioFocus(STREAM_RING); - - mRingingCall = call; - startRinging(call.getRemoteAddress()); - // otherwise there is the beep - } - } else if (call == mRingingCall && mIsRinging) { - // previous state was ringing, so stop ringing - stopRinging(); - } - if (state == Call.State.Connected) { if (core.getCallsNb() == 1) { - // It is for incoming calls, because outgoing calls enter - // MODE_IN_COMMUNICATION immediately when they start. - // However, incoming call first use the MODE_RINGING to play the - // local ring. - if (call.getDir() == Call.Dir.Incoming) { - setAudioManagerInCallMode(); - // mAudioManager.abandonAudioFocus(null); - requestAudioFocus(STREAM_VOICE_CALL); - } - if (!mIsBluetoothHeadsetConnected) { + if (!isBluetoothHeadsetConnected()) { if (mContext.getResources().getBoolean(R.bool.isTablet)) { routeAudioToSpeaker(); } else { @@ -130,70 +63,11 @@ public class AndroidAudioManager { routeAudioToEarPiece(); } } - } - // Only register this one when a call is active - - enableHeadsetReceiver(); - } - } else if (state == Call.State.End || state == Call.State.Error) { - if (core.getCallsNb() == 0) { - if (mAudioFocused) { - int res = mAudioManager.abandonAudioFocus(null); - Log.d( - "[Audio Manager] Audio focus released a bit later: " - + (res - == AudioManager - .AUDIOFOCUS_REQUEST_GRANTED - ? "Granted" - : "Denied")); - mAudioFocused = false; - } - - // Only register this one when a call is active - if (mHeadsetReceiver != null && mHeadsetReceiverRegistered) { - Log.i("[Audio Manager] Unregistering headset receiver"); - mContext.unregisterReceiver(mHeadsetReceiver); - mHeadsetReceiverRegistered = false; - } - - TelephonyManager tm = - (TelephonyManager) - mContext.getSystemService( - Context.TELEPHONY_SERVICE); - if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) { - Log.d( - "[Audio Manager] ---AndroidAudioManager: back to MODE_NORMAL"); - mAudioManager.setMode(AudioManager.MODE_NORMAL); - Log.d( - "[Audio Manager] All call terminated, routing back to earpiece"); - routeAudioToEarPiece(); + } else { + routeAudioToBluetooth(); } } } - if (state == Call.State.OutgoingInit) { - // Enter the MODE_IN_COMMUNICATION mode as soon as possible, so that - // ringback is heard normally in earpiece or bluetooth receiver. - setAudioManagerInCallMode(); - requestAudioFocus(STREAM_VOICE_CALL); - if (mIsBluetoothHeadsetConnected) { - routeAudioToBluetooth(); - } - } - - if (state == Call.State.StreamsRunning) { - setAudioManagerInCallMode(); - if (mIsBluetoothHeadsetConnected) { - routeAudioToBluetooth(); - } - } - } - - @Override - public void onEcCalibrationResult( - Core core, EcCalibratorStatus status, int delay_ms) { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - mAudioManager.abandonAudioFocus(null); - Log.i("[Audio Manager] Set audio mode on 'Normal'"); } }; @@ -204,16 +78,6 @@ public class AndroidAudioManager { } public void destroy() { - if (mBluetoothAdapter != null && mBluetoothHeadset != null) { - Log.i("[Audio Manager] [Bluetooth] Closing HEADSET profile proxy"); - mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); - } - - Log.i("[Audio Manager] [Bluetooth] Unegistering bluetooth receiver"); - if (mBluetoothReceiver != null) { - mContext.unregisterReceiver(mBluetoothReceiver); - } - Core core = LinphoneManager.getCore(); if (core != null) { core.removeListener(mListener); @@ -222,10 +86,6 @@ public class AndroidAudioManager { /* Audio routing */ - public void setAudioManagerModeNormal() { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - } - public void routeAudioToEarPiece() { routeAudioToSpeakerHelper(false); } @@ -244,41 +104,17 @@ public class AndroidAudioManager { /* Echo cancellation */ - public void startEcCalibration() { - Core core = LinphoneManager.getCore(); - if (core == null) { - return; - } - - routeAudioToSpeaker(); - setAudioManagerInCallMode(); - Log.i("[Audio Manager] Set audio mode on 'Voice Communication'"); - requestAudioFocus(STREAM_VOICE_CALL); - int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL); - int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL); - mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0); - core.startEchoCancellerCalibration(); - mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0); - } - public void startEchoTester() { Core core = LinphoneManager.getCore(); if (core == null) { return; } - - routeAudioToSpeaker(); - setAudioManagerInCallMode(); - Log.i("[Audio Manager] Set audio mode on 'Voice Communication'"); - requestAudioFocus(STREAM_VOICE_CALL); - int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL); int sampleRate; - mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0); String sampleRateProperty = mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); sampleRate = Integer.parseInt(sampleRateProperty); - core.startEchoTester(sampleRate); mEchoTesterIsRunning = true; + core.startEchoTester(sampleRate); } public void stopEchoTester() { @@ -287,10 +123,8 @@ public class AndroidAudioManager { return; } - mEchoTesterIsRunning = false; core.stopEchoTester(); - routeAudioToEarPiece(); - mAudioManager.setMode(AudioManager.MODE_NORMAL); + mEchoTesterIsRunning = false; Log.i("[Audio Manager] Set audio mode on 'Normal'"); } @@ -309,107 +143,23 @@ public class AndroidAudioManager { return false; } - private void setAudioManagerInCallMode() { - if (mAudioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION) { - Log.w("[Audio Manager] already in MODE_IN_COMMUNICATION, skipping..."); - return; - } - Log.d("[Audio Manager] Mode: MODE_IN_COMMUNICATION"); - - mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - } - - private void requestAudioFocus(int stream) { - if (!mAudioFocused) { - int res = - mAudioManager.requestAudioFocus( - null, stream, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE); - Log.d( - "[Audio Manager] Audio focus requested: " - + (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED - ? "Granted" - : "Denied")); - if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) mAudioFocused = true; - } - } - - private synchronized void startRinging(Address remoteAddress) { - if (!LinphonePreferences.instance().isDeviceRingtoneEnabled()) { - // Enable speaker audio route, linphone library will do the ringing itself automatically - routeAudioToSpeaker(); - return; - } - - boolean doNotDisturbPolicyAllowsRinging = - Compatibility.isDoNotDisturbPolicyAllowingRinging(mContext, remoteAddress); - if (!doNotDisturbPolicyAllowsRinging) { - Log.e("[Audio Manager] Do not ring as Android Do Not Disturb Policy forbids it"); - return; - } - - routeAudioToSpeaker(); - mAudioManager.setMode(MODE_RINGTONE); - - try { - if ((mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE - || mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) - && mVibrator != null - && LinphonePreferences.instance().isIncomingCallVibrationEnabled()) { - Compatibility.vibrate(mVibrator); - } - if (mRingerPlayer == null) { - requestAudioFocus(STREAM_RING); - mRingerPlayer = new MediaPlayer(); - mRingerPlayer.setAudioStreamType(STREAM_RING); - - String ringtone = - LinphonePreferences.instance() - .getRingtone(Settings.System.DEFAULT_RINGTONE_URI.toString()); - try { - if (ringtone.startsWith("content://")) { - mRingerPlayer.setDataSource(mContext, Uri.parse(ringtone)); - } else { - FileInputStream fis = new FileInputStream(ringtone); - mRingerPlayer.setDataSource(fis.getFD()); - fis.close(); - } - } catch (IOException e) { - Log.e(e, "[Audio Manager] Cannot set ringtone"); - } - - mRingerPlayer.prepare(); - mRingerPlayer.setLooping(true); - mRingerPlayer.start(); - } else { - Log.w("[Audio Manager] Already ringing"); - } - } catch (Exception e) { - Log.e(e, "[Audio Manager] Cannot handle incoming call"); - } - mIsRinging = true; - } - - private synchronized void stopRinging() { - if (mRingerPlayer != null) { - mRingerPlayer.stop(); - mRingerPlayer.release(); - mRingerPlayer = null; - } - if (mVibrator != null) { - mVibrator.cancel(); - } - - mIsRinging = false; - } - private void routeAudioToSpeakerHelper(boolean speakerOn) { Log.w("[Audio Manager] Routing audio to " + (speakerOn ? "speaker" : "earpiece")); - if (mIsBluetoothHeadsetScoConnected) { - Log.w("[Audio Manager] [Bluetooth] Disabling bluetooth audio route"); - changeBluetoothSco(false); - } - mAudioManager.setSpeakerphoneOn(speakerOn); + if (LinphoneManager.getCore().getCallsNb() == 0) return; + Call currentCall = LinphoneManager.getCore().getCurrentCall(); + if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; + if (currentCall == null) return; + + for (AudioDevice audioDevice : LinphoneManager.getCore().getAudioDevices()) { + if (speakerOn && audioDevice.getType() == AudioDevice.Type.Speaker) { + currentCall.setOutputAudioDevice(audioDevice); + return; + } else if (!speakerOn && audioDevice.getType() == AudioDevice.Type.Earpiece) { + currentCall.setOutputAudioDevice(audioDevice); + return; + } + } } private void adjustVolume(int i) { @@ -419,7 +169,7 @@ public class AndroidAudioManager { } int stream = STREAM_VOICE_CALL; - if (mIsBluetoothHeadsetScoConnected) { + if (isUsingBluetoothAudioRoute()) { Log.i( "[Audio Manager] Bluetooth is connected, try to change the volume on STREAM_BLUETOOTH_SCO"); stream = 6; // STREAM_BLUETOOTH_SCO, it's hidden... @@ -433,194 +183,45 @@ public class AndroidAudioManager { AudioManager.FLAG_SHOW_UI); } - // Bluetooth - - public synchronized void bluetoothHeadetConnectionChanged(boolean connected) { - mIsBluetoothHeadsetConnected = connected; - mAudioManager.setBluetoothScoOn(connected); - if (LinphoneContext.isReady()) LinphoneManager.getCallManager().refreshInCallActions(); - } - - public synchronized void bluetoothHeadetAudioConnectionChanged(boolean connected) { - mIsBluetoothHeadsetScoConnected = connected; - mAudioManager.setBluetoothScoOn(connected); + public synchronized boolean isUsingBluetoothAudioRoute() { + if (LinphoneManager.getCore().getCallsNb() == 0) return false; + Call currentCall = LinphoneManager.getCore().getCurrentCall(); + if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; + if (currentCall == null) return false; + AudioDevice audioDevice = currentCall.getOutputAudioDevice(); + Log.i("[Audio Manager] Currently used audio device: ", audioDevice.getDeviceName()); + return audioDevice.getType() == AudioDevice.Type.Bluetooth; } public synchronized boolean isBluetoothHeadsetConnected() { - return mIsBluetoothHeadsetConnected; - } - - public synchronized void bluetoothHeadetScoConnectionChanged(boolean connected) { - mIsBluetoothHeadsetScoConnected = connected; - if (LinphoneContext.isReady()) LinphoneManager.getCallManager().refreshInCallActions(); - } - - public synchronized boolean isUsingBluetoothAudioRoute() { - return mIsBluetoothHeadsetScoConnected; + for (AudioDevice audioDevice : LinphoneManager.getCore().getAudioDevices()) { + if (audioDevice.getType() == AudioDevice.Type.Bluetooth + && audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) { + Log.i("[Audio Manager] Found bluetooth device: ", audioDevice.getDeviceName()); + return true; + } + } + return false; } public synchronized void routeAudioToBluetooth() { - if (!isBluetoothHeadsetConnected()) { - Log.w("[Audio Manager] [Bluetooth] No headset connected"); - return; - } - if (mAudioManager.getMode() != AudioManager.MODE_IN_COMMUNICATION) { - Log.w( - "[Audio Manager] [Bluetooth] Changing audio mode to MODE_IN_COMMUNICATION and requesting STREAM_VOICE_CALL focus"); - mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - requestAudioFocus(STREAM_VOICE_CALL); - } - changeBluetoothSco(true); - } + if (LinphoneManager.getCore().getCallsNb() == 0) return; + Call currentCall = LinphoneManager.getCore().getCurrentCall(); + if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; + if (currentCall == null) return; - private synchronized void changeBluetoothSco(final boolean enable) { - // IT WILL TAKE A CERTAIN NUMBER OF CALLS TO EITHER START/STOP BLUETOOTH SCO FOR IT TO WORK - if (enable && mIsBluetoothHeadsetScoConnected) { - Log.i("[Audio Manager] [Bluetooth] SCO already enabled, skipping"); - return; - } else if (!enable && !mIsBluetoothHeadsetScoConnected) { - Log.i("[Audio Manager] [Bluetooth] SCO already disabled, skipping"); - return; - } - - new Thread() { - @Override - public void run() { - Log.i("[Audio Manager] [Bluetooth] SCO start/stop thread started"); - boolean resultAcknowledged; - int retries = 0; - - do { - try { - Thread.sleep(200); - } catch (InterruptedException e) { - Log.e(e); - } - - synchronized (AndroidAudioManager.this) { - if (enable) { - Log.i( - "[Audio Manager] [Bluetooth] Starting SCO: try number " - + retries); - mAudioManager.startBluetoothSco(); - } else { - Log.i( - "[Audio Manager] [Bluetooth] Stopping SCO: try number " - + retries); - mAudioManager.stopBluetoothSco(); - } - resultAcknowledged = isUsingBluetoothAudioRoute() == enable; - retries++; - } - } while (!resultAcknowledged && retries < 10); + for (AudioDevice audioDevice : LinphoneManager.getCore().getAudioDevices()) { + if (audioDevice.getType() == AudioDevice.Type.Bluetooth + && audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) { + Log.i( + "[Audio Manager] Found bluetooth audio device", + audioDevice.getDeviceName(), + ", routing audio to it"); + currentCall.setOutputAudioDevice(audioDevice); + return; } - }.start(); - } - - public void bluetoothAdapterStateChanged() { - if (mBluetoothAdapter.isEnabled()) { - Log.i("[Audio Manager] [Bluetooth] Adapter enabled"); - mIsBluetoothHeadsetConnected = false; - mIsBluetoothHeadsetScoConnected = false; - - BluetoothProfile.ServiceListener bluetoothServiceListener = - new BluetoothProfile.ServiceListener() { - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.HEADSET) { - Log.i("[Audio Manager] [Bluetooth] HEADSET profile connected"); - mBluetoothHeadset = (BluetoothHeadset) proxy; - - List devices = - mBluetoothHeadset.getConnectedDevices(); - if (devices.size() > 0) { - Log.i( - "[Audio Manager] [Bluetooth] A device is already connected"); - bluetoothHeadetConnectionChanged(true); - } - - Log.i("[Audio Manager] [Bluetooth] Registering bluetooth receiver"); - - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); - filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); - filter.addAction( - BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT); - - Intent sticky = - mContext.registerReceiver(mBluetoothReceiver, filter); - Log.i("[Audio Manager] [Bluetooth] Bluetooth receiver registered"); - int state = - sticky.getIntExtra( - AudioManager.EXTRA_SCO_AUDIO_STATE, - AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO connected"); - bluetoothHeadetScoConnectionChanged(true); - } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO disconnected"); - bluetoothHeadetScoConnectionChanged(false); - } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO connecting"); - } else if (state == AudioManager.SCO_AUDIO_STATE_ERROR) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO connection error"); - } else { - Log.w( - "[Audio Manager] [Bluetooth] Bluetooth headset unknown SCO state changed: " - + state); - } - } - } - - public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.HEADSET) { - Log.i("[Audio Manager] [Bluetooth] HEADSET profile disconnected"); - mBluetoothHeadset = null; - mIsBluetoothHeadsetConnected = false; - mIsBluetoothHeadsetScoConnected = false; - } - } - }; - - mBluetoothAdapter.getProfileProxy( - mContext, bluetoothServiceListener, BluetoothProfile.HEADSET); - } else { - Log.w("[Audio Manager] [Bluetooth] Adapter disabled"); } - } - - private void startBluetooth() { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mBluetoothAdapter != null) { - Log.i("[Audio Manager] [Bluetooth] Adapter found"); - if (mAudioManager.isBluetoothScoAvailableOffCall()) { - Log.i("[Audio Manager] [Bluetooth] SCO available off call, continue"); - } else { - Log.w("[Audio Manager] [Bluetooth] SCO not available off call !"); - } - - mBluetoothReceiver = new BluetoothReceiver(); - IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); - mContext.registerReceiver(mBluetoothReceiver, filter); - - bluetoothAdapterStateChanged(); - } - } - - // HEADSET - - private void enableHeadsetReceiver() { - mHeadsetReceiver = new HeadsetReceiver(); - - Log.i("[Audio Manager] Registering headset receiver"); - mContext.registerReceiver( - mHeadsetReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); - mContext.registerReceiver( - mHeadsetReceiver, new IntentFilter(AudioManager.ACTION_HEADSET_PLUG)); - mHeadsetReceiverRegistered = true; + Log.w( + "[Audio Manager] Didn't find any bluetooth audio device, keeping default audio route"); } } diff --git a/app/src/main/java/org/linphone/call/CallActivity.java b/app/src/main/java/org/linphone/call/CallActivity.java index d97f1c803..952a20ee9 100644 --- a/app/src/main/java/org/linphone/call/CallActivity.java +++ b/app/src/main/java/org/linphone/call/CallActivity.java @@ -430,6 +430,14 @@ public class CallActivity extends LinphoneGenericActivity updateButtons(); updateCallsList(); } + + @Override + public void onAudioDevicesListUpdated(@NonNull Core core) { + if (mAudioManager.isBluetoothHeadsetConnected()) { + mAudioManager.routeAudioToBluetooth(); + } + updateButtons(); + } }; mCore = LinphoneManager.getCore(); diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index bd803625a..70718bf9f 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -50,6 +50,7 @@ import android.widget.CheckBox; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.view.menu.MenuBuilder; import androidx.appcompat.view.menu.MenuPopupHelper; import androidx.core.view.inputmethod.InputConnectionCompat; @@ -1210,6 +1211,9 @@ public class ChatMessagesFragment extends Fragment * Chat room callbacks */ + @Override + public void onNewEvent(@NonNull ChatRoom chatRoom, @NonNull EventLog eventLog) {} + @Override public void onChatMessageSent(ChatRoom cr, EventLog event) { ((ChatMessagesGenericAdapter) mChatEventsList.getAdapter()).addToHistory(event); diff --git a/app/src/main/java/org/linphone/receivers/BluetoothReceiver.java b/app/src/main/java/org/linphone/receivers/BluetoothReceiver.java deleted file mode 100644 index 16cbe6b60..000000000 --- a/app/src/main/java/org/linphone/receivers/BluetoothReceiver.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2010-2019 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * 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 3 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, see . - */ -package org.linphone.receivers; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothHeadset; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.media.AudioManager; -import org.linphone.LinphoneManager; -import org.linphone.core.tools.Log; - -public class BluetoothReceiver extends BroadcastReceiver { - public BluetoothReceiver() { - super(); - Log.i("[Bluetooth] Bluetooth receiver created"); - } - - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - Log.i("[Bluetooth] Bluetooth broadcast received"); - - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); - switch (state) { - case BluetoothAdapter.STATE_OFF: - Log.w("[Bluetooth] Adapter has been turned off"); - break; - case BluetoothAdapter.STATE_TURNING_OFF: - Log.w("[Bluetooth] Adapter is being turned off"); - break; - case BluetoothAdapter.STATE_ON: - Log.i("[Bluetooth] Adapter has been turned on"); - LinphoneManager.getAudioManager().bluetoothAdapterStateChanged(); - break; - case BluetoothAdapter.STATE_TURNING_ON: - Log.i("[Bluetooth] Adapter is being turned on"); - break; - case BluetoothAdapter.ERROR: - Log.e("[Bluetooth] Adapter is in error state !"); - break; - default: - Log.w("[Bluetooth] Unknown adapter state: ", state); - break; - } - } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { - int state = - intent.getIntExtra( - BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED); - if (state == BluetoothHeadset.STATE_CONNECTED) { - Log.i("[Bluetooth] Bluetooth headset connected"); - LinphoneManager.getAudioManager().bluetoothHeadetConnectionChanged(true); - } else if (state == BluetoothHeadset.STATE_DISCONNECTED) { - Log.i("[Bluetooth] Bluetooth headset disconnected"); - LinphoneManager.getAudioManager().bluetoothHeadetConnectionChanged(false); - } else { - Log.w("[Bluetooth] Bluetooth headset unknown state changed: " + state); - } - } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { - int state = - intent.getIntExtra( - BluetoothHeadset.EXTRA_STATE, - BluetoothHeadset.STATE_AUDIO_DISCONNECTED); - if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { - Log.i("[Bluetooth] Bluetooth headset audio connected"); - LinphoneManager.getAudioManager().bluetoothHeadetAudioConnectionChanged(true); - } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { - Log.i("[Bluetooth] Bluetooth headset audio disconnected"); - LinphoneManager.getAudioManager().bluetoothHeadetAudioConnectionChanged(false); - } else if (state == BluetoothHeadset.STATE_AUDIO_CONNECTING) { - Log.i("[Bluetooth] Bluetooth headset audio connecting"); - } else { - Log.w("[Bluetooth] Bluetooth headset unknown audio state changed: " + state); - } - } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) { - int state = - intent.getIntExtra( - AudioManager.EXTRA_SCO_AUDIO_STATE, - AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { - Log.i("[Bluetooth] Bluetooth headset SCO connected"); - LinphoneManager.getAudioManager().bluetoothHeadetScoConnectionChanged(true); - } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { - Log.i("[Bluetooth] Bluetooth headset SCO disconnected"); - LinphoneManager.getAudioManager().bluetoothHeadetScoConnectionChanged(false); - } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) { - Log.i("[Bluetooth] Bluetooth headset SCO connecting"); - } else if (state == AudioManager.SCO_AUDIO_STATE_ERROR) { - Log.i("[Bluetooth] Bluetooth headset SCO connection error"); - } else { - Log.w("[Bluetooth] Bluetooth headset unknown SCO state changed: " + state); - } - } else if (action.equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) { - String command = - intent.getStringExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD); - int type = - intent.getIntExtra( - BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE, -1); - - String commandType; - switch (type) { - case BluetoothHeadset.AT_CMD_TYPE_ACTION: - commandType = "AT Action"; - break; - case BluetoothHeadset.AT_CMD_TYPE_READ: - commandType = "AT Read"; - break; - case BluetoothHeadset.AT_CMD_TYPE_TEST: - commandType = "AT Test"; - break; - case BluetoothHeadset.AT_CMD_TYPE_SET: - commandType = "AT Set"; - break; - case BluetoothHeadset.AT_CMD_TYPE_BASIC: - commandType = "AT Basic"; - break; - default: - commandType = "AT Unknown"; - break; - } - Log.i("[Bluetooth] Vendor action " + commandType + " : " + command); - } else { - Log.w("[Bluetooth] Bluetooth unknown action: " + action); - } - } -} diff --git a/app/src/main/java/org/linphone/receivers/HeadsetReceiver.java b/app/src/main/java/org/linphone/receivers/HeadsetReceiver.java deleted file mode 100644 index 07cac4ff4..000000000 --- a/app/src/main/java/org/linphone/receivers/HeadsetReceiver.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2010-2019 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * 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 3 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, see . - */ -package org.linphone.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.media.AudioManager; -import org.linphone.LinphoneManager; -import org.linphone.core.tools.Log; - -public class HeadsetReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (isInitialStickyBroadcast()) { - Log.i("[Headset] Received broadcast from sticky cache, ignoring..."); - return; - } - - String action = intent.getAction(); - if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) { - // This happens when the user plugs a Jack headset to the device for example - // https://developer.android.com/reference/android/media/AudioManager.html#ACTION_HEADSET_PLUG - int state = intent.getIntExtra("state", 0); - String name = intent.getStringExtra("name"); - int hasMicrophone = intent.getIntExtra("microphone", 0); - - if (state == 0) { - Log.i("[Headset] Headset disconnected:" + name); - } else if (state == 1) { - Log.i("[Headset] Headset connected:" + name); - if (hasMicrophone == 1) { - Log.i("[Headset] Headset " + name + " has a microphone"); - } - } else { - Log.w("[Headset] Unknown headset plugged state: " + state); - } - - LinphoneManager.getAudioManager().routeAudioToEarPiece(); - LinphoneManager.getCallManager().refreshInCallActions(); - } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { - // This happens when the user disconnect a headset, so we shouldn't play audio loudly - Log.i("[Headset] Noisy state detected, most probably a headset has been disconnected"); - LinphoneManager.getAudioManager().routeAudioToEarPiece(); - LinphoneManager.getCallManager().refreshInCallActions(); - } else { - Log.w("[Headset] Unknown action: " + action); - } - } -} diff --git a/app/src/main/java/org/linphone/recording/RecordingsActivity.java b/app/src/main/java/org/linphone/recording/RecordingsActivity.java index f1a270d0f..00f4b0e13 100644 --- a/app/src/main/java/org/linphone/recording/RecordingsActivity.java +++ b/app/src/main/java/org/linphone/recording/RecordingsActivity.java @@ -107,7 +107,6 @@ public class RecordingsActivity extends MainActivity hideTopBar(); hideTabBar(); - LinphoneManager.getAudioManager().setAudioManagerModeNormal(); LinphoneManager.getAudioManager().routeAudioToSpeaker(); removeDeletedRecordings(); diff --git a/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java b/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java index 0e6036c88..64b24608d 100644 --- a/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java +++ b/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java @@ -20,9 +20,7 @@ package org.linphone.settings; import android.Manifest; -import android.content.Context; import android.content.pm.PackageManager; -import android.media.AudioManager; import android.os.Bundle; import android.text.InputType; import android.view.LayoutInflater; @@ -274,7 +272,6 @@ public class AudioSettingsFragment extends SettingsFragment { Core core, EcCalibratorStatus status, int delayMs) { if (status == EcCalibratorStatus.InProgress) return; core.removeListener(this); - LinphoneManager.getAudioManager().routeAudioToEarPiece(); if (status == EcCalibratorStatus.DoneNoEcho) { mEchoCalibration.setSubtitle(getString(R.string.no_echo)); @@ -287,12 +284,8 @@ public class AudioSettingsFragment extends SettingsFragment { mEchoCalibration.setSubtitle(getString(R.string.failed)); } mEchoCanceller.setChecked(status != EcCalibratorStatus.DoneNoEcho); - ((AudioManager) - getActivity() - .getSystemService(Context.AUDIO_SERVICE)) - .setMode(AudioManager.MODE_NORMAL); } }); - LinphoneManager.getAudioManager().startEcCalibration(); + LinphoneManager.getCore().startEchoCancellerCalibration(); } } From f5ce0d9cdbf370c07a8227006363c59ea5a1790d Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 21 Jan 2021 16:30:22 +0100 Subject: [PATCH 08/32] Updated translations --- app/build.gradle | 2 +- app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-tr/strings.xml | 59 +++++++++++++------------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index bbac598de..a691b286c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4312 + versionCode 4313 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 8073cebb9..9d347a6c6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -615,6 +615,7 @@ Выйти из конференции Сервисное уведомление Linphone Уведомления мгновенных сообщений Linphone + Уведомления о пропущенных звонках Linphone Тема группового чата Информация о групповом чате Запись звонка diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index f4f426186..7eefbd7cc 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -83,10 +83,10 @@ Linphone hesabı kullan SIP hesabı kullan Uzaktan yapılandırma al - Lütfen ülke kodunuzu doğrulayın ve telefon numaranızı girin - Telefon numaranıza SMS ile bir doğrulama kodu gönderdik: - Telefon numarası doğrulamayı tamamlamak için, lütfen 4 haneli kodu aşağı girin:\n - Lütfen Linphone hesabınız için bir kullanıcı adı, e-posta ve parola girin + Lütfen ülke kodunuzu doğrulayın ve telefon numaranızı girin + Telefon numaranıza SMS ile doğrulama kodu gönderdik: + Telefon numarası doğrulamayı tamamlamak için lütfen 4 haneli kodu aşağı girin:\n + Lütfen Linphone hesabınız için kullanıcı adı, e-posta ve parola girin Görünen ad (isteğe bağlı) Linphone hesabını kullan SIP hesabı kullan @@ -104,10 +104,10 @@ Cisco Systems, Inc. tarafından sağlanan OpenH264 Video çözücüsü indiriliyor. OpenH264 indiriliyor OpenH264 çözücüyü kullanmadan önce %s yeniden başlatılmalı. - Üzgünüz bir hata oluştu. + Üzgünüz hata oluştu. Cisco Systems, Inc. tarafından sağlanan OpenH264 Video çözücüsü indirildi. - Bir hata oluştu, daha sonra yeniden deneyin. - Sunucuya ulaşılamıyor,ağ bağlantınızı kontrol edin. + Hata oluştu, daha sonra yeniden deneyin. + Sunucuya ulaşılamıyor, ağ bağlantınızı gözden geçirin. Bu kullanıcı adı alınmış. Bu telefon numarası zaten kullanılıyor.\nLütfen başka numara girin.\nEğer telefon numaranızı yeniden kullanmak istiyorsanız var olan hesabınızı silebilirsiniz. Kullanıcı adınız geçersiz. @@ -127,7 +127,7 @@ Telefon numaram ne için kullanılacak? \nTelefon numaranız sayesinde arkadaşlarınız sizi daha kolay bulacak.\n\n Adres defterinizde kimlerin Linphone kullandığını göreceksiniz ve arkadaşlarınız da size Linphone\'dan ulaşabileceklerini bilecek.\n \nEğer hesabını telefon numarana bağlarsan arkadaşların seni daha kolay bulacak\n\nAdres listende kimlerin Linphone kullandığını göreceksin ve arkadaşların da sana Linphone üzerinden ulaşabileceğini bilecek.\n - Telefon numaranı yalnızca tek Linphone hesabıyla kullanabilirsin.\n\nEğer hesabını zaten başka bir hesaba bağladıysan ama bunu kullanmak istiyorsan, şimdi bağla ve numaran kendiliğinden bu hesaba taşınsın. + Telefon numaranı yalnızca tek Linphone hesabıyla kullanabilirsin.\n\nEğer hesabını zaten başka hesaba bağladıysan ama bunu kullanmak istiyorsan, şimdi bağla ve numaran kendiliğinden bu hesaba taşınsın. Bu numaraya kısa zamanda birçok SMS gönderildi, 24 saat içinde yeniden deneyin. Hesap yok @@ -192,9 +192,9 @@ Metni kopyalama Kaynak seç Resim kaydedildi - Hata,resim kaydedilmedi + Hata, resim kaydedilmedi Lütfen bekle… - Dosya aktarımı sırasında bir hata oluştu + Dosya aktarımında hata oluştu Bu ileti şifrelenmemiş %s\'den şifresi çözülemeyen bir şifrelenmiş ileti aldınız.\nEğer gelecekte alacağınız iletileri çözmek istiyorsanız, ZRTP anahtarlarınızın değiş tokuşu için eşinizi aramanız gerekiyor. Bu iletinin şifresini çözemezsiniz. @@ -235,7 +235,7 @@ %s aygıtları Konuşmanın aygıtları Bağlantılara ekle - Anlık iletiler, güvenli konuşmalarda uçtan uca şifrelenmiştir. Katılımcıların kimliğini doğrulayarak konuşmanın güvenlik düzeyi artırılabilir. Bunu yapmak için kişiyi arayın ve yetkilendirme sürecini takip edin. + Anlık iletiler, güvenli konuşmalarda uçtan uca şifrelenmiştir. Katılımcıların kimliğini doğrulayarak konuşmanın güvenlik düzeyi artırılabilir. Bunu yapmak için kişiyi arayın ve yetkilendirme sürecini izleyin. %s için LIME kimlik anahtarı değiştirildi %s için Man-in-the-middle saldırısı saptandı %s olduğundan güvenlik düzeyi düşürüldü @@ -272,7 +272,7 @@ Bağlanmadı Bağlantı sürüyor Bağlantı başarısız - okunmamış iletiler + okunmamış ileti Oturumu kapat Yardımcı @@ -286,7 +286,7 @@ Görüştüğünüz kişi görüntüyü açmak istiyor Etkin çağrı yok Görüştüğünüz kişi çağrıyı duraklattı - Gelen aramanın kabulünde bir hata oluştu + Gelen aramanın kabulünde hata oluştu Söyle: Muhatabınızın şunu söylediğini doğrulayın: İletişim güvenliği @@ -299,7 +299,7 @@ IP Ailesi: Karşıya yükleme hızı: İndirme hızı: - Tahmini indirme bant genişliği: + Öngörülen indirme bant genişliği: İCE bağlanılabilirliği: Giden görüntü çözünürlüğü: Alınan görüntü çözünürlüğü: @@ -335,7 +335,7 @@ Uyarı: hizmet hazır değil Hata Dosya aktarım hatası - %s dan gidilecek adres inşa edilemiyor + %s konumundan hedef adres inşa edilemiyor Tanımlanmayan hata Reddedilen çağrı Kullanıcı meşgul @@ -361,12 +361,12 @@ Giden vekil sunucu SIP vekil sunucu makine adı veya ip adresi (isteğe bağlı) Tüm çağrıları SIP vekil sunucuya yönlendir - Eğer hesabınız john@sip.example.org ise örneğin: john - Eğer hesabınız john@sip.example.org ise sip.example.org + Eğer hesabınız inci@sip.ornek.org ise örneğin: inci + Eğer hesabınız inci@sip.ornek.org ise sip.ornek.org Eğer kullanıcı adınızı ve/veya alan adınızı değiştirdiyseniz parolanızı yeniden girmeniz gerekir Süre dolumu AVPF - AVPF düzenli RTCP aralığında ( 1 ile 5 saniye arasında) + Saniye türünde AVPF düzenli RTCP aralığı (1 ile 5 saniye arasında) +\'yı 00 ile değiştir Hesabını bağla Yetkilendirme kullanıcı kimliği @@ -466,12 +466,12 @@ Devre dışı Zorunlu Yeğlenen - LIME, ZRTP şifreleme gerektiriyor.\nLIME\'ı etkinleştirerek ZRTP ortam şifrelemeyi kendiliğinden etkinleştirmiş olacaksınız. + LIME, ZRTP şifreleme gerektiriyor.\nLIME\'ı etkinleştirerek ZRTP ortam şifrelemeyi kendiliğinden etkinleştireceksiniz. Gelen dosyaları kendiliğinden indirme ilkesi Azami boyut (bayt) Asla Daima - Eğer azami boyuttan hafifse + Eğer azami boyuttan azsa Boş konuşma odalarını gizle Kaldırılan vekil yapılandırmalarından olan konuşma odalarını gizle Eğer eksik konuşma odalarınız varsa, bu seçeneğin imini kaldırmayı deneyin @@ -506,13 +506,13 @@ Hata ayıklama Java günlükleyici kullan Arkadaş listesi aboneliği - Artalan kipi + Art alan kipi Uygulamayı uyanık tutmak için bildirim göster Linphone\'un arka plan kullanımı kısıtlandı, lütfen öncelikle yetkilendirin Animasyonlar etkin Hizmet bildirimi etkin Başlangıçta çalıştır - Gelen çağrı kapandı (anında) + Gelen çağrı kapandı (saniye) Aygıt adı Değişiklikler sonraki başlatımda uygulanacak Uzaktan yetkilendirme @@ -524,11 +524,11 @@ Günlük gönderim sunucusu Ne yaptığınızı bilmiyorsanız değiştirmeyin! - Ses kesme - Özgün kesme kipi kullan - 0=NORMAL_KİP (öntanımlı), 2=GELEN_ÇAĞRI_KİPİ - API hack yönlendirmesini kullanın - Galaxy S ses kesmeyi kullan + Ses ayarları + Özgün kip ayarı kullan + 0=MODE_NORMAL (öntanımlı), 2=MODE_IN_CALL + Yönlendirme API\'si ayarını kullan + Galaxy S ses ayarını kullan Güç koruyucu algılandı! Aygıtınızın güç koruyucusu var. Uygulama, anlık bildirimler kullanarak arka planda ileti ve aramaları almak için beyaz listeye eklenmeli. @@ -601,7 +601,7 @@ Soyadı Kuruluş Çağrıya dön - Bir dosya gönder + Dosya gönder Gelen dosya İleti Okunmamış konuşma iletisi @@ -612,7 +612,8 @@ Ses yolu Görüşmeden çık Linphone hizmet bildirimi - Linphone anında iletiler bildirimleri + Linphone anında ileti bildirimleri + Linphone yanıtsız çağrı bildirimleri Küme konuşma odası konusu Küme konuşma odası bilgisi Çağrı kaydet From 8f116a84e48186a4ac95052c2bdda1fb64201307 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 26 Jan 2021 17:13:27 +0100 Subject: [PATCH 09/32] Fixed broken links when only a line break separates the end of the link and the rest of the text --- app/src/main/java/org/linphone/utils/LinphoneUtils.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.java b/app/src/main/java/org/linphone/utils/LinphoneUtils.java index 7b56ac38f..63c52ca65 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.java +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.java @@ -318,7 +318,9 @@ public final class LinphoneUtils { int indexHttp = text.indexOf("http://"); int indexFinHttp = text.indexOf(" ", indexHttp) == -1 - ? text.length() + ? (text.indexOf("
", indexHttp) == -1 + ? text.length() + : text.indexOf("
", indexHttp)) : text.indexOf(" ", indexHttp); String link = text.substring(indexHttp, indexFinHttp); String linkWithoutScheme = link.replace("http://", ""); @@ -331,7 +333,9 @@ public final class LinphoneUtils { int indexHttp = text.indexOf("https://"); int indexFinHttp = text.indexOf(" ", indexHttp) == -1 - ? text.length() + ? (text.indexOf("
", indexHttp) == -1 + ? text.length() + : text.indexOf("
", indexHttp)) : text.indexOf(" ", indexHttp); String link = text.substring(indexHttp, indexFinHttp); String linkWithoutScheme = link.replace("https://", ""); From 3b28d1e57af30769ba1a6e9ee1ccb7d712ae3549 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 27 Jan 2021 10:13:38 +0100 Subject: [PATCH 10/32] Even better solution to properly handle links in messages --- .../linphone/chat/ChatMessageViewHolder.java | 7 ++- .../org/linphone/utils/LinphoneUtils.java | 49 ------------------- 2 files changed, 3 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java b/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java index e1c569981..203e69d2e 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java +++ b/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java @@ -28,8 +28,8 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.CountDownTimer; -import android.text.Spanned; import android.text.method.LinkMovementMethod; +import android.text.util.Linkify; import android.view.LayoutInflater; import android.view.View; import android.webkit.MimeTypeMap; @@ -221,9 +221,8 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi } if (message.hasTextContent()) { - String msg = message.getTextContent(); - Spanned text = LinphoneUtils.getTextWithHttpLinks(msg); - messageText.setText(text); + messageText.setText(message.getTextContent()); + Linkify.addLinks(messageText, Linkify.ALL); messageText.setMovementMethod(LinkMovementMethod.getInstance()); messageText.setVisibility(View.VISIBLE); } diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.java b/app/src/main/java/org/linphone/utils/LinphoneUtils.java index 63c52ca65..09fbd9bb1 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.java +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.java @@ -29,8 +29,6 @@ import android.net.NetworkInfo; import android.os.Handler; import android.os.Looper; import android.telephony.TelephonyManager; -import android.text.Html; -import android.text.Spanned; import android.view.View; import android.view.Window; import android.view.WindowManager; @@ -41,7 +39,6 @@ import androidx.core.content.ContextCompat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; -import java.util.regex.Pattern; import org.linphone.LinphoneContext; import org.linphone.LinphoneManager; import org.linphone.R; @@ -302,52 +299,6 @@ public final class LinphoneUtils { } } - public static Spanned getTextWithHttpLinks(String text) { - if (text == null) return null; - - if (text.contains("<")) { - text = text.replace("<", "<"); - } - if (text.contains(">")) { - text = text.replace(">", ">"); - } - if (text.contains("\n")) { - text = text.replace("\n", "
"); - } - if (text.contains("http://")) { - int indexHttp = text.indexOf("http://"); - int indexFinHttp = - text.indexOf(" ", indexHttp) == -1 - ? (text.indexOf("
", indexHttp) == -1 - ? text.length() - : text.indexOf("
", indexHttp)) - : text.indexOf(" ", indexHttp); - String link = text.substring(indexHttp, indexFinHttp); - String linkWithoutScheme = link.replace("http://", ""); - text = - text.replaceFirst( - Pattern.quote(link), - "" + linkWithoutScheme + ""); - } - if (text.contains("https://")) { - int indexHttp = text.indexOf("https://"); - int indexFinHttp = - text.indexOf(" ", indexHttp) == -1 - ? (text.indexOf("
", indexHttp) == -1 - ? text.length() - : text.indexOf("
", indexHttp)) - : text.indexOf(" ", indexHttp); - String link = text.substring(indexHttp, indexFinHttp); - String linkWithoutScheme = link.replace("https://", ""); - text = - text.replaceFirst( - Pattern.quote(link), - "" + linkWithoutScheme + ""); - } - - return Html.fromHtml(text); - } - public static void showTrustDeniedDialog(Context context) { final Dialog dialog = new Dialog(context); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); From ef9afdcb91189e43a7cdbe2314f461258def8087 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 27 Jan 2021 11:10:01 +0100 Subject: [PATCH 11/32] Fixed message disapearing when using Resend action --- app/src/main/java/org/linphone/chat/ChatMessagesFragment.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index 70718bf9f..ec740d668 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -538,8 +538,6 @@ public class ChatMessagesFragment extends Fragment String messageId = message.getMessageId(); if (item.getItemId() == R.id.resend) { - ((ChatMessagesGenericAdapter) mChatEventsList.getAdapter()) - .removeItem(mContextMenuMessagePosition); message.send(); return true; } From ff98c8580aa5e77d29665a894460bf96cddc3958 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 27 Jan 2021 14:56:21 +0100 Subject: [PATCH 12/32] Fixed some issues related to chat --- .../main/java/org/linphone/chat/ChatMessagesAdapter.java | 8 +++++--- .../main/java/org/linphone/chat/ChatMessagesFragment.java | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesAdapter.java b/app/src/main/java/org/linphone/chat/ChatMessagesAdapter.java index 24dcc5be2..9a17efd3f 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesAdapter.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesAdapter.java @@ -334,9 +334,11 @@ public class ChatMessagesAdapter extends SelectableAdapter logs) { diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index ec740d668..25fe7256c 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -1213,11 +1213,14 @@ public class ChatMessagesFragment extends Fragment public void onNewEvent(@NonNull ChatRoom chatRoom, @NonNull EventLog eventLog) {} @Override - public void onChatMessageSent(ChatRoom cr, EventLog event) { + public void onChatMessageSending(ChatRoom cr, EventLog event) { ((ChatMessagesGenericAdapter) mChatEventsList.getAdapter()).addToHistory(event); scrollToBottom(); } + @Override + public void onChatMessageSent(@NonNull ChatRoom chatRoom, @NonNull EventLog eventLog) {} + @Override public void onConferenceAddressGeneration(ChatRoom cr) {} From 15795cad3065126f9caa8f1daa0c37b770d43c5a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 29 Jan 2021 14:07:43 +0100 Subject: [PATCH 13/32] Allow to check delivery status for incoming messages in group chat rooms --- app/src/main/java/org/linphone/chat/ChatMessagesFragment.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index 25fe7256c..cd04966e0 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -501,8 +501,7 @@ public class ChatMessagesFragment extends Fragment inflater.inflate(R.menu.chat_bubble_menu, menu); } - if (!message.isOutgoing() - || mChatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) { + if (mChatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt())) { // Do not show incoming messages IDMN state in 1 to 1 chat room as we don't receive IMDN // for them menu.removeItem(R.id.imdn_infos); From a8ddc9a49417aa10e5939bcd265561df514cf03d Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 29 Jan 2021 14:17:05 +0100 Subject: [PATCH 14/32] Bumped version & updated italian translation --- app/build.gradle | 2 +- app/src/main/res/values-it/strings.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index a691b286c..3b1be3b72 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4313 + versionCode 4314 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 46d80c357..e4850ce35 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -613,6 +613,7 @@ Esci dalla conferenza Notifica del servizio Linphone Notifiche di messaggi istantanei Linphone + Notifiche di chiamate Linphone perse Oggetto della chat room di gruppo Informazioni sulla chat room di gruppo Registra chiamata From a332334250a2f1808c33e0b13cde77db8ffbf9d2 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 8 Feb 2021 17:51:23 +0100 Subject: [PATCH 15/32] Added checkbox to accept general terms and privacy policy --- .../assistant/MenuAssistantActivity.java | 101 ++++++++++++++++++ .../settings/LinphonePreferences.java | 9 ++ .../main/res/layout-land/assistant_menu.xml | 21 ++++ app/src/main/res/layout/assistant_menu.xml | 21 ++++ app/src/main/res/values/strings.xml | 5 + 5 files changed, 157 insertions(+) diff --git a/app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java b/app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java index 367955124..92b099a4e 100644 --- a/app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/MenuAssistantActivity.java @@ -20,11 +20,22 @@ package org.linphone.assistant; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; import android.view.KeyEvent; import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.linphone.R; import org.linphone.settings.LinphonePreferences; @@ -122,6 +133,8 @@ public class MenuAssistantActivity extends AssistantActivity { PhoneAccountCreationAssistantActivity.class)); finish(); } + + setUpTermsAndPrivacyLinks(); } @Override @@ -158,4 +171,92 @@ public class MenuAssistantActivity extends AssistantActivity { } return super.onKeyDown(keyCode, event); } + + private void setUpTermsAndPrivacyLinks() { + String terms = getString(R.string.assistant_general_terms); + String privacy = getString(R.string.assistant_privacy_policy); + + String label = getString(R.string.assistant_read_and_agree_terms, terms, privacy); + Spannable spannable = new SpannableString(label); + + Matcher termsMatcher = Pattern.compile(terms).matcher(label); + if (termsMatcher.find()) { + ClickableSpan clickableSpan = + new ClickableSpan() { + @Override + public void onClick(@NonNull View widget) { + Intent browserIntent = + new Intent( + Intent.ACTION_VIEW, + Uri.parse( + getString( + R.string + .assistant_general_terms_link))); + startActivity(browserIntent); + } + }; + spannable.setSpan( + clickableSpan, + termsMatcher.start(0), + termsMatcher.end(), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + Matcher privacyMatcher = Pattern.compile(privacy).matcher(label); + if (privacyMatcher.find()) { + ClickableSpan clickableSpan = + new ClickableSpan() { + @Override + public void onClick(@NonNull View widget) { + Intent browserIntent = + new Intent( + Intent.ACTION_VIEW, + Uri.parse( + getString( + R.string + .assistant_privacy_policy_link))); + startActivity(browserIntent); + } + }; + spannable.setSpan( + clickableSpan, + privacyMatcher.start(0), + privacyMatcher.end(), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + TextView termsAndPrivacy = findViewById(R.id.terms_and_privacy); + final CheckBox termsAndPrivacyCheckBox = findViewById(R.id.terms_and_privacy_checkbox); + + termsAndPrivacy.setText(spannable); + termsAndPrivacy.setMovementMethod(new LinkMovementMethod()); + if (LinphonePreferences.instance().getReadAndAgreeTermsAndPrivacy()) { + termsAndPrivacyCheckBox.setEnabled(false); + termsAndPrivacyCheckBox.setChecked(true); + } else { + final TextView accountCreation = findViewById(R.id.account_creation); + final TextView accountConnection = findViewById(R.id.account_connection); + final TextView genericConnection = findViewById(R.id.generic_connection); + final TextView remoteConfiguration = findViewById(R.id.remote_configuration); + accountCreation.setEnabled(false); + accountConnection.setEnabled(false); + genericConnection.setEnabled(false); + remoteConfiguration.setEnabled(false); + + termsAndPrivacyCheckBox.setOnCheckedChangeListener( + new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + LinphonePreferences.instance().setReadAndAgreeTermsAndPrivacy(true); + termsAndPrivacyCheckBox.setEnabled(false); + accountCreation.setEnabled(true); + accountConnection.setEnabled(true); + genericConnection.setEnabled(true); + remoteConfiguration.setEnabled(true); + } + } + }); + } + } } diff --git a/app/src/main/java/org/linphone/settings/LinphonePreferences.java b/app/src/main/java/org/linphone/settings/LinphonePreferences.java index 43e611e33..b946c3333 100644 --- a/app/src/main/java/org/linphone/settings/LinphonePreferences.java +++ b/app/src/main/java/org/linphone/settings/LinphonePreferences.java @@ -203,6 +203,15 @@ public class LinphonePreferences { return ringtone; } + public boolean getReadAndAgreeTermsAndPrivacy() { + if (getConfig() == null) return false; + return getConfig().getBool("app", "read_and_agree_terms_and_privacy", false); + } + + public void setReadAndAgreeTermsAndPrivacy(boolean value) { + getConfig().setBool("app", "read_and_agree_terms_and_privacy", value); + } + // Accounts settings private ProxyConfig getProxyConfig(int n) { if (getLc() == null) return null; diff --git a/app/src/main/res/layout-land/assistant_menu.xml b/app/src/main/res/layout-land/assistant_menu.xml index 1dd2ec3e7..92509cce2 100644 --- a/app/src/main/res/layout-land/assistant_menu.xml +++ b/app/src/main/res/layout-land/assistant_menu.xml @@ -49,6 +49,27 @@ android:layout_height="match_parent" android:columnCount="2"> + + + + + + + + + + + + + + + + You can only use your phone number with one Linphone account.\n\nIf you had already linked your number to an other account but you prefer to use this one, simply link it now and your number will automatically be moved to this account. Too much SMS have been sent to this number in a short period of time, try again in 24 hours. Account doesn\'t exist + https://www.linphone.org/general-terms + https://www.linphone.org/privacy-policy + terms of use + privacy policy + I accept Belledonne Communications\' %1$s and %2$s Invalid email From 217e88ce309164461b1deb4f2285fcc31f8fbdd7 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 9 Feb 2021 11:49:15 +0100 Subject: [PATCH 16/32] Fixed issue while rotating the device during file sharing --- app/src/main/java/org/linphone/chat/ChatMessagesFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index cd04966e0..2b3a9da9f 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -300,6 +300,7 @@ public class ChatMessagesFragment extends Fragment mMessageTextToSend.setText(sharedText); Log.i("[Chat Messages Fragment] Found shared text: " + sharedText); } + getArguments().clear(); } if (savedInstanceState != null) { From 148235f2bb98ec27a3fed3873b2a65240cada9a8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 15 Feb 2021 15:46:55 +0100 Subject: [PATCH 17/32] Fixed empty detail history page --- .../java/org/linphone/history/HistoryDetailFragment.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/src/main/java/org/linphone/history/HistoryDetailFragment.java b/app/src/main/java/org/linphone/history/HistoryDetailFragment.java index 342ca1e8f..a616f98d9 100644 --- a/app/src/main/java/org/linphone/history/HistoryDetailFragment.java +++ b/app/src/main/java/org/linphone/history/HistoryDetailFragment.java @@ -210,13 +210,8 @@ public class HistoryDetailFragment extends Fragment { Core core = LinphoneManager.getCore(); if (address != null && core != null) { address.clean(); - ProxyConfig proxyConfig = core.getDefaultProxyConfig(); CallLog[] logs; - if (proxyConfig != null) { - logs = core.getCallHistory(address, proxyConfig.getIdentityAddress()); - } else { - logs = core.getCallHistoryForAddress(address); - } + logs = core.getCallHistoryForAddress(address); List logsList = Arrays.asList(logs); mLogsList.setAdapter( new HistoryLogAdapter( From 9580befc8a0f34e876b8abab8fdbf8ef507740ef Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 15 Feb 2021 16:12:04 +0100 Subject: [PATCH 18/32] Updated translations & bumped version code --- app/build.gradle | 2 +- app/src/main/res/values-fr/strings.xml | 3 +++ app/src/main/res/values-ru/strings.xml | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3b1be3b72..11df4a072 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4314 + versionCode 4315 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 6fd42de61..868ad493c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -131,6 +131,9 @@ Vos amis pourront vous joindre plus facilement si vous associez votre compte à Vous ne pouvez associer votre numéro qu\'à un seul compte Linphone.\n\nSi vous avez déjà associé votre numéro à un autre compte mais préférez utiliser ce compte-ci, suivez la procédure d\'association et votre numéro sera automatiquement transféré à ce compte. Trop de SMS ont été envoyés vers ce numéro en un court laps de temps, veuillez attendre 24h avant de réessayer. Ce compte n\'existe pas + les conditions d’utilisation + la politique de confidentialité + J’accepte %1$s et %2$s de Belledonne Communications Mail non valide Ce compte existe déjà diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 9d347a6c6..7f741e58a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -130,6 +130,9 @@ Номер телефона можно использовать только с одним аккаунтом Linphone.\n\nЕсли ваш номер уже был связан с другим аккаунтом, но вы предпочитаете использовать его, просто свяжите его сейчас, и ваш номер будет автоматически перенесен в этот аккаунт. Слишком много SMS было отправлено на этот номер за короткий промежуток времени, повторите попытку через 24 часа. Аккаунт не существует + условия использования + политику конфиденциальности + Я принимаю %1$s and %2$s Belledonne Communications\' Недопустимый адрес электронной почты Аккаунт уже существует From 998e069c062d80fb617a65ce3cc82852114266a2 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 2 Mar 2021 15:17:43 +0100 Subject: [PATCH 19/32] Updated translations + bumped version code --- app/build.gradle | 2 +- app/src/main/res/values-it/strings.xml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 11df4a072..ff92bae3b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4315 + versionCode 4316 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index e4850ce35..1dca238b0 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -130,6 +130,9 @@ Puoi utilizzare il tuo numero di telefono solo con un account Linphone.\n\nSe avevi già collegato il tuo numero a un altro account ma preferisci utilizzare questo, collegalo semplicemente ora e il tuo numero verrà automaticamente spostato su questo account. Troppi SMS sono stati inviati a questo numero in un breve periodo di tempo, riprova tra 24 ore. L\'account non esiste + termini di utilizzo + informativa privacy + Accetto %1$s e %2$s di Belledonne Communications E-mail non valida Account già esistente From 2adca8f90f2c4604ef89ed260632e4b5ae84d17b Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 8 Mar 2021 13:54:31 +0100 Subject: [PATCH 20/32] Fixed issue in ChatMessagesFragment after leaving & coming back if Don't Keep Activities setting is enabled --- .../java/org/linphone/chat/ChatMessagesFragment.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index 2b3a9da9f..7496bfae5 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -375,6 +375,9 @@ public class ChatMessagesFragment extends Fragment public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); + outState.putString("LocalSipUri", mChatRoom.getLocalAddress().asStringUriOnly()); + outState.putString("RemoteSipUri", mChatRoom.getPeerAddress().asStringUriOnly()); + ArrayList files = new ArrayList<>(); for (int i = 0; i < mFilesUploadLayout.getChildCount(); i++) { View child = mFilesUploadLayout.getChildAt(i); @@ -715,6 +718,7 @@ public class ChatMessagesFragment extends Fragment || mRemoteSipUri == null || mRemoteSipUri.isEmpty() || core == null) { + Log.e("[Chat Messages Fragment] No local/remote SIP URI found!"); // TODO error return; } @@ -911,6 +915,12 @@ public class ChatMessagesFragment extends Fragment } private void onRestoreInstanceState(Bundle savedInstanceState) { + + String localSipUri = savedInstanceState.getString("LocalSipUri"); + mRemoteSipUri = savedInstanceState.getString("RemoteSipUri"); + mLocalSipAddress = Factory.instance().createAddress(localSipUri); + mRemoteSipAddress = Factory.instance().createAddress(mRemoteSipUri); + ArrayList files = savedInstanceState.getStringArrayList("Files"); if (files != null && !files.isEmpty()) { for (String file : files) { From 68ac6ca680cb612f4b17a6e8f681019427b6ea6c Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 9 Mar 2021 11:24:53 +0100 Subject: [PATCH 21/32] Trying to fix actions in notification not working --- .../compatibility/ApiTwentyEightPlus.java | 3 ++ .../compatibility/ApiTwentyFourPlus.java | 3 ++ .../compatibility/ApiTwentyNinePlus.java | 3 ++ .../linphone/compatibility/Compatibility.java | 1 + .../linphone/notifications/Notifiable.java | 9 ++++ .../NotificationBroadcastReceiver.java | 54 +++++++++++++++---- .../notifications/NotificationsManager.java | 2 + .../settings/LinphonePreferences.java | 4 +- 8 files changed, 67 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java index 932456422..bdc7fc178 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentyEightPlus.java @@ -23,6 +23,7 @@ import static org.linphone.compatibility.Compatibility.CHAT_NOTIFICATIONS_GROUP; import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY; import static org.linphone.compatibility.Compatibility.INTENT_MARK_AS_READ_ACTION; import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID; +import static org.linphone.compatibility.Compatibility.INTENT_REMOTE_IDENTITY; import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION; import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY; @@ -132,6 +133,7 @@ class ApiTwentyEightPlus { replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + replyIntent.putExtra(INTENT_REMOTE_IDENTITY, notif.getRemoteIdentity()); PendingIntent replyPendingIntent = PendingIntent.getBroadcast( @@ -156,6 +158,7 @@ class ApiTwentyEightPlus { markAsReadIntent.setAction(INTENT_MARK_AS_READ_ACTION); markAsReadIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); markAsReadIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + markAsReadIntent.putExtra(INTENT_REMOTE_IDENTITY, notif.getRemoteIdentity()); PendingIntent markAsReadPendingIntent = PendingIntent.getBroadcast( diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java index 54a3812d4..788dd77b8 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentyFourPlus.java @@ -25,6 +25,7 @@ import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_ import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY; import static org.linphone.compatibility.Compatibility.INTENT_MARK_AS_READ_ACTION; import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID; +import static org.linphone.compatibility.Compatibility.INTENT_REMOTE_IDENTITY; import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION; import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY; @@ -167,6 +168,7 @@ class ApiTwentyFourPlus { replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + replyIntent.putExtra(INTENT_REMOTE_IDENTITY, notif.getRemoteIdentity()); PendingIntent replyPendingIntent = PendingIntent.getBroadcast( @@ -190,6 +192,7 @@ class ApiTwentyFourPlus { markAsReadIntent.setAction(INTENT_MARK_AS_READ_ACTION); markAsReadIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); markAsReadIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + markAsReadIntent.putExtra(INTENT_REMOTE_IDENTITY, notif.getRemoteIdentity()); PendingIntent markAsReadPendingIntent = PendingIntent.getBroadcast( diff --git a/app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java b/app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java index d79d05faa..8cee33b34 100644 --- a/app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java +++ b/app/src/main/java/org/linphone/compatibility/ApiTwentyNinePlus.java @@ -24,6 +24,7 @@ import static org.linphone.compatibility.Compatibility.INTENT_HANGUP_CALL_NOTIF_ import static org.linphone.compatibility.Compatibility.INTENT_LOCAL_IDENTITY; import static org.linphone.compatibility.Compatibility.INTENT_MARK_AS_READ_ACTION; import static org.linphone.compatibility.Compatibility.INTENT_NOTIF_ID; +import static org.linphone.compatibility.Compatibility.INTENT_REMOTE_IDENTITY; import static org.linphone.compatibility.Compatibility.INTENT_REPLY_NOTIF_ACTION; import static org.linphone.compatibility.Compatibility.KEY_TEXT_REPLY; @@ -48,6 +49,7 @@ public class ApiTwentyNinePlus { replyIntent.setAction(INTENT_REPLY_NOTIF_ACTION); replyIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); replyIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + replyIntent.putExtra(INTENT_REMOTE_IDENTITY, notif.getRemoteIdentity()); PendingIntent replyPendingIntent = PendingIntent.getBroadcast( @@ -72,6 +74,7 @@ public class ApiTwentyNinePlus { markAsReadIntent.setAction(INTENT_MARK_AS_READ_ACTION); markAsReadIntent.putExtra(INTENT_NOTIF_ID, notif.getNotificationId()); markAsReadIntent.putExtra(INTENT_LOCAL_IDENTITY, notif.getLocalIdentity()); + markAsReadIntent.putExtra(INTENT_REMOTE_IDENTITY, notif.getRemoteIdentity()); PendingIntent markAsReadPendingIntent = PendingIntent.getBroadcast( diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.java b/app/src/main/java/org/linphone/compatibility/Compatibility.java index 2749e5cf2..9b421d576 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.java +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.java @@ -45,6 +45,7 @@ public class Compatibility { public static final String INTENT_HANGUP_CALL_NOTIF_ACTION = "org.linphone.HANGUP_CALL_ACTION"; public static final String INTENT_ANSWER_CALL_NOTIF_ACTION = "org.linphone.ANSWER_CALL_ACTION"; public static final String INTENT_LOCAL_IDENTITY = "LOCAL_IDENTITY"; + public static final String INTENT_REMOTE_IDENTITY = "REMOTE_IDENTITY"; public static final String INTENT_MARK_AS_READ_ACTION = "org.linphone.MARK_AS_READ_ACTION"; public static String getDeviceName(Context context) { diff --git a/app/src/main/java/org/linphone/notifications/Notifiable.java b/app/src/main/java/org/linphone/notifications/Notifiable.java index 51ae7ef73..025be3613 100644 --- a/app/src/main/java/org/linphone/notifications/Notifiable.java +++ b/app/src/main/java/org/linphone/notifications/Notifiable.java @@ -28,6 +28,7 @@ public class Notifiable { private boolean mIsGroup; private String mGroupTitle; private String mLocalIdentity; + private String mRemoteIdentity; private String mMyself; private int mIconId; private int mTextId; @@ -84,10 +85,18 @@ public class Notifiable { return mLocalIdentity; } + public String getRemoteIdentity() { + return mRemoteIdentity; + } + public void setLocalIdentity(String localIdentity) { mLocalIdentity = localIdentity; } + public void setRemoteIdentity(String remoteIdentity) { + mRemoteIdentity = remoteIdentity; + } + public int getIconResourceId() { return mIconId; } diff --git a/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java b/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java index 81dbba3c9..82d939918 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java +++ b/app/src/main/java/org/linphone/notifications/NotificationBroadcastReceiver.java @@ -19,7 +19,10 @@ */ package org.linphone.notifications; +import static android.content.Context.NOTIFICATION_SERVICE; + import android.app.Notification; +import android.app.NotificationManager; import android.app.RemoteInput; import android.content.BroadcastReceiver; import android.content.Context; @@ -34,27 +37,40 @@ import org.linphone.core.Call; import org.linphone.core.ChatMessage; import org.linphone.core.ChatRoom; import org.linphone.core.Core; +import org.linphone.core.Factory; import org.linphone.core.tools.Log; +import org.linphone.settings.LinphonePreferences; public class NotificationBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { final int notifId = intent.getIntExtra(Compatibility.INTENT_NOTIF_ID, 0); final String localyIdentity = intent.getStringExtra(Compatibility.INTENT_LOCAL_IDENTITY); + final String remoteIdentity = intent.getStringExtra(Compatibility.INTENT_REMOTE_IDENTITY); if (!LinphoneContext.isReady()) { - Log.e("[Notification Broadcast Receiver] Context not ready, aborting..."); - return; + Log.e("[Notification Broadcast Receiver] Context not ready..."); } if (intent.getAction().equals(Compatibility.INTENT_REPLY_NOTIF_ACTION) || intent.getAction().equals(Compatibility.INTENT_MARK_AS_READ_ACTION)) { - String remoteSipAddr = - LinphoneContext.instance() - .getNotificationManager() - .getSipUriForNotificationId(notifId); + String remoteSipAddr = remoteIdentity; + + Core core; + boolean stopCoreWhenFinished = false; + if (!LinphoneContext.isReady()) { + String basePath = context.getFilesDir().getAbsolutePath(); + core = + Factory.instance() + .createCore( + basePath + LinphonePreferences.LINPHONE_DEFAULT_RC, + basePath + LinphonePreferences.LINPHONE_FACTORY_RC, + context); + stopCoreWhenFinished = true; + Log.e("[Notification Broadcast Receiver] Created temporary Core"); + core.start(); + } else core = LinphoneManager.getCore(); - Core core = LinphoneManager.getCore(); if (core == null) { Log.e("[Notification Broadcast Receiver] Couldn't get Core instance"); onError(context, notifId); @@ -102,15 +118,33 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver { ChatMessage msg = room.createMessage(reply); msg.setUserData(notifId); - msg.addListener( - LinphoneContext.instance().getNotificationManager().getMessageListener()); + if (!stopCoreWhenFinished) { + msg.addListener( + LinphoneContext.instance() + .getNotificationManager() + .getMessageListener()); + } msg.send(); Log.i("[Notification Broadcast Receiver] Reply sent for notif id " + notifId); } else { - LinphoneContext.instance().getNotificationManager().dismissNotification(notifId); + if (!stopCoreWhenFinished) { + LinphoneContext.instance() + .getNotificationManager() + .dismissNotification(notifId); + } else { + NotificationManager notificationManager = + (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); + notificationManager.cancel(notifId); + } + } + + if (stopCoreWhenFinished) { + core.stopAsync(); } } else if (intent.getAction().equals(Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION) || intent.getAction().equals(Compatibility.INTENT_HANGUP_CALL_NOTIF_ACTION)) { + if (!LinphoneContext.isReady()) return; + String remoteAddr = LinphoneContext.instance() .getNotificationManager() diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.java b/app/src/main/java/org/linphone/notifications/NotificationsManager.java index c16001487..fc87d6219 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.java +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.java @@ -462,6 +462,7 @@ public class NotificationsManager { notif.setGroupTitle(subject); notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity)); notif.setLocalIdentity(localIdentity.asString()); + notif.setRemoteIdentity(conferenceAddress); displayMessageNotificationFromNotifiable( notif, conferenceAddress, localIdentity.asStringUriOnly()); @@ -496,6 +497,7 @@ public class NotificationsManager { notif.setIsGroup(false); notif.setMyself(LinphoneUtils.getAddressDisplayName(localIdentity)); notif.setLocalIdentity(localIdentity.asString()); + notif.setRemoteIdentity(fromSipUri); displayMessageNotificationFromNotifiable( notif, fromSipUri, localIdentity.asStringUriOnly()); diff --git a/app/src/main/java/org/linphone/settings/LinphonePreferences.java b/app/src/main/java/org/linphone/settings/LinphonePreferences.java index b946c3333..48fb666e9 100644 --- a/app/src/main/java/org/linphone/settings/LinphonePreferences.java +++ b/app/src/main/java/org/linphone/settings/LinphonePreferences.java @@ -53,8 +53,8 @@ import org.linphone.utils.LinphoneUtils; public class LinphonePreferences { private static final int LINPHONE_CORE_RANDOM_PORT = -1; - private static final String LINPHONE_DEFAULT_RC = "/.linphonerc"; - private static final String LINPHONE_FACTORY_RC = "/linphonerc"; + public static final String LINPHONE_DEFAULT_RC = "/.linphonerc"; + public static final String LINPHONE_FACTORY_RC = "/linphonerc"; private static final String LINPHONE_LPCONFIG_XSD = "/lpconfig.xsd"; private static final String DEFAULT_ASSISTANT_RC = "/default_assistant_create.rc"; private static final String LINPHONE_ASSISTANT_RC = "/linphone_assistant_create.rc"; From f1d887e7be8acb6e2b4223201ea3fd47116865d8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 15 Mar 2021 10:24:01 +0100 Subject: [PATCH 22/32] Updated translations & bumped version code --- app/build.gradle | 2 +- app/src/main/res/values-tr/strings.xml | 3 +++ app/src/main/res/values-uk/strings.xml | 8 ++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index ff92bae3b..33e8a737e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4316 + versionCode 4317 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 7eefbd7cc..f45de0591 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -130,6 +130,9 @@ Telefon numaranı yalnızca tek Linphone hesabıyla kullanabilirsin.\n\nEğer hesabını zaten başka hesaba bağladıysan ama bunu kullanmak istiyorsan, şimdi bağla ve numaran kendiliğinden bu hesaba taşınsın. Bu numaraya kısa zamanda birçok SMS gönderildi, 24 saat içinde yeniden deneyin. Hesap yok + kullanım koşullarını + gizlilik ilkesini + Belledonne Communications\'ın %1$s ve %2$s kabul ediyorum Geçersiz e-posta Hesap zaten var diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 2d2745e52..1bc816e90 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -12,7 +12,7 @@ Linphone Android %s Linphone ядро %s Linphone SDK %s - Відвідайте нашу політику конфіденційності + Відвідайте нашу політику конфіденційности контакти linphone Відповідь @@ -25,7 +25,7 @@ Ідентифікатор користувача (необов\'язково) Номер телефону Код підтвердження - Префікс міжнародного номеру телефону + Префікс міжнародного номера телефону Показуване ім\'я Пароль Схвалення паролю @@ -130,6 +130,9 @@ Номер телефону можна використовувати лише з однією обліківкою Linphone.\n\nЯкщо ваш номер вже був зв\'язаний з иншою обліківкою, але ви волієте використовувати його, просто зв\'яжіть його зараз, й ваш номер буде автоматично перенесено в цю обліківку. Забагато SMS було відправлено на цей номер за короткий проміжок часу, повторіть спробу через 24 години. Обліківки не існує + умови використання + політика конфіденційности + Я приймаю %1$s та %2$s Belledonne Communications\' Неприпустима адреса електронної пошти Обліківка вже існує @@ -615,6 +618,7 @@ Вийти з конференції Сервісне сповіщення Linphone Сповіщення миттєвих повідомлень Linphone + Сповіщення про пропущені дзвінки Linphone Тема групового чату Інформація про груповий чат Запис дзвінка From 7e5b9c464871c0dd538acbf429e8ead7d18b6af1 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 18 Mar 2021 11:14:26 +0100 Subject: [PATCH 23/32] Fixed various issues --- app/build.gradle | 2 +- .../linphone/call/AndroidAudioManager.java | 1 + .../java/org/linphone/call/CallActivity.java | 7 ++++ .../java/org/linphone/call/CallManager.java | 4 ++ .../linphone/chat/ChatMessageViewHolder.java | 3 +- .../linphone/chat/ChatMessagesFragment.java | 38 +++++++++++-------- .../contacts/ContactEditorFragment.java | 3 +- .../org/linphone/dialer/DialerActivity.java | 30 ++++++++------- .../main/res/layout/contact_control_cell.xml | 3 +- app/src/main/res/values-hu/strings.xml | 4 ++ .../res/values/non_localizable_custom.xml | 2 +- 11 files changed, 62 insertions(+), 35 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 33e8a737e..5e8ea8d52 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4317 + versionCode 4318 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/java/org/linphone/call/AndroidAudioManager.java b/app/src/main/java/org/linphone/call/AndroidAudioManager.java index e6931a2fd..83eadbfe8 100644 --- a/app/src/main/java/org/linphone/call/AndroidAudioManager.java +++ b/app/src/main/java/org/linphone/call/AndroidAudioManager.java @@ -189,6 +189,7 @@ public class AndroidAudioManager { if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; if (currentCall == null) return false; AudioDevice audioDevice = currentCall.getOutputAudioDevice(); + if (audioDevice == null) return false; Log.i("[Audio Manager] Currently used audio device: ", audioDevice.getDeviceName()); return audioDevice.getType() == AudioDevice.Type.Bluetooth; } diff --git a/app/src/main/java/org/linphone/call/CallActivity.java b/app/src/main/java/org/linphone/call/CallActivity.java index 952a20ee9..91533aa2f 100644 --- a/app/src/main/java/org/linphone/call/CallActivity.java +++ b/app/src/main/java/org/linphone/call/CallActivity.java @@ -409,6 +409,13 @@ public class CallActivity extends LinphoneGenericActivity setCurrentCallContactInformation(); updateInterfaceDependingOnVideo(); + } else if (state == Call.State.Updating) { + if (call.getCurrentParams().videoEnabled()) { + if (!LinphoneManager.getAudioManager() + .isUsingBluetoothAudioRoute()) { + LinphoneManager.getAudioManager().routeAudioToSpeaker(); + } + } } else if (state == Call.State.UpdatedByRemote) { // If the correspondent asks for video while in audio call boolean videoEnabled = LinphonePreferences.instance().isVideoEnabled(); diff --git a/app/src/main/java/org/linphone/call/CallManager.java b/app/src/main/java/org/linphone/call/CallManager.java index 26587029f..de54ccd19 100644 --- a/app/src/main/java/org/linphone/call/CallManager.java +++ b/app/src/main/java/org/linphone/call/CallManager.java @@ -144,6 +144,10 @@ public class CallManager { params.enableVideo(true); core.enableVideoCapture(true); core.enableVideoDisplay(true); + + if (!LinphoneManager.getAudioManager().isUsingBluetoothAudioRoute()) { + LinphoneManager.getAudioManager().routeAudioToSpeaker(); + } } else { params.enableVideo(false); } diff --git a/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java b/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java index 203e69d2e..667d741ac 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java +++ b/app/src/main/java/org/linphone/chat/ChatMessageViewHolder.java @@ -264,7 +264,8 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi final TextView fileName = content.findViewById(R.id.file); fileName.setVisibility(View.GONE); - if (c.isFile() || (c.isFileTransfer() && !c.getFilePath().isEmpty())) { + if (c.isFile() + || (c.isFileTransfer() && message.isOutgoing() && !c.getFilePath().isEmpty())) { // If message is outgoing, even if content // is file transfer we have the file available final String filePath = c.getFilePath(); diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index 7496bfae5..ee6d2c735 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -668,10 +668,15 @@ public class ChatMessagesFragment extends Fragment } /** View initialization */ - private void setReadOnly() { - mMessageTextToSend.setEnabled(false); - mAttachImageButton.setEnabled(false); - mSendMessageButton.setEnabled(false); + private void setReadOnly(boolean readOnly) { + if (readOnly) { + mMessageTextToSend.setText(""); + mFilesUploadLayout.removeAllViews(); + } + + mMessageTextToSend.setEnabled(!readOnly); + mAttachImageButton.setEnabled(!readOnly); + mSendMessageButton.setEnabled(!readOnly); mSendEphemeralIcon.setEnabled(mSendMessageButton.isEnabled()); } @@ -801,7 +806,7 @@ public class ChatMessagesFragment extends Fragment mSendEphemeralIcon.setVisibility(mChatRoom.ephemeralEnabled() ? View.VISIBLE : View.GONE); if (mChatRoom.hasBeenLeft()) { - setReadOnly(); + setReadOnly(true); } updateSecurityLevelIcon(); @@ -1084,15 +1089,18 @@ public class ChatMessagesFragment extends Fragment boolean split = isBasicChatRoom; // Always split contents in basic chat rooms for compatibility - if (hasText && sendImageAndTextAsDifferentMessages) { - split = true; - } else if (mFilesUploadLayout.getChildCount() > 1 - && sendMultipleImagesAsDifferentMessages) { - split = true; + if (!split) { + if (hasText && sendImageAndTextAsDifferentMessages) { + split = true; + } else if (mFilesUploadLayout.getChildCount() > 1 + && sendMultipleImagesAsDifferentMessages) { + split = true; - // Allow the last image to be sent with text if image and text at the same time OK - if (hasText && i == filesCount - 1) { - split = false; + // Allow the last image to be sent with text if image and text at the same time + // OK + if (hasText && i == filesCount - 1) { + split = false; + } } } @@ -1450,9 +1458,7 @@ public class ChatMessagesFragment extends Fragment @Override public void onStateChanged(ChatRoom cr, ChatRoom.State newState) { - if (mChatRoom.hasBeenLeft()) { - setReadOnly(); - } + setReadOnly(mChatRoom.hasBeenLeft()); } @Override diff --git a/app/src/main/java/org/linphone/contacts/ContactEditorFragment.java b/app/src/main/java/org/linphone/contacts/ContactEditorFragment.java index 238681f51..e8bf17f8a 100644 --- a/app/src/main/java/org/linphone/contacts/ContactEditorFragment.java +++ b/app/src/main/java/org/linphone/contacts/ContactEditorFragment.java @@ -500,9 +500,8 @@ public class ContactEditorFragment extends Fragment { } catch (IOException e) { Log.e("[Contact Editor] Failed to get Exif rotation, error is ", e); } - } else { - } + if (image == null) { Log.e( "[Contact Editor] Couldn't get bitmap from either filePath [", diff --git a/app/src/main/java/org/linphone/dialer/DialerActivity.java b/app/src/main/java/org/linphone/dialer/DialerActivity.java index af30679a5..301351344 100644 --- a/app/src/main/java/org/linphone/dialer/DialerActivity.java +++ b/app/src/main/java/org/linphone/dialer/DialerActivity.java @@ -106,6 +106,9 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC @Override public void onCallStateChanged( Core core, Call call, Call.State state, String message) { + if (state == Call.State.OutgoingInit) { + if (mAddress != null) mAddress.setText(""); + } updateLayout(); } @@ -166,10 +169,6 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC }; mIsTransfer = false; - if (getIntent() != null) { - mIsTransfer = getIntent().getBooleanExtra("isTransfer", false); - } - handleIntentParams(getIntent()); } @@ -178,13 +177,6 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC super.onNewIntent(intent); handleIntentParams(intent); - - if (intent != null) { - mIsTransfer = intent.getBooleanExtra("isTransfer", mIsTransfer); - if (mAddress != null && intent.getStringExtra("SipUri") != null) { - mAddress.setText(intent.getStringExtra("SipUri")); - } - } } @Override @@ -207,7 +199,6 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC @Override protected void onPause() { enableVideoPreviewIfTablet(false); - if (mAddress != null) mAddress.setText(""); Core core = LinphoneManager.getCore(); if (core != null) { core.removeListener(mListener); @@ -219,6 +210,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC @Override protected void onDestroy() { if (mInterfaceLoaded) { + if (mAddress != null) mAddress.setText(""); mAddress = null; mStartCall = null; mAddCall = null; @@ -280,6 +272,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC intent.putExtra("EditOnClick", true); intent.putExtra("SipAddress", mAddress.getText().toString()); startActivity(intent); + if (mAddress != null) mAddress.setText(""); } }); @@ -289,6 +282,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC @Override public void onClick(View v) { goBackToCall(); + if (mAddress != null) mAddress.setText(""); } }); @@ -334,6 +328,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); + outState.putSerializable("address", mAddress.getText().toString()); outState.putSerializable("isTransfer", mIsTransfer); } @@ -341,6 +336,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mIsTransfer = savedInstanceState.getBoolean("isTransfer"); + mAddress.setText(savedInstanceState.getString("address")); } @Override @@ -375,6 +371,8 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC private void handleIntentParams(Intent intent) { if (intent == null) return; + mIsTransfer = intent.getBooleanExtra("isTransfer", mIsTransfer); + String action = intent.getAction(); String addressToCall = null; if (ACTION_CALL_LINPHONE.equals(action) @@ -409,7 +407,13 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC Log.i("[Dialer] " + action + " with number: " + addressToCall); } } else { - Log.w("[Dialer] Intent data is null for action " + action); + String sipUri = intent.getStringExtra("SipUri"); + if (sipUri != null) { + Log.i("[Dialer] Found extra SIP URI: " + sipUri); + addressToCall = sipUri; + } else { + Log.w("[Dialer] Intent data is null for action " + action); + } } } diff --git a/app/src/main/res/layout/contact_control_cell.xml b/app/src/main/res/layout/contact_control_cell.xml index 07c27700d..5662958e7 100644 --- a/app/src/main/res/layout/contact_control_cell.xml +++ b/app/src/main/res/layout/contact_control_cell.xml @@ -45,11 +45,12 @@ diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 594290fd9..5d1d7f1fb 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -130,6 +130,9 @@ A telefonszámát csak egy Linphone-fiókkal használhatja.\n\nHa már összekapcsolta telefonszámát egy másik fiókkal, de inkább ezt használja, egyszerűen kapcsolja össze, és a telefonszám önműködően átkerül ebbe a fiókba. Túl sok SMS-t küldtek erre a számra rövid idő alatt. Kérjük, várjon 24 órát, mielőtt újra megpróbálja. Fiók nem létezik + használati feltételek + adatvédelmi szabályzat + Elfogadom a Belledonne Communications %1$s és %2$s Érvénytelen e-mail Fiók már létezik @@ -613,6 +616,7 @@ Konferencia elhagyása Linphone szolgáltatás-értesítés Linphone csevegőüzenetek értesítések + Linphone nem fogadott hívások értesítései Csoportos csevegőszoba tárgya Csoportos csevegőszoba tájékoztatás Hívás felvétele diff --git a/app/src/main/res/values/non_localizable_custom.xml b/app/src/main/res/values/non_localizable_custom.xml index 590768902..21e2cfc5a 100644 --- a/app/src/main/res/values/non_localizable_custom.xml +++ b/app/src/main/res/values/non_localizable_custom.xml @@ -116,7 +116,7 @@ false false true - true + false true true From b63b23a8b33510e87ed0bb168dc8a12cdfdceff7 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 22 Mar 2021 11:30:11 +0100 Subject: [PATCH 24/32] Fixes more issues --- app/src/main/java/org/linphone/LinphoneManager.java | 9 --------- .../main/java/org/linphone/activities/MainActivity.java | 1 + app/src/main/java/org/linphone/call/CallActivity.java | 3 ++- .../java/org/linphone/contacts/ContactsFragment.java | 2 ++ .../main/java/org/linphone/service/LinphoneService.java | 5 ----- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/linphone/LinphoneManager.java b/app/src/main/java/org/linphone/LinphoneManager.java index cd49efb0f..94c54598b 100644 --- a/app/src/main/java/org/linphone/LinphoneManager.java +++ b/app/src/main/java/org/linphone/LinphoneManager.java @@ -314,15 +314,6 @@ public class LinphoneManager implements SensorEventListener { private void destroyCore() { Log.w("[Manager] Destroying Core"); - if (LinphonePreferences.instance() != null) { - // We set network reachable at false before destroying the Core - // to not send a register with expires at 0 - if (LinphonePreferences.instance().isPushNotificationEnabled()) { - Log.w( - "[Manager] Setting network reachability to False to prevent unregister and allow incoming push notifications"); - mCore.setNetworkReachable(false); - } - } mCore.stop(); mCore.removeListener(mCoreListener); } diff --git a/app/src/main/java/org/linphone/activities/MainActivity.java b/app/src/main/java/org/linphone/activities/MainActivity.java index f2ca78da1..86017f275 100644 --- a/app/src/main/java/org/linphone/activities/MainActivity.java +++ b/app/src/main/java/org/linphone/activities/MainActivity.java @@ -559,6 +559,7 @@ public abstract class MainActivity extends LinphoneGenericActivity if (LinphoneContext.isReady()) { ContactsManager.getInstance().enableContactsAccess(); ContactsManager.getInstance().initializeContactManager(); + ContactsManager.getInstance().fetchContactsAsync(); } } } else if (permissions[i].equals(Manifest.permission.READ_EXTERNAL_STORAGE)) { diff --git a/app/src/main/java/org/linphone/call/CallActivity.java b/app/src/main/java/org/linphone/call/CallActivity.java index 91533aa2f..ab97dbcf7 100644 --- a/app/src/main/java/org/linphone/call/CallActivity.java +++ b/app/src/main/java/org/linphone/call/CallActivity.java @@ -1122,7 +1122,8 @@ public class CallActivity extends LinphoneGenericActivity if (mCore.isInConference()) { displayConferenceCall(call); conferenceDisplayed = true; - } else if (!pausedConferenceDisplayed) { + } else if (!pausedConferenceDisplayed + && mCore.getCallsNb() > 1) { // Workaround for temporary SDK issue displayPausedConference(); pausedConferenceDisplayed = true; } diff --git a/app/src/main/java/org/linphone/contacts/ContactsFragment.java b/app/src/main/java/org/linphone/contacts/ContactsFragment.java index 0d6028d75..1ea2d0c63 100644 --- a/app/src/main/java/org/linphone/contacts/ContactsFragment.java +++ b/app/src/main/java/org/linphone/contacts/ContactsFragment.java @@ -216,6 +216,7 @@ public class ContactsFragment extends Fragment @Override public void onResume() { super.onResume(); + ContactsManager.getInstance().addContactsListener(this); mOnlyDisplayLinphoneContacts = @@ -224,6 +225,7 @@ public class ContactsFragment extends Fragment changeContactsToggle(); invalidate(); + onContactsUpdated(); ((ContactsActivity) (getActivity())).showTabBar(); } diff --git a/app/src/main/java/org/linphone/service/LinphoneService.java b/app/src/main/java/org/linphone/service/LinphoneService.java index b08aa85b1..47ba8365f 100644 --- a/app/src/main/java/org/linphone/service/LinphoneService.java +++ b/app/src/main/java/org/linphone/service/LinphoneService.java @@ -107,11 +107,6 @@ public final class LinphoneService extends Service { if (core != null) { core.terminateAllCalls(); } - - // If push is enabled, don't unregister account, otherwise do unregister - if (LinphonePreferences.instance().isPushNotificationEnabled()) { - if (core != null) core.setNetworkReachable(false); - } stopSelf(); } super.onTaskRemoved(rootIntent); From 7c244654b365e8bb0da4c0d3ad2c1066bf00c2db Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 22 Mar 2021 17:30:13 +0100 Subject: [PATCH 25/32] Fixed issues with link phone number to account dialog --- .../java/org/linphone/LinphoneManager.java | 133 ---------------- .../org/linphone/activities/MainActivity.java | 148 ++++++++++++++++-- .../PhoneAccountLinkingAssistantActivity.java | 11 +- 3 files changed, 143 insertions(+), 149 deletions(-) diff --git a/app/src/main/java/org/linphone/LinphoneManager.java b/app/src/main/java/org/linphone/LinphoneManager.java index 94c54598b..06bf7a197 100644 --- a/app/src/main/java/org/linphone/LinphoneManager.java +++ b/app/src/main/java/org/linphone/LinphoneManager.java @@ -20,9 +20,7 @@ package org.linphone; import android.annotation.SuppressLint; -import android.app.Dialog; import android.content.Context; -import android.content.Intent; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; @@ -33,20 +31,13 @@ import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; -import android.view.View; -import android.widget.Button; -import android.widget.CheckBox; import java.io.File; -import java.sql.Timestamp; -import java.util.Date; import java.util.Timer; import java.util.TimerTask; -import org.linphone.assistant.PhoneAccountLinkingAssistantActivity; import org.linphone.call.AndroidAudioManager; import org.linphone.call.CallManager; import org.linphone.contacts.ContactsManager; import org.linphone.core.AccountCreator; -import org.linphone.core.AccountCreatorListenerStub; import org.linphone.core.Call; import org.linphone.core.Call.State; import org.linphone.core.Core; @@ -92,7 +83,6 @@ public class LinphoneManager implements SensorEventListener { private Core mCore; private CoreListenerStub mCoreListener; private AccountCreator mAccountCreator; - private AccountCreatorListenerStub mAccountCreatorListener; private boolean mExited; private boolean mCallGsmON; @@ -223,39 +213,6 @@ public class LinphoneManager implements SensorEventListener { list.removeListener(ContactsManager.getInstance()); } }; - - mAccountCreatorListener = - new AccountCreatorListenerStub() { - @Override - public void onIsAccountExist( - AccountCreator accountCreator, - AccountCreator.Status status, - String resp) { - if (status.equals(AccountCreator.Status.AccountExist)) { - accountCreator.isAccountLinked(); - } - } - - @Override - public void onLinkAccount( - AccountCreator accountCreator, - AccountCreator.Status status, - String resp) { - if (status.equals(AccountCreator.Status.AccountNotLinked)) { - askLinkWithPhoneNumber(); - } - } - - @Override - public void onIsAccountLinked( - AccountCreator accountCreator, - AccountCreator.Status status, - String resp) { - if (status.equals(AccountCreator.Status.AccountNotLinked)) { - askLinkWithPhoneNumber(); - } - } - }; } public static synchronized LinphoneManager getInstance() { @@ -452,7 +409,6 @@ public class LinphoneManager implements SensorEventListener { resetCameraFromPreferences(); mAccountCreator = mCore.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); - mAccountCreator.setListener(mAccountCreatorListener); mCallGsmON = false; Log.i("[Manager] Core configured"); @@ -489,99 +445,10 @@ public class LinphoneManager implements SensorEventListener { Log.w("[Manager] Account creator shouldn't be null !"); mAccountCreator = mCore.createAccountCreator(LinphonePreferences.instance().getXmlrpcUrl()); - mAccountCreator.setListener(mAccountCreatorListener); } return mAccountCreator; } - public void isAccountWithAlias() { - if (mCore.getDefaultProxyConfig() != null) { - long now = new Timestamp(new Date().getTime()).getTime(); - AccountCreator accountCreator = getAccountCreator(); - if (LinphonePreferences.instance().getLinkPopupTime() == null - || Long.parseLong(LinphonePreferences.instance().getLinkPopupTime()) < now) { - accountCreator.reset(); - accountCreator.setUsername( - LinphonePreferences.instance() - .getAccountUsername( - LinphonePreferences.instance().getDefaultAccountIndex())); - accountCreator.isAccountExist(); - } - } else { - LinphonePreferences.instance().setLinkPopupTime(null); - } - } - - private void askLinkWithPhoneNumber() { - if (!LinphonePreferences.instance().isLinkPopupEnabled()) return; - - long now = new Timestamp(new Date().getTime()).getTime(); - if (LinphonePreferences.instance().getLinkPopupTime() != null - && Long.parseLong(LinphonePreferences.instance().getLinkPopupTime()) >= now) return; - - ProxyConfig proxyConfig = mCore.getDefaultProxyConfig(); - if (proxyConfig == null) return; - if (!proxyConfig.getDomain().equals(getString(R.string.default_domain))) return; - - long future = - new Timestamp( - mContext.getResources() - .getInteger( - R.integer.phone_number_linking_popup_time_interval)) - .getTime(); - long newDate = now + future; - - LinphonePreferences.instance().setLinkPopupTime(String.valueOf(newDate)); - - final Dialog dialog = - LinphoneUtils.getDialog( - mContext, - String.format( - getString(R.string.link_account_popup), - proxyConfig.getIdentityAddress().asStringUriOnly())); - Button delete = dialog.findViewById(R.id.dialog_delete_button); - delete.setVisibility(View.GONE); - Button ok = dialog.findViewById(R.id.dialog_ok_button); - ok.setText(getString(R.string.link)); - ok.setVisibility(View.VISIBLE); - Button cancel = dialog.findViewById(R.id.dialog_cancel_button); - cancel.setText(getString(R.string.maybe_later)); - - dialog.findViewById(R.id.dialog_do_not_ask_again_layout).setVisibility(View.VISIBLE); - final CheckBox doNotAskAgain = dialog.findViewById(R.id.doNotAskAgain); - dialog.findViewById(R.id.doNotAskAgainLabel) - .setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - doNotAskAgain.setChecked(!doNotAskAgain.isChecked()); - } - }); - - ok.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent assistant = new Intent(); - assistant.setClass(mContext, PhoneAccountLinkingAssistantActivity.class); - mContext.startActivity(assistant); - dialog.dismiss(); - } - }); - - cancel.setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - if (doNotAskAgain.isChecked()) { - LinphonePreferences.instance().enableLinkPopup(false); - } - dialog.dismiss(); - } - }); - dialog.show(); - } - /* Presence stuff */ private boolean isPresenceModelActivitySet() { diff --git a/app/src/main/java/org/linphone/activities/MainActivity.java b/app/src/main/java/org/linphone/activities/MainActivity.java index 86017f275..bd5091699 100644 --- a/app/src/main/java/org/linphone/activities/MainActivity.java +++ b/app/src/main/java/org/linphone/activities/MainActivity.java @@ -43,10 +43,13 @@ import android.widget.TextView; import android.widget.Toast; import androidx.core.app.ActivityCompat; import androidx.drawerlayout.widget.DrawerLayout; +import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Date; import org.linphone.LinphoneContext; import org.linphone.LinphoneManager; import org.linphone.R; +import org.linphone.assistant.PhoneAccountLinkingAssistantActivity; import org.linphone.call.CallActivity; import org.linphone.call.CallIncomingActivity; import org.linphone.call.CallOutgoingActivity; @@ -55,8 +58,9 @@ import org.linphone.compatibility.Compatibility; import org.linphone.contacts.ContactsActivity; import org.linphone.contacts.ContactsManager; import org.linphone.contacts.LinphoneContact; +import org.linphone.core.AccountCreator; +import org.linphone.core.AccountCreatorListenerStub; import org.linphone.core.Address; -import org.linphone.core.AuthInfo; import org.linphone.core.Call; import org.linphone.core.ChatMessage; import org.linphone.core.ChatRoom; @@ -99,6 +103,7 @@ public abstract class MainActivity extends LinphoneGenericActivity protected String[] mPermissionsToHave; private CoreListenerStub mListener; + private AccountCreatorListenerStub mAccountCreatorListener; @Override protected void onCreate(Bundle savedInstanceState) { @@ -228,15 +233,10 @@ public abstract class MainActivity extends LinphoneGenericActivity MainActivity.this); if (getResources().getBoolean(R.bool.use_phone_number_validation)) { - AuthInfo authInfo = - core.findAuthInfo( - proxyConfig.getRealm(), - proxyConfig.getIdentityAddress().getUsername(), - proxyConfig.getDomain()); - if (authInfo != null - && authInfo.getDomain() - .equals(getString(R.string.default_domain))) { - LinphoneManager.getInstance().isAccountWithAlias(); + if (proxyConfig + .getDomain() + .equals(getString(R.string.default_domain))) { + isAccountWithAlias(); } } @@ -269,6 +269,39 @@ public abstract class MainActivity extends LinphoneGenericActivity } } }; + + mAccountCreatorListener = + new AccountCreatorListenerStub() { + @Override + public void onIsAccountExist( + AccountCreator accountCreator, + AccountCreator.Status status, + String resp) { + if (status.equals(AccountCreator.Status.AccountExist)) { + accountCreator.isAccountLinked(); + } + } + + @Override + public void onLinkAccount( + AccountCreator accountCreator, + AccountCreator.Status status, + String resp) { + if (status.equals(AccountCreator.Status.AccountNotLinked)) { + askLinkWithPhoneNumber(); + } + } + + @Override + public void onIsAccountLinked( + AccountCreator accountCreator, + AccountCreator.Status status, + String resp) { + if (status.equals(AccountCreator.Status.AccountNotLinked)) { + askLinkWithPhoneNumber(); + } + } + }; } @Override @@ -814,6 +847,101 @@ public abstract class MainActivity extends LinphoneGenericActivity dialog.show(); } + public void isAccountWithAlias() { + if (LinphoneManager.getCore().getDefaultProxyConfig() != null) { + long now = new Timestamp(new Date().getTime()).getTime(); + AccountCreator accountCreator = LinphoneManager.getInstance().getAccountCreator(); + accountCreator.setListener(mAccountCreatorListener); + if (LinphonePreferences.instance().getLinkPopupTime() == null + || Long.parseLong(LinphonePreferences.instance().getLinkPopupTime()) < now) { + accountCreator.reset(); + accountCreator.setUsername( + LinphonePreferences.instance() + .getAccountUsername( + LinphonePreferences.instance().getDefaultAccountIndex())); + accountCreator.isAccountExist(); + } + } else { + LinphonePreferences.instance().setLinkPopupTime(null); + } + } + + private void askLinkWithPhoneNumber() { + if (!LinphonePreferences.instance().isLinkPopupEnabled()) return; + + long now = new Timestamp(new Date().getTime()).getTime(); + if (LinphonePreferences.instance().getLinkPopupTime() != null + && Long.parseLong(LinphonePreferences.instance().getLinkPopupTime()) >= now) return; + + ProxyConfig proxyConfig = LinphoneManager.getCore().getDefaultProxyConfig(); + if (proxyConfig == null) return; + if (!proxyConfig.getDomain().equals(getString(R.string.default_domain))) return; + + final Dialog dialog = + LinphoneUtils.getDialog( + this, + String.format( + getString(R.string.link_account_popup), + proxyConfig.getIdentityAddress().asStringUriOnly())); + Button delete = dialog.findViewById(R.id.dialog_delete_button); + delete.setVisibility(View.GONE); + Button ok = dialog.findViewById(R.id.dialog_ok_button); + ok.setText(getString(R.string.link)); + ok.setVisibility(View.VISIBLE); + Button cancel = dialog.findViewById(R.id.dialog_cancel_button); + cancel.setText(getString(R.string.maybe_later)); + + dialog.findViewById(R.id.dialog_do_not_ask_again_layout).setVisibility(View.VISIBLE); + final CheckBox doNotAskAgain = dialog.findViewById(R.id.doNotAskAgain); + dialog.findViewById(R.id.doNotAskAgainLabel) + .setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + doNotAskAgain.setChecked(!doNotAskAgain.isChecked()); + } + }); + + ok.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent assistant = new Intent(); + assistant.setClass( + MainActivity.this, PhoneAccountLinkingAssistantActivity.class); + startActivity(assistant); + updatePopupTimestamp(); + dialog.dismiss(); + } + }); + + cancel.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View view) { + if (doNotAskAgain.isChecked()) { + LinphonePreferences.instance().enableLinkPopup(false); + } + updatePopupTimestamp(); + dialog.dismiss(); + } + }); + dialog.show(); + } + + private void updatePopupTimestamp() { + long future = + new Timestamp( + getResources() + .getInteger( + R.integer.phone_number_linking_popup_time_interval)) + .getTime(); + long now = new Timestamp(new Date().getTime()).getTime(); + long newDate = now + future; + + LinphonePreferences.instance().setLinkPopupTime(String.valueOf(newDate)); + } + // Logs private void shareUploadedLogsUrl(String info) { diff --git a/app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java b/app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java index 851ef0385..88ac130ab 100644 --- a/app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/PhoneAccountLinkingAssistantActivity.java @@ -52,8 +52,11 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity { setContentView(R.layout.assistant_phone_account_linking); - if (getIntent() != null && getIntent().hasExtra("AccountNumber")) { - int proxyConfigIndex = getIntent().getExtras().getInt("AccountNumber"); + if (getIntent() != null) { + int proxyConfigIndex = 0; + if (getIntent().hasExtra("AccountNumber")) + proxyConfigIndex = getIntent().getExtras().getInt("AccountNumber"); + Core core = LinphoneManager.getCore(); if (core == null) { Log.e("[Account Linking Assistant] Core not available"); @@ -96,10 +99,6 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity { unexpectedError(); return; } - } else { - Log.e("[Account Linking Assistant] Proxy config index not found"); - unexpectedError(); - return; } mCountryPicker = findViewById(R.id.select_country); From 7889d531bf7328f786953edbe980354493cdab30 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 23 Mar 2021 09:58:02 +0100 Subject: [PATCH 26/32] Bumped version code --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 5e8ea8d52..8ea052f08 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4318 + versionCode 4319 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true From 39b3b4580a31486895f4d95a601a35ec10cbe726 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 23 Mar 2021 10:04:40 +0100 Subject: [PATCH 27/32] Fixed crash upon rotation while on Dialer view --- app/src/main/java/org/linphone/dialer/DialerActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/linphone/dialer/DialerActivity.java b/app/src/main/java/org/linphone/dialer/DialerActivity.java index 301351344..42736cf72 100644 --- a/app/src/main/java/org/linphone/dialer/DialerActivity.java +++ b/app/src/main/java/org/linphone/dialer/DialerActivity.java @@ -336,7 +336,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mIsTransfer = savedInstanceState.getBoolean("isTransfer"); - mAddress.setText(savedInstanceState.getString("address")); + if (mAddress != null) mAddress.setText(savedInstanceState.getString("address")); } @Override From f5c2be45c0c671bd980568e40551a3ac031b341f Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 23 Mar 2021 13:53:51 +0100 Subject: [PATCH 28/32] Fixed speaker not activated when video call is started + prevent switch to speaker if using wired headset --- .../org/linphone/call/AndroidAudioManager.java | 14 ++++++++++++++ .../java/org/linphone/call/CallActivity.java | 18 +++++++++++------- .../java/org/linphone/call/CallManager.java | 3 ++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/linphone/call/AndroidAudioManager.java b/app/src/main/java/org/linphone/call/AndroidAudioManager.java index 83eadbfe8..cf78818e2 100644 --- a/app/src/main/java/org/linphone/call/AndroidAudioManager.java +++ b/app/src/main/java/org/linphone/call/AndroidAudioManager.java @@ -205,6 +205,20 @@ public class AndroidAudioManager { return false; } + public synchronized boolean isWiredHeadsetAvailable() { + for (AudioDevice audioDevice : LinphoneManager.getCore().getExtendedAudioDevices()) { + Log.e("# AUDIO DEVICE TYPE IS " + audioDevice.getType().name()); + if (audioDevice.getType() == AudioDevice.Type.Headphones + || audioDevice.getType() == AudioDevice.Type.Headset) { + Log.i( + "[Audio Manager] Found headset/headphone device: ", + audioDevice.getDeviceName()); + return true; + } + } + return false; + } + public synchronized void routeAudioToBluetooth() { if (LinphoneManager.getCore().getCallsNb() == 0) return; Call currentCall = LinphoneManager.getCore().getCurrentCall(); diff --git a/app/src/main/java/org/linphone/call/CallActivity.java b/app/src/main/java/org/linphone/call/CallActivity.java index ab97dbcf7..20def9233 100644 --- a/app/src/main/java/org/linphone/call/CallActivity.java +++ b/app/src/main/java/org/linphone/call/CallActivity.java @@ -407,15 +407,16 @@ public class CallActivity extends LinphoneGenericActivity } else if (state == Call.State.StreamsRunning) { mCallPausedByRemote.setVisibility(View.GONE); - setCurrentCallContactInformation(); - updateInterfaceDependingOnVideo(); - } else if (state == Call.State.Updating) { if (call.getCurrentParams().videoEnabled()) { - if (!LinphoneManager.getAudioManager() - .isUsingBluetoothAudioRoute()) { + AndroidAudioManager manager = LinphoneManager.getAudioManager(); + if (!manager.isUsingBluetoothAudioRoute() + && !manager.isWiredHeadsetAvailable()) { LinphoneManager.getAudioManager().routeAudioToSpeaker(); } } + + setCurrentCallContactInformation(); + updateInterfaceDependingOnVideo(); } else if (state == Call.State.UpdatedByRemote) { // If the correspondent asks for video while in audio call boolean videoEnabled = LinphonePreferences.instance().isVideoEnabled(); @@ -464,8 +465,11 @@ public class CallActivity extends LinphoneGenericActivity if (videoEnabled) { mAudioManager = LinphoneManager.getAudioManager(); - mAudioManager.routeAudioToSpeaker(); - mSpeaker.setSelected(true); + if (!mAudioManager.isWiredHeadsetAvailable() + && !mAudioManager.isUsingBluetoothAudioRoute()) { + mAudioManager.routeAudioToSpeaker(); + mSpeaker.setSelected(true); + } } } } diff --git a/app/src/main/java/org/linphone/call/CallManager.java b/app/src/main/java/org/linphone/call/CallManager.java index de54ccd19..cdafb21eb 100644 --- a/app/src/main/java/org/linphone/call/CallManager.java +++ b/app/src/main/java/org/linphone/call/CallManager.java @@ -145,7 +145,8 @@ public class CallManager { core.enableVideoCapture(true); core.enableVideoDisplay(true); - if (!LinphoneManager.getAudioManager().isUsingBluetoothAudioRoute()) { + if (!LinphoneManager.getAudioManager().isUsingBluetoothAudioRoute() + && !LinphoneManager.getAudioManager().isWiredHeadsetAvailable()) { LinphoneManager.getAudioManager().routeAudioToSpeaker(); } } else { From b6445cda7f3826d71a5014d3e3485a874e4ace37 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 24 Mar 2021 13:54:33 +0100 Subject: [PATCH 29/32] Fixed audio route issues --- .../linphone/call/AndroidAudioManager.java | 48 +++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/linphone/call/AndroidAudioManager.java b/app/src/main/java/org/linphone/call/AndroidAudioManager.java index cf78818e2..4e296a5ab 100644 --- a/app/src/main/java/org/linphone/call/AndroidAudioManager.java +++ b/app/src/main/java/org/linphone/call/AndroidAudioManager.java @@ -36,12 +36,14 @@ public class AndroidAudioManager { private Context mContext; private AudioManager mAudioManager; private boolean mEchoTesterIsRunning = false; + private boolean mPreviousStateIsConnected = false; private CoreListenerStub mListener; public AndroidAudioManager(Context context) { mContext = context; mAudioManager = ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)); + mPreviousStateIsConnected = false; mListener = new CoreListenerStub() { @@ -63,11 +65,15 @@ public class AndroidAudioManager { routeAudioToEarPiece(); } } - } else { - routeAudioToBluetooth(); } } + } else if (state == Call.State.StreamsRunning + && mPreviousStateIsConnected) { + if (isBluetoothHeadsetConnected()) { + routeAudioToBluetooth(); + } } + mPreviousStateIsConnected = state == Call.State.Connected; } }; @@ -95,11 +101,11 @@ public class AndroidAudioManager { } public boolean isAudioRoutedToSpeaker() { - return mAudioManager.isSpeakerphoneOn() && !isUsingBluetoothAudioRoute(); + return isUsingSpeakerAudioRoute() && !isUsingBluetoothAudioRoute(); } public boolean isAudioRoutedToEarpiece() { - return !mAudioManager.isSpeakerphoneOn() && !isUsingBluetoothAudioRoute(); + return !isUsingSpeakerAudioRoute() && !isUsingBluetoothAudioRoute(); } /* Echo cancellation */ @@ -143,6 +149,21 @@ public class AndroidAudioManager { return false; } + public synchronized boolean isUsingSpeakerAudioRoute() { + if (LinphoneManager.getCore().getCallsNb() == 0) return false; + Call currentCall = LinphoneManager.getCore().getCurrentCall(); + if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; + if (currentCall == null) return false; + AudioDevice audioDevice = currentCall.getOutputAudioDevice(); + if (audioDevice == null) return false; + Log.i( + "[Audio Manager] Currently used audio device: ", + audioDevice.getDeviceName(), + "/", + audioDevice.getType().name()); + return audioDevice.getType() == AudioDevice.Type.Speaker; + } + private void routeAudioToSpeakerHelper(boolean speakerOn) { Log.w("[Audio Manager] Routing audio to " + (speakerOn ? "speaker" : "earpiece")); @@ -190,7 +211,11 @@ public class AndroidAudioManager { if (currentCall == null) return false; AudioDevice audioDevice = currentCall.getOutputAudioDevice(); if (audioDevice == null) return false; - Log.i("[Audio Manager] Currently used audio device: ", audioDevice.getDeviceName()); + Log.i( + "[Audio Manager] Currently used audio device: ", + audioDevice.getDeviceName(), + "/", + audioDevice.getType().name()); return audioDevice.getType() == AudioDevice.Type.Bluetooth; } @@ -198,7 +223,11 @@ public class AndroidAudioManager { for (AudioDevice audioDevice : LinphoneManager.getCore().getAudioDevices()) { if (audioDevice.getType() == AudioDevice.Type.Bluetooth && audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) { - Log.i("[Audio Manager] Found bluetooth device: ", audioDevice.getDeviceName()); + Log.i( + "[Audio Manager] Found bluetooth device: ", + audioDevice.getDeviceName(), + "/", + audioDevice.getType().name()); return true; } } @@ -207,12 +236,13 @@ public class AndroidAudioManager { public synchronized boolean isWiredHeadsetAvailable() { for (AudioDevice audioDevice : LinphoneManager.getCore().getExtendedAudioDevices()) { - Log.e("# AUDIO DEVICE TYPE IS " + audioDevice.getType().name()); if (audioDevice.getType() == AudioDevice.Type.Headphones || audioDevice.getType() == AudioDevice.Type.Headset) { Log.i( "[Audio Manager] Found headset/headphone device: ", - audioDevice.getDeviceName()); + audioDevice.getDeviceName(), + "/", + audioDevice.getType().name()); return true; } } @@ -231,6 +261,8 @@ public class AndroidAudioManager { Log.i( "[Audio Manager] Found bluetooth audio device", audioDevice.getDeviceName(), + "/", + audioDevice.getType().name(), ", routing audio to it"); currentCall.setOutputAudioDevice(audioDevice); return; From e97a68dda5f8665782c3e392416154a9fc0fe03b Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 24 Mar 2021 13:54:51 +0100 Subject: [PATCH 30/32] Fixed crash due to not using the local address in getChatRooms() --- app/build.gradle | 2 +- app/src/main/java/org/linphone/chat/ChatActivity.java | 9 ++++++++- .../java/org/linphone/chat/ChatMessagesFragment.java | 8 ++++++-- .../java/org/linphone/chat/ChatRoomCreationFragment.java | 1 + .../main/java/org/linphone/chat/EphemeralFragment.java | 4 +++- .../main/java/org/linphone/chat/GroupInfoFragment.java | 9 ++++++++- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8ea052f08..c878aea7c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4319 + versionCode 4320 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true diff --git a/app/src/main/java/org/linphone/chat/ChatActivity.java b/app/src/main/java/org/linphone/chat/ChatActivity.java index 9646da8bc..56c494edc 100644 --- a/app/src/main/java/org/linphone/chat/ChatActivity.java +++ b/app/src/main/java/org/linphone/chat/ChatActivity.java @@ -297,6 +297,7 @@ public class ChatActivity extends MainActivity { public void showChatRoomGroupInfo( Address peerAddress, + Address localAddress, ArrayList participants, String subject, boolean encrypted) { @@ -304,6 +305,9 @@ public class ChatActivity extends MainActivity { if (peerAddress != null) { extras.putSerializable("RemoteSipUri", peerAddress.asStringUriOnly()); } + if (localAddress != null) { + extras.putSerializable("LocalSipUri", localAddress.asStringUriOnly()); + } extras.putSerializable("Participants", participants); extras.putString("Subject", subject); extras.putBoolean("Encrypted", encrypted); @@ -313,11 +317,14 @@ public class ChatActivity extends MainActivity { changeFragment(fragment, "Chat room group info", true); } - public void showChatRoomEphemeral(Address peerAddress) { + public void showChatRoomEphemeral(Address peerAddress, Address localAddress) { Bundle extras = new Bundle(); if (peerAddress != null) { extras.putSerializable("RemoteSipUri", peerAddress.asStringUriOnly()); } + if (localAddress != null) { + extras.putSerializable("LocalSipUri", localAddress.asStringUriOnly()); + } EphemeralFragment fragment = new EphemeralFragment(); fragment.setArguments(extras); changeFragment(fragment, "Chat room ephemeral", true); diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index ee6d2c735..440f85b6d 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -1215,12 +1215,16 @@ public class ChatMessagesFragment extends Fragment boolean encrypted = mChatRoom.hasCapability(ChatRoomCapabilities.Encrypted.toInt()); ((ChatActivity) getActivity()) .showChatRoomGroupInfo( - mRemoteSipAddress, participants, mChatRoom.getSubject(), encrypted); + mRemoteSipAddress, + mLocalSipAddress, + participants, + mChatRoom.getSubject(), + encrypted); } private void goToEphemeral() { if (mChatRoom == null) return; - ((ChatActivity) getActivity()).showChatRoomEphemeral(mRemoteSipAddress); + ((ChatActivity) getActivity()).showChatRoomEphemeral(mRemoteSipAddress, mLocalSipAddress); } /* diff --git a/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java b/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java index bce06962a..190ee1476 100644 --- a/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatRoomCreationFragment.java @@ -154,6 +154,7 @@ public class ChatRoomCreationFragment extends Fragment ? null : Factory.instance() .createAddress(mChatRoomAddress), + mChatRoom == null ? null : mChatRoom.getLocalAddress(), mSearchAdapter.getContactsSelectedList(), mChatRoomSubject, mSecurityToggle.isChecked()); diff --git a/app/src/main/java/org/linphone/chat/EphemeralFragment.java b/app/src/main/java/org/linphone/chat/EphemeralFragment.java index 8f5553671..ef9a3906b 100644 --- a/app/src/main/java/org/linphone/chat/EphemeralFragment.java +++ b/app/src/main/java/org/linphone/chat/EphemeralFragment.java @@ -58,12 +58,14 @@ public class EphemeralFragment extends Fragment { String address = getArguments().getString("RemoteSipUri"); Address peerAddress = null; + String localSipUri = getArguments().getString("LocalSipUri"); + Address localSipAddress = Factory.instance().createAddress(localSipUri); mChatRoom = null; if (address != null && address.length() > 0) { peerAddress = Factory.instance().createAddress(address); } if (peerAddress != null) { - mChatRoom = LinphoneManager.getCore().getChatRoom(peerAddress); + mChatRoom = LinphoneManager.getCore().getChatRoom(peerAddress, localSipAddress); } if (mChatRoom == null) { return null; diff --git a/app/src/main/java/org/linphone/chat/GroupInfoFragment.java b/app/src/main/java/org/linphone/chat/GroupInfoFragment.java index 331200c2d..127fde021 100644 --- a/app/src/main/java/org/linphone/chat/GroupInfoFragment.java +++ b/app/src/main/java/org/linphone/chat/GroupInfoFragment.java @@ -95,9 +95,16 @@ public class GroupInfoFragment extends Fragment { mGroupChatRoomAddress = Factory.instance().createAddress(address); } + Address localSipAddress = null; + String localSipUri = getArguments().getString("LocalSipUri"); + if (localSipUri != null && localSipUri.length() > 0) { + localSipAddress = Factory.instance().createAddress(localSipUri); + } + mIsAlreadyCreatedGroup = mGroupChatRoomAddress != null; if (mIsAlreadyCreatedGroup) { - mChatRoom = LinphoneManager.getCore().getChatRoom(mGroupChatRoomAddress); + mChatRoom = + LinphoneManager.getCore().getChatRoom(mGroupChatRoomAddress, localSipAddress); } if (mChatRoom == null) { From f2893093d12855ec0d7bb4da12a28474a06dfca0 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 24 Mar 2021 14:27:55 +0100 Subject: [PATCH 31/32] Fixed issue preventing reinvite with video --- app/src/main/java/org/linphone/call/CallManager.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/linphone/call/CallManager.java b/app/src/main/java/org/linphone/call/CallManager.java index cdafb21eb..bf367cce5 100644 --- a/app/src/main/java/org/linphone/call/CallManager.java +++ b/app/src/main/java/org/linphone/call/CallManager.java @@ -347,15 +347,17 @@ public class CallManager { Log.e("[Call Manager] Remote has low bandwidth, won't be able to do video"); return false; } + if (call.getCurrentParams().videoEnabled()) { + Log.e("[Call Manager] Video is already enabled"); + return false; + } CallParams params = core.createCallParams(call); - if (params.videoEnabled()) return false; - // Check if video possible regarding bandwidth limitations mBandwidthManager.updateWithProfileSettings(params); - // Abort if not enough bandwidth... if (!params.videoEnabled()) { + Log.e("[Call Manager] Video can't be enabled"); return false; } From d8a7afcc7ac8f2b3dfbbf5c9c548e9955e2c724b Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 29 Mar 2021 10:39:25 +0200 Subject: [PATCH 32/32] 4.4.0 release --- CHANGELOG.md | 11 ++++++++++- app/build.gradle | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 168466f01..fb2fdc05e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,19 @@ Group changes to describe their impact on the project, as follows: Fixed for any bug fixes. Security to invite users to upgrade in case of vulnerabilities. -### [4.4.0] - Unreleased +### [4.4.0] - 2021-03-29 + +### Added +- Dedicated notification channel for missed calls ### Changed +- SDK updated to 4.5.0 - Min Android version updated from 21 to 23 (Android 6) due to SDK audio routes feature +- Rely on SDK audio routes feature instead of doing it in the application +- User can now check incoming messages delivery status in group chat rooms +- Asking user to read and accept privacy policy and general terms +- Updated translations +- Various crashes & issues fixed ## [4.3.0] - 2020-06-23 diff --git a/app/build.gradle b/app/build.gradle index c878aea7c..f3f61580b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ android { defaultConfig { minSdkVersion 23 targetSdkVersion 29 - versionCode 4320 + versionCode 4400 versionName "${project.version}" applicationId getPackageName() multiDexEnabled true