Refactor: Worked out a better way for moving around the app.

Changed from using ViewPager2 for changing apps of the app.
Added animations for changing to different fragments of the app
This commit is contained in:
HeCodes2Much
2024-05-25 17:47:02 +01:00
parent fc81f750fd
commit 8b1c0a390d
32 changed files with 365 additions and 295 deletions

View File

@@ -4,7 +4,8 @@
<uses-permission android:name="android.permission.SET_WALLPAPER" /> <uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /> <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" <uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" /> android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" /> <uses-permission android:name="android.permission.USE_BIOMETRIC" />
@@ -13,11 +14,11 @@
tools:ignore="QueryAllPackagesPermission" /> tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" /> <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.BIND_APPWIDGET" <uses-permission
android:name="android.permission.BIND_APPWIDGET"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<queries> <queries>
<intent> <intent>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@@ -34,10 +35,6 @@
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.Launcher"> android:theme="@style/Theme.Launcher">
<activity
android:name=".ui.activities.SettingsActivity"
android:exported="false" />
<activity <activity
android:name=".ui.activities.LauncherActivity" android:name=".ui.activities.LauncherActivity"
android:enabled="false" android:enabled="false"
@@ -95,13 +92,14 @@
android:resource="@xml/policies" /> android:resource="@xml/policies" />
<intent-filter> <intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
<action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<service <service
android:name=".accessibility.MyAccessibilityService" android:name=".accessibility.ActionService"
android:exported="false" android:exported="false"
android:label="@string/app_name" android:label="@string/accessibility_service_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<meta-data <meta-data
android:name="android.accessibilityservice" android:name="android.accessibilityservice"

View File

@@ -65,5 +65,4 @@ object Constants {
const val APP_WIDGET_HOST_ID = 1024 const val APP_WIDGET_HOST_ID = 1024
const val TRIPLE_TAP_DELAY_MS = 300 const val TRIPLE_TAP_DELAY_MS = 300
const val LONG_PRESS_DELAY_MS = 500 const val LONG_PRESS_DELAY_MS = 500
const val REQUEST_CODE_ENABLE_ADMIN = 123
} }

View File

@@ -12,7 +12,7 @@ import com.github.droidworksstudio.launcher.R
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
class MyAccessibilityService : AccessibilityService() { class ActionService : AccessibilityService() {
private var info: AccessibilityServiceInfo = AccessibilityServiceInfo() private var info: AccessibilityServiceInfo = AccessibilityServiceInfo()
@@ -20,7 +20,8 @@ class MyAccessibilityService : AccessibilityService() {
mInstance = WeakReference(this) mInstance = WeakReference(this)
info.apply { info.apply {
eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED or AccessibilityEvent.TYPE_VIEW_FOCUSED eventTypes =
AccessibilityEvent.TYPE_VIEW_CLICKED or AccessibilityEvent.TYPE_VIEW_FOCUSED
feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC
@@ -95,8 +96,8 @@ class MyAccessibilityService : AccessibilityService() {
return return
} }
private var mInstance: WeakReference<MyAccessibilityService> = WeakReference(null) private var mInstance: WeakReference<ActionService> = WeakReference(null)
fun instance(): MyAccessibilityService? { fun instance(): ActionService? {
return mInstance.get() return mInstance.get()
} }
} }

View File

@@ -27,7 +27,7 @@ import androidx.appcompat.widget.LinearLayoutCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.github.droidworksstudio.launcher.Constants import com.github.droidworksstudio.launcher.Constants
import com.github.droidworksstudio.launcher.R import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.accessibility.MyAccessibilityService import com.github.droidworksstudio.launcher.accessibility.ActionService
import com.github.droidworksstudio.launcher.data.entities.AppInfo import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.ui.activities.FakeHomeActivity import com.github.droidworksstudio.launcher.ui.activities.FakeHomeActivity
import java.util.Calendar import java.util.Calendar
@@ -95,8 +95,8 @@ class AppHelper @Inject constructor() {
.invoke(context.getSystemService(Constants.NOTIFICATION_SERVICE)) .invoke(context.getSystemService(Constants.NOTIFICATION_SERVICE))
} catch (exception: Exception) { } catch (exception: Exception) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
MyAccessibilityService.runAccessibilityMode(context) ActionService.runAccessibilityMode(context)
MyAccessibilityService.instance()?.openNotifications() ActionService.instance()?.openNotifications()
} }
exception.printStackTrace() exception.printStackTrace()
} }
@@ -110,8 +110,8 @@ class AppHelper @Inject constructor() {
.invoke(context.getSystemService(Constants.QUICKSETTINGS_SERVICE)) .invoke(context.getSystemService(Constants.QUICKSETTINGS_SERVICE))
} catch (exception: Exception) { } catch (exception: Exception) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
MyAccessibilityService.runAccessibilityMode(context) ActionService.runAccessibilityMode(context)
MyAccessibilityService.instance()?.openQuickSettings() ActionService.instance()?.openQuickSettings()
} }
exception.printStackTrace() exception.printStackTrace()
} }

View File

