From adad98f3e24aa9edcbe545e677de28b2bce97191 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 3 Oct 2023 11:53:03 +0200 Subject: [PATCH] Added permissions fragment --- .../assistant/fragment/PermissionsFragment.kt | 176 +++++++++++ .../viewmodel/PermissionsViewModel.kt | 34 +++ .../java/org/linphone/ui/main/MainActivity.kt | 51 ---- .../layout/assistant_permissions_fragment.xml | 279 ++++++++++++++++++ .../res/navigation/assistant_nav_graph.xml | 17 +- app/src/main/res/values/strings.xml | 11 + 6 files changed, 516 insertions(+), 52 deletions(-) create mode 100644 app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt create mode 100644 app/src/main/java/org/linphone/ui/assistant/viewmodel/PermissionsViewModel.kt create mode 100644 app/src/main/res/layout/assistant_permissions_fragment.xml diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt new file mode 100644 index 000000000..f35a1f196 --- /dev/null +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2010-2023 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.ui.assistant.fragment + +import android.Manifest +import android.content.pm.PackageManager +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.UiThread +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import androidx.navigation.navGraphViewModels +import org.linphone.R +import org.linphone.core.tools.Log +import org.linphone.databinding.AssistantPermissionsFragmentBinding +import org.linphone.ui.assistant.viewmodel.PermissionsViewModel + +@UiThread +class PermissionsFragment : Fragment() { + companion object { + private const val TAG = "[Permissions Fragment]" + } + + private lateinit var binding: AssistantPermissionsFragmentBinding + + private val viewModel: PermissionsViewModel by navGraphViewModels( + R.id.assistant_nav_graph + ) + + private val requestPermissionLauncher = registerForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { permissions -> + permissions.entries.forEach() { + val permissionName = it.key + val isGranted = it.value + + when (permissionName) { + "READ_CONTACTS" -> { + viewModel.readContacts.value = isGranted + } + "POST_NOTIFICATIONS" -> { + viewModel.postNotifications.value = isGranted + } + "RECORD_AUDIO" -> { + viewModel.recordAudio.value = isGranted + } + "CAMERA" -> { + viewModel.accessCamera.value = isGranted + } + else -> {} + } + + if (isGranted) { + Log.i("Permission [$permissionName] is now granted") + } else { + Log.i("Permission [$permissionName] has been denied") + } + } + + checkIfAllPermissionsHaveBeenGranted() + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = AssistantPermissionsFragmentBinding.inflate(layoutInflater) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.lifecycleOwner = viewLifecycleOwner + binding.viewModel = viewModel + + binding.setBackClickListener { + findNavController().popBackStack() + } + + binding.setGrantReadContactsClickListener { + Log.i("$TAG Requesting READ_CONTACTS permission") + requestPermissionLauncher.launch(arrayOf(Manifest.permission.READ_CONTACTS)) + } + + // TODO FIXME: use compat for older Androids + binding.setGrantPostNotificationsClickListener { + Log.i("$TAG Requesting POST_NOTIFICATIONS permission") + requestPermissionLauncher.launch(arrayOf(Manifest.permission.POST_NOTIFICATIONS)) + } + + binding.setGrantRecordAudioClickListener { + Log.i("$TAG Requesting RECORD_AUDIO permission") + requestPermissionLauncher.launch(arrayOf(Manifest.permission.RECORD_AUDIO)) + } + + binding.setGrantAccessCameraClickListener { + Log.i("$TAG Requesting CAMERA permission") + requestPermissionLauncher.launch(arrayOf(Manifest.permission.CAMERA)) + } + + binding.setSkipClickListener { + Log.i("$TAG User clicked skip...") + goToLoginFragment() + } + + if (ContextCompat.checkSelfPermission( + requireContext(), + Manifest.permission.MANAGE_OWN_CALLS + ) != PackageManager.PERMISSION_GRANTED + ) { + requestPermissionLauncher.launch(arrayOf(Manifest.permission.MANAGE_OWN_CALLS)) + } + } + + override fun onResume() { + super.onResume() + + viewModel.readContacts.value = ContextCompat.checkSelfPermission( + requireContext(), + Manifest.permission.READ_CONTACTS + ) == PackageManager.PERMISSION_GRANTED + + // TODO FIXME: use compat for older Androids + viewModel.postNotifications.value = ContextCompat.checkSelfPermission( + requireContext(), + Manifest.permission.POST_NOTIFICATIONS + ) == PackageManager.PERMISSION_GRANTED + + viewModel.recordAudio.value = ContextCompat.checkSelfPermission( + requireContext(), + Manifest.permission.RECORD_AUDIO + ) == PackageManager.PERMISSION_GRANTED + + viewModel.accessCamera.value = ContextCompat.checkSelfPermission( + requireContext(), + Manifest.permission.CAMERA + ) == PackageManager.PERMISSION_GRANTED + + checkIfAllPermissionsHaveBeenGranted() + } + + private fun goToLoginFragment() { + val action = PermissionsFragmentDirections.actionPermissionsFragmentToLoginFragment() + findNavController().navigate(action) + } + + private fun checkIfAllPermissionsHaveBeenGranted() { + if (viewModel.readContacts.value == true && viewModel.postNotifications.value == true && viewModel.recordAudio.value == true && viewModel.accessCamera.value == true) { + Log.i("$TAG All permissions are granted, continuing to login fragment") + goToLoginFragment() + } + } +} diff --git a/app/src/main/java/org/linphone/ui/assistant/viewmodel/PermissionsViewModel.kt b/app/src/main/java/org/linphone/ui/assistant/viewmodel/PermissionsViewModel.kt new file mode 100644 index 000000000..b2870f29d --- /dev/null +++ b/app/src/main/java/org/linphone/ui/assistant/viewmodel/PermissionsViewModel.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010-2023 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.ui.assistant.viewmodel + +import androidx.annotation.UiThread +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class PermissionsViewModel @UiThread constructor() : ViewModel() { + val readContacts = MutableLiveData() + + val postNotifications = MutableLiveData() + + val recordAudio = MutableLiveData() + + val accessCamera = MutableLiveData() +} diff --git a/app/src/main/java/org/linphone/ui/main/MainActivity.kt b/app/src/main/java/org/linphone/ui/main/MainActivity.kt index b47cc6a11..85a8933a3 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -43,13 +43,6 @@ import org.linphone.utils.slideInToastFromTopForDuration @UiThread class MainActivity : AppCompatActivity() { - companion object { - private const val CONTACTS_PERMISSION_REQUEST = 0 - private const val CAMERA_PERMISSION_REQUEST = 1 - private const val RECORD_AUDIO_PERMISSION_REQUEST = 2 - private const val POST_NOTIFICATIONS_PERMISSION_REQUEST = 3 - private const val MANAGE_OWN_CALLS_PERMISSION_REQUEST = 4 - } private lateinit var binding: MainActivityBinding @@ -101,38 +94,6 @@ class MainActivity : AppCompatActivity() { // TODO FIXME: uncomment // startActivity(Intent(this, WelcomeActivity::class.java)) - if (checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { - requestPermissions( - arrayOf(Manifest.permission.READ_CONTACTS), - CONTACTS_PERMISSION_REQUEST - ) - } - if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - requestPermissions( - arrayOf(Manifest.permission.CAMERA), - CAMERA_PERMISSION_REQUEST - ) - } - if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { - requestPermissions( - arrayOf(Manifest.permission.RECORD_AUDIO), - RECORD_AUDIO_PERMISSION_REQUEST - ) - } - if (checkSelfPermission(Manifest.permission.MANAGE_OWN_CALLS) != PackageManager.PERMISSION_GRANTED) { - requestPermissions( - arrayOf(Manifest.permission.MANAGE_OWN_CALLS), - MANAGE_OWN_CALLS_PERMISSION_REQUEST - ) - } - // TODO FIXME : use compatibility - if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - requestPermissions( - arrayOf(Manifest.permission.POST_NOTIFICATIONS), - POST_NOTIFICATIONS_PERMISSION_REQUEST - ) - } - coreContext.greenToastToShowEvent.observe(this) { it.consume { pair -> val message = pair.first @@ -142,18 +103,6 @@ class MainActivity : AppCompatActivity() { } } - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { - if (requestCode == CONTACTS_PERMISSION_REQUEST && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - loadContacts() - } - - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - } - @SuppressLint("RtlHardcoded") fun toggleDrawerMenu() { if (binding.drawerMenu.isDrawerOpen(Gravity.LEFT)) { diff --git a/app/src/main/res/layout/assistant_permissions_fragment.xml b/app/src/main/res/layout/assistant_permissions_fragment.xml new file mode 100644 index 000000000..57ccd0473 --- /dev/null +++ b/app/src/main/res/layout/assistant_permissions_fragment.xml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/assistant_nav_graph.xml b/app/src/main/res/navigation/assistant_nav_graph.xml index 46cb36fe3..50970ba87 100644 --- a/app/src/main/res/navigation/assistant_nav_graph.xml +++ b/app/src/main/res/navigation/assistant_nav_graph.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/assistant_nav_graph" - app:startDestination="@id/loginFragment"> + app:startDestination="@id/permissionsFragment"> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d48572d2a..a65505c44 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -151,6 +151,17 @@ Unexpected error occurred, please try again later Wrong username or password Failed to login: error code is %i + Grant permissions + + To be able to work properly, we need you to grand the application the following permissions.\n\nIf you don\'t, some features won\'t be available, but you can grant them later. + Read contacts + This allows us to import your address-book in &appName; + Post notifications + To notify incoming calls & chat messages + Record audio + For audio calls, duh! + Access camera + For video calls & scan QR codes Manage the profile Connected