Commit 1eadbde2 authored by Christophe Deschamps's avatar Christophe Deschamps
Browse files

My Account + fix file observer on api < 29


Former-commit-id: 6f808b901bb594a023bd2d5c9f0165d65870952a
parent 49335baa
This diff is collapsed.
......@@ -4,13 +4,12 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services'
apply plugin: "androidx.navigation.safeargs"
apply plugin: 'com.google.firebase.crashlytics'
repositories {
/*
maven {
url file(LinphoneSdkBuildDir + '/maven_repository/')
}*/
}
maven {
url "https://linphone.org/maven_repository"
}
......@@ -44,7 +43,16 @@ android {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
firebaseCrashlytics {
nativeSymbolUploadEnabled true
}
}
debug {
firebaseCrashlytics {
nativeSymbolUploadEnabled true
}
}
}
compileOptions {
......@@ -83,9 +91,11 @@ dependencies {
kapt 'com.github.bumptech.glide:compiler:4.11.0'
implementation 'com.caverock:androidsvg-aar:1.4'
implementation 'com.google.firebase:firebase-messaging:20.2.0'
implementation 'com.google.firebase:firebase-analytics:17.4.2'
implementation 'com.google.firebase:firebase-analytics:17.4.3'
implementation 'com.google.firebase:firebase-crashlytics:17.0.1'
implementation 'com.github.ybq:Android-SpinKit:1.4.0'
implementation "androidx.media:media:1.1.0"
implementation 'com.google.firebase:firebase-crashlytics-ndk:17.0.1'
}
......
......@@ -36,5 +36,6 @@ xmlrpc_url=https://subscribe.linphone.org:444/wizard.php
; MD5 / SHA-256
password_algo=SHA-256
domain=sip.linphone.org
freesip_url=https://www.linphone.org/freesip/home
## End of factory rc
......@@ -208,6 +208,7 @@ class MainActivity : GenericActivity() {
R.id.navigation_history -> Texts.get("history")
R.id.navigation_about -> Texts.get("about")
R.id.navigation_settings -> Texts.get("settings")
R.id.navigation_account -> Texts.get("menu_account")
else -> null
}
}
......
......@@ -27,14 +27,19 @@ import android.graphics.BlendModeColorFilter
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.FileObserver
import android.os.Vibrator
import android.view.WindowManager
import androidx.core.app.NotificationManagerCompat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.lindoor.LindoorApplication
import org.lindoor.compatibility.Api23Compatibility
import org.lindoor.compatibility.Api25Compatibility
import org.lindoor.compatibility.Api26Compatibility
import org.linphone.mediastream.Version
import java.io.File
@Suppress("DEPRECATION")
......@@ -120,5 +125,27 @@ class Compatibility {
}
}
// Lindoor
fun fileObserverWithMainThreadRunnable(file: File, runnable: Runnable): FileObserver {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return object : FileObserver(file, ATTRIB) {
override fun onEvent(event: Int, file: String?) {
GlobalScope.launch(context = Dispatchers.Main) {
runnable.run()
}
}
}
} else {
return object : FileObserver(file.absolutePath, ATTRIB) {
override fun onEvent(event: Int, file: String?) {
GlobalScope.launch(context = Dispatchers.Main) {
runnable.run()
}
}
}
}
}
}
}
package org.lindoor.customisation
import org.lindoor.customisation.Customisation.textsConfig
import org.lindoor.utils.cdlog
import java.util.*
object Texts {
......@@ -18,31 +19,31 @@ object Texts {
return text
}
private fun pureGet(key: String): String {
private fun pureGet(key: String):String {
val deviceLanguage = Locale.getDefault().language.toLowerCase(Locale.ROOT)
return textsConfig.let { config ->
config.getString(key, deviceLanguage, null)?.also { translation ->
config.getString(key,deviceLanguage,null)?.also { translation ->
return translation
} ?: config.getString(key, "default", null)?.also { default ->
} ?: config.getString(key,"default",null)?.also {default ->
return default
} ?: key
}
}
fun get(textKey: String, args: Array<String>? = null): String {
return formatText(textKey, args)
return formatText(textKey,args)
}
fun get(textKey: String, oneArg: String): String {
return get(textKey, arrayOf(oneArg))
}
fun get(textKey: String, arg1: String, arg2: String): String {
return get(textKey, arrayOf(arg1, arg2))
fun get(textKey: String, arg1: String, arg2:String): String {
return get(textKey, arrayOf(arg1,arg2))
}
fun get(key: String): String {
return pureGet(key).replace("{appname}", appName).replace("\n", System.lineSeparator())
return pureGet(key).replace("{appname}",appName).replace("\\n",System.lineSeparator())
}
}
......@@ -3,6 +3,7 @@ package org.lindoor.entities
import androidx.lifecycle.MutableLiveData
import org.lindoor.LindoorApplication
import org.lindoor.LindoorApplication.Companion.coreContext
import org.lindoor.LindoorApplication.Companion.corePreferences
import org.lindoor.utils.extensions.xDigitsUUID
import org.linphone.core.AccountCreator
import org.linphone.core.AccountCreatorListenerStub
......@@ -19,6 +20,10 @@ object Account {
return coreContext.core.proxyConfigList.isNotEmpty()
}
fun get(): ProxyConfig? {
return coreContext.core.defaultProxyConfig
}
fun lindoorAccountCreate(accountCreator: AccountCreator) {
accountCreator.createProxyConfig().refKey = PUSH_GW_REF_KEY
}
......
package org.lindoor.linphonecore.extensions
import org.lindoor.customisation.Texts
import org.linphone.core.RegistrationState
fun RegistrationState.toHumanReadable():String {
return when (this) {
RegistrationState.None -> Texts.get("registration_state_none")
RegistrationState.Progress -> Texts.get("registration_state_progress")
RegistrationState.Ok -> Texts.get("registration_state_ok")
RegistrationState.Failed -> Texts.get("registration_state_failed")
RegistrationState.Cleared -> Texts.get("registration_state_cleared")
}
}
package org.lindoor.ui.account
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.fragment_account.view.*
import kotlinx.android.synthetic.main.widget_round_rect_button.view.*
import org.lindoor.LindoorApplication
import org.lindoor.databinding.FragmentAccountBinding
import org.lindoor.entities.Account
import org.lindoor.utils.DialogUtil
class AccountFragment : Fragment() {
......@@ -16,7 +26,44 @@ class AccountFragment : Fragment() {
savedInstanceState: Bundle?
): View? {
val binding = FragmentAccountBinding.inflate(inflater, container, false)
binding.coreContext = LindoorApplication.coreContext
val model = ViewModelProvider(this).get(AccountViewModel::class.java)
binding.model = model
binding.lifecycleOwner = this
binding.root.refresh_registers.root.setOnClickListener {
model.refreshRegisters()
}
binding.root.change_lindoor_password.root.setOnClickListener {
gotoFreeSip()
}
binding.root.delete_lindoor_account.root.setOnClickListener {
gotoFreeSip()
}
binding.root.disconnect.root.setOnClickListener {
DialogUtil.confirm(
"menu_disconnect",
"disconnect_confirm_message",
{ _: DialogInterface, _: Int ->
Account.disconnect()
findNavController().navigateUp()
})
}
return binding.root
}
fun gotoFreeSip() {
DialogUtil.confirm(
"account_manage_on_freesip_title",
"account_manage_on_freesip_message",
{ _: DialogInterface, _: Int ->
val browserIntent =
Intent(Intent.ACTION_VIEW, Uri.parse(LindoorApplication.corePreferences.config.getString("assistant","freesip_url","www.linphone.org")))
startActivity(browserIntent)
},confirmTextKey="continue")
}
}
......@@ -2,11 +2,62 @@ package org.lindoor.ui.account
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.lindoor.LindoorApplication
import org.lindoor.customisation.Texts
import org.lindoor.entities.Account
import org.lindoor.entities.Device
import org.lindoor.linphonecore.extensions.callLogsWithNonEmptyCallId
import org.lindoor.linphonecore.extensions.isNew
import org.lindoor.linphonecore.extensions.toHumanReadable
import org.lindoor.store.DeviceStore
import org.linphone.core.*
class AccountViewModel : ViewModel() {
val devices = MutableLiveData<ArrayList<Device>>().apply {
value = DeviceStore.devices
val account = Account.get()
val pushGw = Account.pushGateway()
val accountDesc = MutableLiveData(getDescription("account_info",account))
val pushGWDesc = MutableLiveData(getDescription("push_account_info",pushGw))
private val coreListener = object : CoreListenerStub() {
override fun onRegistrationStateChanged(
lc: Core?,
cfg: ProxyConfig?,
cstate: RegistrationState?,
message: String?
) {
if (cfg != null) {
if (cfg == account)
accountDesc.value = getDescription("account_info",account)
if (cfg == pushGw)
pushGWDesc.value = getDescription("push_account_info",pushGw)
}
}
}
init {
LindoorApplication.coreContext.core.addListener(coreListener)
}
override fun onCleared() {
LindoorApplication.coreContext.core.removeListener(coreListener)
super.onCleared()
}
fun refreshRegisters() {
account?.refreshRegister()
pushGw?.refreshRegister()
}
fun getDescription(key:String, proxyConfig: ProxyConfig?): String? {
return account?.state?.toHumanReadable()?.let {
proxyConfig?.identityAddress?.asStringUriOnly()?.let { it1 ->
Texts.get(key, it1,
it
)
}
}
}
}
......@@ -27,7 +27,7 @@ class LoginSipAccountViewModel :
)
val moreOptionsOpened = MutableLiveData(false)
var pushReady = MutableLiveData(false)
val pushReady = MutableLiveData<Boolean>()
fun valid(): Boolean {
......
......@@ -8,7 +8,7 @@ import com.bumptech.glide.signature.ObjectKey
import org.lindoor.customisation.Theme
import org.lindoor.entities.Device
import org.lindoor.utils.extensions.existsAndIsNotEmpty
import org.lindoor.utils.fileObserverWithMainThreadRunnable
import org.linphone.compatibility.Compatibility.Companion.fileObserverWithMainThreadRunnable
import java.io.File
......
package org.lindoor.utils
import android.os.FileObserver
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
fun fileObserverWithMainThreadRunnable(file: File, runnable: Runnable): FileObserver {
return object : FileObserver(file, ATTRIB) {
override fun onEvent(event: Int, file: String?) {
GlobalScope.launch(context = Dispatchers.Main) {
runnable.run()
}
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="org.lindoor.customisation.Texts"/>
<import type="android.view.View"/>
<variable
name="coreContext"
type="org.lindoor.linphonecore.CoreContext" />
name="model"
type="org.lindoor.ui.account.AccountViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
gradientBackground='@{"dark_light_vertical_gradient"}'
>
<ImageView
android:id="@+id/lindoor_icon"
android:layout_width="0dp"
android:layout_height="100dp"
android:scaleType="centerInside"
app:layout_constraintBottom_toTopOf="@+id/lindoor_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
src='@{"others/lindoor_icon"}'
/>
<ImageView
android:id="@+id/lindoor_text"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginTop="20dp"
android:scaleType="centerInside"
app:layout_constraintBottom_toTopOf="@+id/lindoor_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lindoor_icon"
src='@{"others/lindoor_text"}'
/>
<TextView
android:id="@+id/lindoor_title"
android:layout_width="0dp"
android:layout_marginTop="10dp"
android:layout_height="wrap_content"
android:textAlignment="textStart"
app:layout_constraintBottom_toTopOf="@+id/texts"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lindoor_text"
style='@{"splash_title"}'
text='@{"splash_title"}'
/>
<RelativeLayout
android:id="@+id/texts"
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
android:layout_height="match_parent"
backgoundcolor='@{"color_c"}'
>
<TextView
android:id="@+id/appversion"
android:layout_width="match_parent"
android:layout_marginTop="10dp"
android:layout_height="wrap_content"
text='@{"app_version"}'
text_args='@{"Android,"+coreContext.appVersion}'
style='@{"about_text"}'
/>
<TextView
android:id="@+id/sdkversion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/appversion"
text='@{"sdk_version"}'
text_args='@{coreContext.sdkVersion}'
style='@{"about_text"}'
/>
<TextView
android:id="@+id/lindoor_link"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:layout_marginTop="38dp"
android:layout_below="@+id/sdkversion"
style='@{"about_link"}'
text='@{"about_link"}'
/>
<TextView
android:id="@+id/licence"
android:layout_width="match_parent"
android:layout_marginTop="9dp"
android:layout_height="wrap_content"
android:layout_below="@+id/lindoor_link"
style='@{"about_text"}'
text='@{"license_text"}'
/>
<TextView
android:id="@+id/copyright"
android:layout_width="match_parent"
android:layout_marginBottom="23dp"
android:layout_height="wrap_content"
android:layout_below="@+id/licence"
style='@{"about_text"}'
text='@{"copyright_text"}'
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
tools:context=".ui.account.AccountFragment">
<TextView
android:id="@+id/account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
app:layout_constraintBottom_toTopOf="@id/pushaccount"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
style='@{"account_info"}'
android:lines="2"
android:text='@{model.accountDesc}' />
<TextView
android:id="@+id/pushaccount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
app:layout_constraintTop_toBottomOf="@id/account"
app:layout_constraintBottom_toTopOf="@id/refresh_registers"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
style='@{"account_info"}'
android:lines="2"
android:visibility="@{model.pushGw != null &amp;&amp; model.account != model.pushGw ? View.VISIBLE : View.GONE}"
android:text='@{model.accountDesc}' />
<org.lindoor.ui.widgets.LRoundRectButton
android:id="@+id/refresh_registers"
android:clickable="true"
android:focusable="true"
android:layout_width="320dp"
android:layout_height="40dp"
android:layout_marginTop="60dp"
app:layout_constraintTop_toBottomOf="@id/pushaccount"
app:layout_constraintBottom_toTopOf="@id/change_lindoor_password"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
primary='@{false}'
text='@{"refresh_registers"}'
/>
<org.lindoor.ui.widgets.LRoundRectButton
android:id="@+id/change_lindoor_password"
android:clickable="true"
android:focusable="true"
android:layout_width="320dp"
android:layout_height="40dp"
android:layout_marginTop="23dp"
app:layout_constraintTop_toBottomOf="@id/refresh_registers"
app:layout_constraintBottom_toTopOf="@id/delete_lindoor_account"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
primary='@{false}'
text='@{"change_password"}'
/>
<org.lindoor.ui.widgets.LRoundRectButton
android:id="@+id/delete_lindoor_account"
android:clickable="true"
android:focusable="true"
android:layout_width="320dp"
android:layout_height="40dp"
android:layout_marginTop="23dp"
app:layout_constraintTop_toBottomOf="@id/change_lindoor_password"
app:layout_constraintBottom_toTopOf="@id/disconnect"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
primary='@{false}'
text='@{"delete_account"}'
/>
<org.lindoor.ui.widgets.LRoundRectButton
android:id="@+id/disconnect"
android:clickable="true"
android:focusable="true"
android:layout_width="320dp"
android:layout_height="40dp"