@@ -1,10 +1,10 @@
package com.github.droidworksstudio.launcher.helper package com.github.droidworksstudio.launcher.helper
import android.content.Intent
import androidx.biometric.BiometricManager import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.github.droidworksstudio.launcher.R import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo import com.github.droidworksstudio.launcher.data.entities.AppInfo
import javax.inject.Inject import javax.inject.Inject
@@ -56,32 +56,46 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) {
} }
} }
fun startFingerprintSettingsAuth(targetClass: Class<*>) { fun startFingerprintSettingsAuth(runNavigation: Int) {
val executor = ContextCompat.getMainExecutor(fragment.requireContext()) val executor = ContextCompat.getMainExecutor(fragment.requireContext())
val biometricPrompt = BiometricPrompt(fragment, executor, object : BiometricPrompt.AuthenticationCallback() { val biometricPrompt =
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { BiometricPrompt(fragment, executor, object : BiometricPrompt.AuthenticationCallback() {
sendToTargetActivity(targetClass) override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
} fragment.findNavController().navigate(runNavigation)
override fun onAuthenticationFailed() {
appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence) {
when (errorCode) {
BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_cancel))
else -> appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_error).format(errorMessage, errorCode))
} }
}
}) override fun onAuthenticationFailed() {
appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_failed)
)
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence) {
when (errorCode) {
BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_cancel)
)
else -> appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_error)
.format(errorMessage, errorCode)
)
}
}
})
val promptInfoBuilder = BiometricPrompt.PromptInfo.Builder() val promptInfoBuilder = BiometricPrompt.PromptInfo.Builder()
.setTitle(fragment.getString(R.string.authentication_title)) .setTitle(fragment.getString(R.string.authentication_title))
.setSubtitle(fragment.getString(R.string.authentication_subtitle)) .setSubtitle(fragment.getString(R.string.authentication_subtitle))
val authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL val authenticators =
val canAuthenticate = BiometricManager.from(fragment.requireContext()).canAuthenticate(authenticators) BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL
val canAuthenticate =
BiometricManager.from(fragment.requireContext()).canAuthenticate(authenticators)
if (canAuthenticate == BiometricManager.BIOMETRIC_SUCCESS) { if (canAuthenticate == BiometricManager.BIOMETRIC_SUCCESS) {
promptInfoBuilder.setAllowedAuthenticators(authenticators) promptInfoBuilder.setAllowedAuthenticators(authenticators)
@@ -95,17 +109,23 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) {
BiometricManager.BIOMETRIC_SUCCESS -> biometricPrompt.authenticate(promptInfo) BiometricManager.BIOMETRIC_SUCCESS -> biometricPrompt.authenticate(promptInfo)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE,
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE,
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> sendToTargetActivity(targetClass) BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> sendToTarget(runNavigation)
else -> appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_failed))
else -> appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_failed)
)
} }
} }
fun sendToTargetActivity(targetClass: Class<*>) { private fun sendToTarget(runNavigation: Int) {
try { try {
val intent = Intent(fragment.requireActivity(), targetClass) fragment.findNavController().navigate(runNavigation)
fragment.requireActivity().startActivity(intent)
} catch (e: Exception) { } catch (e: Exception) {
appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_failed)) appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_failed)
)
} }
} }
} }

View File

@@ -96,6 +96,7 @@ internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
open fun onLongClick() {} open fun onLongClick() {}
open fun onDoubleClick() {} open fun onDoubleClick() {}
open fun onTripleClick() {} open fun onTripleClick() {}
init { init {
gestureDetector = GestureDetector(c, GestureListener()) gestureDetector = GestureDetector(c, GestureListener())
} }

View File

@@ -1,12 +1,15 @@
package com.github.droidworksstudio.launcher.ui.activities package com.github.droidworksstudio.launcher.ui.activities
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager
import android.content.Intent
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@@ -15,6 +18,7 @@ import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp import androidx.navigation.ui.navigateUp
import com.github.droidworksstudio.launcher.Constants
import com.github.droidworksstudio.launcher.R import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.ActivityMainBinding import com.github.droidworksstudio.launcher.databinding.ActivityMainBinding
import com.github.droidworksstudio.launcher.helper.AppHelper import com.github.droidworksstudio.launcher.helper.AppHelper
@@ -143,5 +147,4 @@ class MainActivity : AppCompatActivity() {
if (navController.currentDestination?.id != R.id.HomeFragment) if (navController.currentDestination?.id != R.id.HomeFragment)
navController.popBackStack(R.id.HomeFragment, false) navController.popBackStack(R.id.HomeFragment, false)
} }
} }

View File

@@ -1,74 +0,0 @@
package com.github.droidworksstudio.launcher.ui.activities
import android.os.Bundle
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.ActivitySettingsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class SettingsActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingsBinding
private lateinit var appBarConfiguration: AppBarConfiguration
private val preferenceViewModel: PreferenceViewModel by viewModels()
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var appHelper: AppHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
// Find the NavHostFragment
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_content_settings) as NavHostFragment
// Retrieve the NavController
val navController = navHostFragment.navController
appBarConfiguration = AppBarConfiguration(navController.graph)
initializeDependencies()
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_settings)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
private fun initializeDependencies() {
preferenceViewModel.setShowStatusBar(preferenceHelper.showStatusBar)
}
private fun observeUI(){
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
preferenceViewModel.setShowStatusBar(preferenceHelper.showStatusBar)
preferenceViewModel.showStatusBarLiveData.observe(this) {
if (it) appHelper.showStatusBar(this.window)
else appHelper.hideStatusBar(this.window) }
}
override fun onResume() {
super.onResume()
observeUI()
}
}

View File

@@ -10,9 +10,10 @@ import com.github.droidworksstudio.launcher.databinding.ItemDrawBinding
import com.github.droidworksstudio.launcher.helper.PreferenceHelper import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
class DrawAdapter(private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener, class DrawAdapter(
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener, private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val preferenceHelperProvider: PreferenceHelper private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener,
private val preferenceHelperProvider: PreferenceHelper
) : ) :
ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()) { ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()) {
@@ -27,7 +28,12 @@ class DrawAdapter(private val onAppClickedListener: OnItemClickedListener.OnApps
) )
val preferenceHelper = preferenceHelperProvider val preferenceHelper = preferenceHelperProvider
return DrawViewHolder(binding, onAppClickedListener, onAppLongClickedListener, preferenceHelper) return DrawViewHolder(
binding,
onAppClickedListener,
onAppLongClickedListener,
preferenceHelper
)
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
@@ -36,7 +42,7 @@ class DrawAdapter(private val onAppClickedListener: OnItemClickedListener.OnApps
(holder as DrawViewHolder).bind(appInfo) (holder as DrawViewHolder).bind(appInfo)
} }
class DiffCallback : DiffUtil.ItemCallback<AppInfo>() { class DiffCallback : DiffUtil.ItemCallback<AppInfo>() {
override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) = override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem.id == newItem.id oldItem.id == newItem.id

View File

@@ -39,7 +39,8 @@ import javax.inject.Inject
* A simple [Fragment] subclass as the second destination in the navigation. * A simple [Fragment] subclass as the second destination in the navigation.
*/ */
@AndroidEntryPoint @AndroidEntryPoint
class DrawFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, class DrawFragment : Fragment(),
OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.OnAppLongClickedListener, OnItemClickedListener.OnAppLongClickedListener,
OnItemClickedListener.BottomSheetDismissListener, OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener, OnItemClickedListener.OnAppStateClickListener,
@@ -143,7 +144,8 @@ class DrawFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
private fun observeSwipeTouchListener() { private fun observeSwipeTouchListener() {
binding.mainView.setOnTouchListener(getSwipeGestureListener(context)) binding.touchArea.setOnTouchListener(getSwipeGestureListener(context))
binding.drawAdapter.setOnTouchListener(getSwipeGestureListener(context))
} }
private fun getSwipeGestureListener(context: Context): View.OnTouchListener { private fun getSwipeGestureListener(context: Context): View.OnTouchListener {

View File

@@ -8,10 +8,12 @@ import com.github.droidworksstudio.launcher.databinding.ItemDrawBinding
import com.github.droidworksstudio.launcher.helper.PreferenceHelper import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
class DrawViewHolder(private val binding: ItemDrawBinding, class DrawViewHolder(
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener, private val binding: ItemDrawBinding,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener, private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val preferenceHelper: PreferenceHelper): private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener,
private val preferenceHelper: PreferenceHelper
) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun bind(appInfo: AppInfo) { fun bind(appInfo: AppInfo) {
binding.apply { binding.apply {

View File

@@ -10,8 +10,11 @@ import com.github.droidworksstudio.launcher.databinding.ItemFavoriteBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnItemMoveListener import com.github.droidworksstudio.launcher.listener.OnItemMoveListener
class FavoriteAdapter(private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener, class FavoriteAdapter(
) : ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()) ,OnItemMoveListener.OnItemActionListener{ private val onAppClickedListener:
OnItemClickedListener.OnAppsClickedListener,
) : ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()),
OnItemMoveListener.OnItemActionListener {
private lateinit var touchHelper: ItemTouchHelper private lateinit var touchHelper: ItemTouchHelper

View File

@@ -13,6 +13,7 @@ import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager import androidx.recyclerview.widget.StaggeredGridLayoutManager
@@ -24,6 +25,7 @@ import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnItemMoveListener import com.github.droidworksstudio.launcher.listener.OnItemMoveListener
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -32,7 +34,8 @@ import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class FavoriteFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, class FavoriteFragment : Fragment(),
OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.BottomSheetDismissListener, OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener, OnItemClickedListener.OnAppStateClickListener,
OnItemMoveListener.OnItemActionListener, OnItemMoveListener.OnItemActionListener,
@@ -77,6 +80,7 @@ class FavoriteFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener
setupRecyclerView() setupRecyclerView()
observeFavorite() observeFavorite()
observeHomeAppOrder() observeHomeAppOrder()
observeSwipeTouchListener()
} }
private fun setupRecyclerView() { private fun setupRecyclerView() {
@@ -101,6 +105,14 @@ class FavoriteFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener
} }
} }
private fun observeFavorite() {
viewModel.compareInstalledAppInfo()
viewLifecycleOwner.lifecycleScope.launch {
viewModel.favoriteApps.collect {
favoriteAdapter.submitList(it)
}
}
}
private fun observeHomeAppOrder() { private fun observeHomeAppOrder() {
binding.favoriteAdapter.adapter = favoriteAdapter binding.favoriteAdapter.adapter = favoriteAdapter
@@ -165,11 +177,22 @@ class FavoriteFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener
itemTouchHelper.attachToRecyclerView(binding.favoriteAdapter) itemTouchHelper.attachToRecyclerView(binding.favoriteAdapter)
} }
private fun observeFavorite() { @SuppressLint("ClickableViewAccessibility")
viewModel.compareInstalledAppInfo() private fun observeSwipeTouchListener() {
viewLifecycleOwner.lifecycleScope.launch { binding.touchArea.setOnTouchListener(getSwipeGestureListener(context))
viewModel.favoriteApps.collect { binding.favoriteAdapter.setOnTouchListener(getSwipeGestureListener(context))
favoriteAdapter.submitList(it) }
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().popBackStack()
}
override fun onSwipeRight() {
super.onSwipeRight()
findNavController().popBackStack()
} }
} }
} }

View File

@@ -10,11 +10,12 @@ import com.github.droidworksstudio.launcher.databinding.ItemFavoriteBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
class FavoriteViewHolder(private val binding: ItemFavoriteBinding, class FavoriteViewHolder(
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener, private val binding: ItemFavoriteBinding,
private val touchHelper: ItemTouchHelper, private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val touchHelper: ItemTouchHelper,
) : ) :
RecyclerView.ViewHolder(binding.root){ RecyclerView.ViewHolder(binding.root) {
init { init {
binding.appFavoriteDragIcon.setOnTouchListener { _, event -> binding.appFavoriteDragIcon.setOnTouchListener { _, event ->

View File

@@ -12,6 +12,7 @@ import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.StaggeredGridLayoutManager import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.launcher.R import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo import com.github.droidworksstudio.launcher.data.entities.AppInfo
@@ -19,13 +20,15 @@ import com.github.droidworksstudio.launcher.databinding.FragmentHiddenBinding
import com.github.droidworksstudio.launcher.helper.AppHelper import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class HiddenFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, class HiddenFragment : Fragment(),
OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.OnAppLongClickedListener, OnItemClickedListener.OnAppLongClickedListener,
OnItemClickedListener.BottomSheetDismissListener, OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener, OnItemClickedListener.OnAppStateClickListener,
@@ -65,6 +68,7 @@ class HiddenFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
setupRecyclerView() setupRecyclerView()
observeHiddenApps() observeHiddenApps()
observeSwipeTouchListener()
} }
private fun setupRecyclerView() { private fun setupRecyclerView() {
@@ -86,6 +90,26 @@ class HiddenFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
} }
} }
@SuppressLint("ClickableViewAccessibility")
private fun observeSwipeTouchListener() {
binding.touchArea.setOnTouchListener(getSwipeGestureListener(context))
binding.hiddenAdapter.setOnTouchListener(getSwipeGestureListener(context))
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().popBackStack()
}
override fun onSwipeRight() {
super.onSwipeRight()
findNavController().popBackStack()
}
}
}
private fun observeBioAuthCheck(appInfo: AppInfo) { private fun observeBioAuthCheck(appInfo: AppInfo) {
if (!appInfo.lock) { if (!appInfo.lock) {
appHelper.launchApp(context, appInfo) appHelper.launchApp(context, appInfo)

View File

@@ -6,23 +6,25 @@ import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemHiddenBinding import com.github.droidworksstudio.launcher.databinding.ItemHiddenBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
class HiddenViewHolder(private val binding: ItemHiddenBinding, class HiddenViewHolder(
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener, private val binding: ItemHiddenBinding,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener) : private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener
) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun bind(appInfo: AppInfo) { fun bind(appInfo: AppInfo) {
binding.apply { binding.apply {
appHiddenName.text = appInfo.appName appHiddenName.text = appInfo.appName
Log.d("Tag", "Draw Adapter: ${appInfo.appName}") Log.d("Tag", "Draw Adapter: ${appInfo.appName}")
} }
itemView.setOnClickListener { itemView.setOnClickListener {
onAppClickedListener.onAppClicked(appInfo) onAppClickedListener.onAppClicked(appInfo)
} }
itemView.setOnLongClickListener { itemView.setOnLongClickListener {
onAppLongClickedListener.onAppLongClicked(appInfo) onAppLongClickedListener.onAppLongClicked(appInfo)
true true
} }
} }
} }

View File

@@ -11,11 +11,12 @@ import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import javax.inject.Inject import javax.inject.Inject
class HomeAdapter @Inject constructor(private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener, class HomeAdapter @Inject constructor(
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener, private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val preferenceHelperProvider: PreferenceHelper private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener,
private val preferenceHelperProvider: PreferenceHelper
) : ) :
ListAdapter<AppInfo,RecyclerView.ViewHolder>(DiffCallback()) { ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: android.view.ViewGroup, parent: android.view.ViewGroup,
@@ -28,7 +29,12 @@ class HomeAdapter @Inject constructor(private val onAppClickedListener: OnItemCl
) )
val preferenceHelper = preferenceHelperProvider val preferenceHelper = preferenceHelperProvider
return HomeViewHolder(binding, onAppClickedListener, onAppLongClickedListener, preferenceHelper) return HomeViewHolder(
binding,
onAppClickedListener,
onAppLongClickedListener,
preferenceHelper
)
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
@@ -37,7 +43,7 @@ class HomeAdapter @Inject constructor(private val onAppClickedListener: OnItemCl
(holder as HomeViewHolder).bind(appInfo) (holder as HomeViewHolder).bind(appInfo)
} }
class DiffCallback : DiffUtil.ItemCallback<AppInfo>() { class DiffCallback : DiffUtil.ItemCallback<AppInfo>() {
override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) = override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem.id == newItem.id oldItem.id == newItem.id

View File

@@ -20,7 +20,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.StaggeredGridLayoutManager import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.launcher.R import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.accessibility.MyAccessibilityService import com.github.droidworksstudio.launcher.accessibility.ActionService
import com.github.droidworksstudio.launcher.data.entities.AppInfo import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentHomeBinding import com.github.droidworksstudio.launcher.databinding.FragmentHomeBinding
import com.github.droidworksstudio.launcher.helper.AppHelper import com.github.droidworksstudio.launcher.helper.AppHelper
@@ -30,7 +30,6 @@ import com.github.droidworksstudio.launcher.helper.hideKeyboard
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.ui.activities.SettingsActivity
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
@@ -46,7 +45,8 @@ import javax.inject.Inject
* A simple [Fragment] subclass as the default destination in the navigation. * A simple [Fragment] subclass as the default destination in the navigation.
*/ */
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, class HomeFragment : Fragment(),
OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.OnAppLongClickedListener, OnItemClickedListener.OnAppLongClickedListener,
OnItemClickedListener.BottomSheetDismissListener, OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener, OnItemClickedListener.OnAppStateClickListener,
@@ -91,16 +91,16 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initializeInjectedDependencies() initializeInjectedDependencies()
initSwipeTouchListener()
setupBattery() setupBattery()
setupRecyclerView() setupRecyclerView()
observeSwipeTouchListener()
observeUserInterfaceSettings() observeUserInterfaceSettings()
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
private fun initializeInjectedDependencies() { private fun initializeInjectedDependencies() {
context = requireContext() context = requireContext()
binding.mainView.hideKeyboard() binding.nestScrollView.hideKeyboard()
binding.nestScrollView.scrollEventListener = this binding.nestScrollView.scrollEventListener = this
@@ -111,15 +111,6 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
preferenceViewModel.setShowDailyWord(preferenceHelper.showDailyWord) preferenceViewModel.setShowDailyWord(preferenceHelper.showDailyWord)
} }
@SuppressLint("ClickableViewAccessibility")
private fun initSwipeTouchListener() {
binding.nestScrollView.setOnTouchListener(getSwipeGestureListener(context))
binding.clock.setOnClickListener { appHelper.launchClock(context) }
binding.date.setOnClickListener { appHelper.launchCalendar(context) }
binding.battery.setOnClickListener { appHelper.openBatteryManager(context) }
}
private fun setupBattery() { private fun setupBattery() {
batteryReceiver = object : BroadcastReceiver() { batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
@@ -163,8 +154,18 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
} }
} }
@SuppressLint("ClickableViewAccessibility")
private fun observeSwipeTouchListener() {
binding.touchArea.setOnTouchListener(getSwipeGestureListener(context))
binding.nestScrollView.setOnTouchListener(getSwipeGestureListener(context))
binding.clock.setOnClickListener { appHelper.launchClock(context) }
binding.date.setOnClickListener { appHelper.launchCalendar(context) }
binding.battery.setOnClickListener { appHelper.openBatteryManager(context) }
}
private fun observeUserInterfaceSettings() { private fun observeUserInterfaceSettings() {
binding.mainView.hideKeyboard() binding.nestScrollView.hideKeyboard()
preferenceViewModel.setShowTime(preferenceHelper.showTime) preferenceViewModel.setShowTime(preferenceHelper.showTime)
preferenceViewModel.setShowDate(preferenceHelper.showDate) preferenceViewModel.setShowDate(preferenceHelper.showDate)
@@ -226,10 +227,13 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
} }
private fun observeBioAuthCheck(appInfo: AppInfo) { private fun observeBioAuthCheck(appInfo: AppInfo) {
if (!appInfo.lock) appHelper.launchApp( if (!appInfo.lock)
context, appHelper.launchApp(
appInfo context,
) else fingerHelper.startFingerprintAuth(appInfo, this) appInfo
)
else
fingerHelper.startFingerprintAuth(appInfo, this)
} }
private fun showSelectedApp(appInfo: AppInfo) { private fun showSelectedApp(appInfo: AppInfo) {
@@ -252,8 +256,8 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
override fun onDoubleClick() { override fun onDoubleClick() {
super.onDoubleClick() super.onDoubleClick()
if (preferenceHelper.tapLockScreen) { if (preferenceHelper.tapLockScreen) {
MyAccessibilityService.runAccessibilityMode(context) ActionService.runAccessibilityMode(context)
MyAccessibilityService.instance()?.lockScreen() ActionService.instance()?.lockScreen()
} else { } else {
return return
} }
@@ -267,7 +271,6 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
override fun onSwipeRight() { override fun onSwipeRight() {
super.onSwipeRight() super.onSwipeRight()
findNavController().navigate(R.id.action_HomeFragment_to_FavoriteFragment) findNavController().navigate(R.id.action_HomeFragment_to_FavoriteFragment)
} }
override fun onSwipeDown() { override fun onSwipeDown() {
@@ -320,7 +323,7 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
}) })
if (preferenceHelper.settingsLock) { if (preferenceHelper.settingsLock) {
fingerHelper.startFingerprintSettingsAuth(SettingsActivity::class.java) fingerHelper.startFingerprintSettingsAuth(R.id.action_HomeFragment_to_SettingsFragment)
} else { } else {
findNavController().navigate(R.id.action_HomeFragment_to_SettingsFragment) findNavController().navigate(R.id.action_HomeFragment_to_SettingsFragment)
} }
@@ -335,12 +338,12 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
binding.mainView.hideKeyboard() binding.nestScrollView.hideKeyboard()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
binding.mainView.hideKeyboard() binding.nestScrollView.hideKeyboard()
observeUserInterfaceSettings() observeUserInterfaceSettings()
observeFavoriteAppList() observeFavoriteAppList()
} }

View File

@@ -1,5 +1,6 @@
package com.github.droidworksstudio.launcher.ui.home package com.github.droidworksstudio.launcher.ui.home
import android.annotation.SuppressLint
import android.util.Log import android.util.Log
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
@@ -11,13 +12,13 @@ import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import javax.inject.Inject import javax.inject.Inject
class HomeViewHolder @Inject constructor( class HomeViewHolder @Inject constructor(
private val binding: ItemHomeBinding, private val binding: ItemHomeBinding,
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener, private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener, private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener,
private val preferenceHelper: PreferenceHelper, private val preferenceHelper: PreferenceHelper,
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
@SuppressLint("ClickableViewAccessibility")
fun bind(appInfo: AppInfo) { fun bind(appInfo: AppInfo) {
binding.apply { binding.apply {
val layoutParams = LinearLayoutCompat.LayoutParams( val layoutParams = LinearLayoutCompat.LayoutParams(
@@ -36,26 +37,33 @@ class HomeViewHolder @Inject constructor(
Log.d("Tag", "Home Adapter Color: ${preferenceHelper.appColor}") Log.d("Tag", "Home Adapter Color: ${preferenceHelper.appColor}")
if (preferenceHelper.showAppIcon) { if (preferenceHelper.showAppIcon) {
val appIcon = binding.root.context.packageManager.getApplicationIcon(appInfo.packageName) val appIcon =
binding.root.context.packageManager.getApplicationIcon(appInfo.packageName)
when (preferenceHelper.homeAppAlignment) { when (preferenceHelper.homeAppAlignment) {
Gravity.START -> { Gravity.START -> {
appHomeLeftIcon.setImageDrawable(appIcon) appHomeLeftIcon.setImageDrawable(appIcon)
appHomeLeftIcon.layoutParams.width = preferenceHelper.appTextSize.toInt() * 3 appHomeLeftIcon.layoutParams.width =
appHomeLeftIcon.layoutParams.height = preferenceHelper.appTextSize.toInt() * 3 preferenceHelper.appTextSize.toInt() * 3
appHomeLeftIcon.layoutParams.height =
preferenceHelper.appTextSize.toInt() * 3
appHomeLeftIcon.visibility = View.VISIBLE appHomeLeftIcon.visibility = View.VISIBLE
} }
Gravity.END -> { Gravity.END -> {
appHomeRightIcon.setImageDrawable(appIcon) appHomeRightIcon.setImageDrawable(appIcon)
appHomeRightIcon.layoutParams.width = preferenceHelper.appTextSize.toInt() * 3 appHomeRightIcon.layoutParams.width =
appHomeRightIcon.layoutParams.height = preferenceHelper.appTextSize.toInt() * 3 preferenceHelper.appTextSize.toInt() * 3
appHomeRightIcon.layoutParams.height =
preferenceHelper.appTextSize.toInt() * 3
appHomeRightIcon.visibility = View.VISIBLE appHomeRightIcon.visibility = View.VISIBLE
} }
} }
} }
} }
itemView.setOnClickListener { onAppClickedListener.onAppClicked(appInfo) } itemView.setOnClickListener {
onAppClickedListener.onAppClicked(appInfo)
}
itemView.setOnLongClickListener { itemView.setOnLongClickListener {
onAppLongClickedListener.onAppLongClicked(appInfo) onAppLongClickedListener.onAppLongClicked(appInfo)

View File

@@ -1,6 +1,7 @@
package com.github.droidworksstudio.launcher.ui.settings package com.github.droidworksstudio.launcher.ui.settings
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -16,6 +17,7 @@ import com.github.droidworksstudio.launcher.databinding.FragmentSettingsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.helper.restartApp import com.github.droidworksstudio.launcher.helper.restartApp
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AlignmentBottomSheetDialogFragment import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AlignmentBottomSheetDialogFragment
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.ColorBottomSheetDialogFragment import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.ColorBottomSheetDialogFragment
@@ -26,7 +28,8 @@ import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class SettingsFragment : Fragment(), ScrollEventListener { class SettingsFragment : Fragment(),
ScrollEventListener {
private var _binding: FragmentSettingsBinding? = null private var _binding: FragmentSettingsBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
@@ -41,6 +44,8 @@ class SettingsFragment : Fragment(), ScrollEventListener {
private lateinit var navController: NavController private lateinit var navController: NavController
private lateinit var context: Context
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
@@ -59,8 +64,11 @@ class SettingsFragment : Fragment(), ScrollEventListener {
appHelper.dayNightMod(requireContext(), binding.nestScrollView) appHelper.dayNightMod(requireContext(), binding.nestScrollView)
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
context = requireContext()
initializeInjectedDependencies() initializeInjectedDependencies()
observeClickListener() observeClickListener()
observeSwipeTouchListener()
val packageInfo = val packageInfo =
requireContext().packageManager.getPackageInfo(requireContext().packageName, 0) requireContext().packageManager.getPackageInfo(requireContext().packageName, 0)
@@ -217,4 +225,24 @@ class SettingsFragment : Fragment(), ScrollEventListener {
preferenceViewModel.setLockSettings(isChecked) preferenceViewModel.setLockSettings(isChecked)
} }
} }
@SuppressLint("ClickableViewAccessibility")
private fun observeSwipeTouchListener() {
binding.touchArea.setOnTouchListener(getSwipeGestureListener(context))
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().popBackStack()
}
override fun onSwipeRight() {
super.onSwipeRight()
findNavController().popBackStack()
}
}
}
} }

View File

@@ -24,7 +24,8 @@ import javax.inject.Inject
* A simple [Fragment] subclass as the second destination in the navigation. * A simple [Fragment] subclass as the second destination in the navigation.
*/ */
@AndroidEntryPoint @AndroidEntryPoint
class WidgetManagerFragment : Fragment(), WidgetOptionsDialogFragment.WidgetOptionsListener { class WidgetManagerFragment : Fragment(),
WidgetOptionsDialogFragment.WidgetOptionsListener {
private var _binding: FragmentWidgetManagerBinding? = null private var _binding: FragmentWidgetManagerBinding? = null
@@ -78,47 +79,51 @@ class WidgetManagerFragment : Fragment(), WidgetOptionsDialogFragment.WidgetOpti
} }
// Initialize the ActivityResultLaunchers // Initialize the ActivityResultLaunchers
pickWidgetLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> pickWidgetLauncher =
if (result.resultCode == Activity.RESULT_OK) { registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val data = result.data if (result.resultCode == Activity.RESULT_OK) {
data?.let { val data = result.data
val appWidgetId = it.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) data?.let {
if (appWidgetId != -1) { val appWidgetId = it.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
val appWidgetInfo = appWidgetManager.getAppWidgetInfo(appWidgetId) if (appWidgetId != -1) {
if (appWidgetInfo?.configure != null) { val appWidgetInfo = appWidgetManager.getAppWidgetInfo(appWidgetId)
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE) if (appWidgetInfo?.configure != null) {
intent.component = appWidgetInfo.configure val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) intent.component = appWidgetInfo.configure
createWidgetLauncher.launch(intent) intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
} else { createWidgetLauncher.launch(intent)
} else {
addWidget(appWidgetId)
}
}
}
} else if (result.resultCode == Activity.RESULT_CANCELED) {
val appWidgetId =
result.data?.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
if (appWidgetId != null && appWidgetId != -1) {
appWidgetHost.deleteAppWidgetId(appWidgetId)
}
}
}
createWidgetLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data
data?.let {
val appWidgetId = it.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
if (appWidgetId != -1) {
addWidget(appWidgetId) addWidget(appWidgetId)
} }
} }
} } else if (result.resultCode == Activity.RESULT_CANCELED) {
} else if (result.resultCode == Activity.RESULT_CANCELED) { val appWidgetId =
val appWidgetId = result.data?.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) result.data?.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
if (appWidgetId != null && appWidgetId != -1) { if (appWidgetId != null && appWidgetId != -1) {
appWidgetHost.deleteAppWidgetId(appWidgetId) appWidgetHost.deleteAppWidgetId(appWidgetId)
}
}
}
createWidgetLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data
data?.let {
val appWidgetId = it.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
if (appWidgetId != -1) {
addWidget(appWidgetId)
} }
} }
} else if (result.resultCode == Activity.RESULT_CANCELED) {
val appWidgetId = result.data?.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
if (appWidgetId != null && appWidgetId != -1) {
appWidgetHost.deleteAppWidgetId(appWidgetId)
}
} }
}
// Set long-click listener on the root view // Set long-click listener on the root view
binding.widgetParent.setOnLongClickListener { binding.widgetParent.setOnLongClickListener {
@@ -161,7 +166,8 @@ class WidgetManagerFragment : Fragment(), WidgetOptionsDialogFragment.WidgetOpti
} }
private fun saveWidgetIds(widgetIds: List<Int>) { private fun saveWidgetIds(widgetIds: List<Int>) {
val sharedPreferences = requireContext().getSharedPreferences(Constants.WIDGETS_PREFS, Activity.MODE_PRIVATE) val sharedPreferences =
requireContext().getSharedPreferences(Constants.WIDGETS_PREFS, Activity.MODE_PRIVATE)
val editor = sharedPreferences.edit() val editor = sharedPreferences.edit()
val widgetIdsSet = widgetIds.map { it.toString() }.toSet() val widgetIdsSet = widgetIds.map { it.toString() }.toSet()
editor.putStringSet(Constants.APP_WIDGETS_ID, widgetIdsSet) editor.putStringSet(Constants.APP_WIDGETS_ID, widgetIdsSet)
@@ -169,7 +175,8 @@ class WidgetManagerFragment : Fragment(), WidgetOptionsDialogFragment.WidgetOpti
} }
private fun loadWidgetIds(): List<Int> { private fun loadWidgetIds(): List<Int> {
val sharedPreferences = requireContext().getSharedPreferences(Constants.WIDGETS_PREFS, Activity.MODE_PRIVATE) val sharedPreferences =
requireContext().getSharedPreferences(Constants.WIDGETS_PREFS, Activity.MODE_PRIVATE)
val widgetIdsSet = sharedPreferences.getStringSet(Constants.APP_WIDGETS_ID, emptySet()) val widgetIdsSet = sharedPreferences.getStringSet(Constants.APP_WIDGETS_ID, emptySet())
return widgetIdsSet?.map { it.toInt() } ?: emptyList() return widgetIdsSet?.map { it.toInt() } ?: emptyList()
} }

View File

@@ -1,14 +1,10 @@
package com.github.droidworksstudio.launcher.ui.widgetmanager package com.github.droidworksstudio.launcher.ui.widgetmanager
import android.annotation.SuppressLint
import android.app.Dialog import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.widget.Button
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import com.github.droidworksstudio.launcher.Constants import com.github.droidworksstudio.launcher.Constants
import com.github.droidworksstudio.launcher.R
class WidgetOptionsDialogFragment : DialogFragment() { class WidgetOptionsDialogFragment : DialogFragment() {
@@ -18,7 +14,8 @@ class WidgetOptionsDialogFragment : DialogFragment() {
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val appWidgetId = arguments?.getInt(ARG_APP_WIDGET_ID) ?: return super.onCreateDialog(savedInstanceState) val appWidgetId =
arguments?.getInt(ARG_APP_WIDGET_ID) ?: return super.onCreateDialog(savedInstanceState)
val builder = AlertDialog.Builder(requireContext()) val builder = AlertDialog.Builder(requireContext())
builder.setTitle("Widget Options") builder.setTitle("Widget Options")

View File

@@ -6,7 +6,8 @@ import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.listener.ScrollEventListener import com.github.droidworksstudio.launcher.listener.ScrollEventListener
class GestureNestedScrollView(context: Context, attrs: AttributeSet) : NestedScrollView(context, attrs){ class GestureNestedScrollView(context: Context, attrs: AttributeSet) :
NestedScrollView(context, attrs) {
var scrollEventListener: ScrollEventListener? = null var scrollEventListener: ScrollEventListener? = null

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.SettingsActivity">
<include layout="@layout/content_settings"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment_content_settings"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -7,6 +7,13 @@
android:id="@+id/draw_background" android:id="@+id/draw_background"
tools:context=".ui.drawer.DrawFragment"> tools:context=".ui.drawer.DrawFragment">
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/mainView" android:id="@+id/mainView"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -46,8 +53,9 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/drawAdapter" android:id="@+id/drawAdapter"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/search_view_text" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>

View File

@@ -7,6 +7,13 @@
android:id="@+id/favorite_view" android:id="@+id/favorite_view"
tools:context=".ui.favorite.FavoriteFragment"> tools:context=".ui.favorite.FavoriteFragment">
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout <FrameLayout
android:id="@+id/fragment_container" android:id="@+id/fragment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -22,7 +29,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="20dp" android:layout_margin="20dp"
android:text="Home App Order" android:text="@string/favorite_fragment_name"
android:textSize="@dimen/text_super_large" android:textSize="@dimen/text_super_large"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -31,11 +38,11 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/favoriteAdapter" android:id="@+id/favoriteAdapter"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginHorizontal="20dp" android:layout_marginHorizontal="20dp"
android:layout_marginTop="92dp" android:layout_marginTop="92dp"
app:layout_constraintTop_toBottomOf="@id/topTextView" /> app:layout_constraintTop_toBottomOf="@id/topTextView" />
</FrameLayout> </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -7,6 +7,13 @@
android:id="@+id/hidden_view" android:id="@+id/hidden_view"
tools:context=".ui.hidden.HiddenFragment"> tools:context=".ui.hidden.HiddenFragment">
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout <FrameLayout
android:id="@+id/fragment_container" android:id="@+id/fragment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -22,7 +29,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="20dp" android:layout_margin="20dp"
android:text="Hidden App" android:text="@string/hidden_fragment_name"
android:textSize="@dimen/text_super_large" android:textSize="@dimen/text_super_large"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -30,9 +37,8 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/hiddenAdapter" android:id="@+id/hiddenAdapter"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginHorizontal="20dp" android:layout_marginHorizontal="20dp"
android:layout_marginTop="92dp" android:layout_marginTop="92dp"
app:layout_constraintTop_toBottomOf="@id/topTextView" /> app:layout_constraintTop_toBottomOf="@id/topTextView" />

View File

@@ -2,14 +2,24 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mainLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical"
tools:context=".ui.home.HomeFragment"> tools:context=".ui.home.HomeFragment">
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.github.droidworksstudio.launcher.view.GestureNestedScrollView <com.github.droidworksstudio.launcher.view.GestureNestedScrollView
android:id="@+id/nestScrollView" android:id="@+id/nestScrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:fillViewport="true" android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@@ -81,7 +91,7 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/appListAdapter" android:id="@+id/appListAdapter"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>

View File

@@ -6,9 +6,16 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".ui.settings.SettingsFragment"> tools:context=".ui.settings.SettingsFragment">
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.github.droidworksstudio.launcher.view.GestureNestedScrollView <com.github.droidworksstudio.launcher.view.GestureNestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:id="@+id/nestScrollView" android:id="@+id/nestScrollView"
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false" android:clipToPadding="false"

View File

@@ -6,6 +6,13 @@
android:id="@+id/draw_background" android:id="@+id/draw_background"
tools:context=".ui.widgetmanager.WidgetManagerFragment"> tools:context=".ui.widgetmanager.WidgetManagerFragment">
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout <FrameLayout
android:id="@+id/widget_parent" android:id="@+id/widget_parent"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -21,13 +28,4 @@
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp" /> android:padding="16dp" />
</FrameLayout> </FrameLayout>
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -10,6 +10,10 @@
<string name="settings_fragment_label">Settings Fragment</string> <string name="settings_fragment_label">Settings Fragment</string>
<string name="widgets_fragment_label">Widgets Fragment</string> <string name="widgets_fragment_label">Widgets Fragment</string>
<!-- Strings used for fragments header labels -->
<string name="favorite_fragment_name">Favorite Apps</string>
<string name="hidden_fragment_name">Hidden Apps</string>
<string name="battery_level">%s%%</string> <string name="battery_level">%s%%</string>
<string name="search">Search</string> <string name="search">Search</string>
@@ -26,7 +30,6 @@
<string name="settings_name">Launcher Settings</string> <string name="settings_name">Launcher Settings</string>
<string name="settings_version">%s Version: %s</string> <string name="settings_version">%s Version: %s</string>
<string name="settings_home">Home</string>
<string name="settings_title_home_display_preferences">Display</string> <string name="settings_title_home_display_preferences">Display</string>
<string name="settings_title_home_behavior_preferences">Behavior</string> <string name="settings_title_home_behavior_preferences">Behavior</string>
@@ -101,6 +104,7 @@
<string name="accessibility_settings_enable">Enable</string> <string name="accessibility_settings_enable">Enable</string>
<string name="accessibility_settings_disable">Disable</string> <string name="accessibility_settings_disable">Disable</string>
<string name="accessibility_service_name">Easy Launcher Actions Service</string>
<string name="accessibility_service_desc">Please turn on accessibility service to use double tap to lock feature in Easy Launcher.\n\nThis permission is used only to turn off your screen.Our accessibility service does not collect or share any data.</string> <string name="accessibility_service_desc">Please turn on accessibility service to use double tap to lock feature in Easy Launcher.\n\nThis permission is used only to turn off your screen.Our accessibility service does not collect or share any data.</string>
<string name="admin_permission_message">Easy launcher promises to use lock screen permission responsibly. Easy launcher does not collect or share any data.</string> <string name="admin_permission_message">Easy launcher promises to use lock screen permission responsibly. Easy launcher does not collect or share any data.</string>