Skip to content

Commit

Permalink
implement checkup to show the user dnd-state
Browse files Browse the repository at this point in the history
  • Loading branch information
newhinton committed Jan 6, 2024
1 parent d27004c commit f788e8b
Show file tree
Hide file tree
Showing 17 changed files with 482 additions and 6 deletions.
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- Needed for warnings if dnd is set -->


<application
android:allowBackup="true"
android:fullBackupContent="true"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/de/felixnuesse/timedsilence/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Constants {
const val RECURRING_INTENT_ID = 123789

const val CALENDAR_PERMISSION_REQUEST_ID = 12387
const val CONTACT_PERMISSION_REQUEST_ID = 12388

const val SERVICE_INTENT_DELAY_ACTION = "SERVICE_INTENT_DELAY_ACTION"
const val SERVICE_INTENT_DELAY_ACTION_TOGGLE = "SERVICE_INTENT_DELAY_ACTION_TOGGLE"
Expand Down
18 changes: 16 additions & 2 deletions app/src/main/java/de/felixnuesse/timedsilence/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ package de.felixnuesse.timedsilence
*/

import android.annotation.SuppressLint
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.PorterDuff
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.text.format.DateFormat
Expand All @@ -57,12 +59,14 @@ import de.felixnuesse.timedsilence.IntroActivity.Companion.INTRO_PREFERENCES
import de.felixnuesse.timedsilence.databinding.ActivityMainBinding
import de.felixnuesse.timedsilence.extensions.TAG
import de.felixnuesse.timedsilence.fragments.CalendarFragment
import de.felixnuesse.timedsilence.fragments.CheckupFragment
import de.felixnuesse.timedsilence.fragments.KeywordFragment
import de.felixnuesse.timedsilence.fragments.ScheduleFragment
import de.felixnuesse.timedsilence.fragments.graph.GraphFragment
import de.felixnuesse.timedsilence.handler.*
import de.felixnuesse.timedsilence.handler.trigger.Trigger
import de.felixnuesse.timedsilence.handler.volume.VolumeHandler
import de.felixnuesse.timedsilence.model.contacts.ContactUtil
import de.felixnuesse.timedsilence.services.`interface`.TimerInterface
import de.felixnuesse.timedsilence.volumestate.StateGenerator

Expand Down Expand Up @@ -151,6 +155,7 @@ class MainActivity : AppCompatActivity(), TimerInterface {
if (mDontCheckGraph) {
mVolumeHandler.setVolumeStateAndApply(StateGenerator(this).stateAt(System.currentTimeMillis()))
}

}


Expand Down Expand Up @@ -199,6 +204,7 @@ class MainActivity : AppCompatActivity(), TimerInterface {


when (item.itemId) {
R.id.action_goto_dnd -> openDnDSettings()
R.id.action_settings -> openSettings()
R.id.action_set_manual_loud -> {
val makeSound = !mVolumeHandler.isButtonClickAudible()
Expand Down Expand Up @@ -247,6 +253,13 @@ class MainActivity : AppCompatActivity(), TimerInterface {
return true
}



private fun openDnDSettings(): Boolean {
startActivity(Intent("android.settings.ZEN_MODE_SETTINGS"))
return true
}

private fun updateTimeCheckDisplay() {
binding.nextCheckDisplay.text = mTrigger.getNextAlarmTimestamp()

Expand Down Expand Up @@ -352,9 +365,9 @@ class MainActivity : AppCompatActivity(), TimerInterface {
* sequence.
* FragmentStatePagerAdapter
*/
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

override fun getCount(): Int = 4
override fun getCount(): Int = 5

override fun getItem(position: Int): Fragment {

Expand All @@ -364,6 +377,7 @@ class MainActivity : AppCompatActivity(), TimerInterface {
2 -> return CalendarFragment()
3 -> return KeywordFragment()
//4 -> return WifiConnectedFragment()
4 -> return CheckupFragment()
else -> return ScheduleFragment()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package de.felixnuesse.timedsilence.fragments

import android.app.NotificationManager
import android.app.NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
import android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS
import android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS
import android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES
import android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON
import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import de.felixnuesse.timedsilence.databinding.FragmentCheckupBinding
import de.felixnuesse.timedsilence.extensions.e
import de.felixnuesse.timedsilence.model.contacts.Contact
import de.felixnuesse.timedsilence.model.contacts.ContactUtil
import de.felixnuesse.timedsilence.util.PermissionManager


class CheckupFragment : Fragment() {

companion object {
private const val TAG = "CheckupFragment"
}

private var _binding: FragmentCheckupBinding? = null
private val binding get() = _binding!!


override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCheckupBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
updateData()

binding.gotoDND.setOnClickListener {
startActivity(Intent("android.settings.ZEN_MODE_SETTINGS"))
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

override fun onResume() {
super.onResume()
updateData()
}

private fun updateData() {
val context = binding.root.context

var l = arrayListOf<Contact>()


var permissionManager = PermissionManager(context)
if(permissionManager.grantedContacts()) {
binding.CheckupContentContainer.visibility = View.VISIBLE
binding.CheckupPermissionCheckContainer.visibility = View.GONE
l = ContactUtil(context).getContactList()
} else{
binding.CheckupContentContainer.visibility = View.GONE
binding.buttonRequestContactPermissions.setOnClickListener{
permissionManager.requestContactsAccess()
}
}

val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
val policy = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
mNotificationManager?.consolidatedNotificationPolicy
} else {
mNotificationManager?.notificationPolicy
}


/*
The following is the current (api 33) list of available categories:
fun allowAlarms(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS != 0
}
fun allowMedia(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA != 0
}
fun allowSystem(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM != 0
}
fun allowRepeatCallers(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS != 0
}
fun allowCalls(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_CALLS != 0
}
fun allowConversations(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS != 0
}
fun allowMessages(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES != 0
}
fun allowEvents(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS != 0
}
fun allowReminders(): Boolean {
return priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS != 0
}
fun allowCallsFrom(): Int {
return priorityCallSenders
}
fun allowMessagesFrom(): Int {
return priorityMessageSenders
}
fun allowConversationsFrom(): Int {
return priorityConversationSenders
}
*/

var prioCategories = policy?.priorityCategories ?: 0
var suppressedVisuals = policy?.suppressedVisualEffects ?: 0


val repeatCaller = prioCategories and PRIORITY_CATEGORY_REPEAT_CALLERS
val priorityCaller = prioCategories and PRIORITY_CATEGORY_CALLS

// contacts, or conversations
var repeatMessenger = prioCategories and PRIORITY_CATEGORY_MESSAGES

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
repeatMessenger += prioCategories and PRIORITY_CATEGORY_CONVERSATIONS
}

val alarms = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
prioCategories and PRIORITY_CATEGORY_ALARMS
} else {
1
}


binding.checkboxHavePriorityContacts.isChecked = l.size > 0
binding.checkboxPriorityContactsCanBypass.isChecked = priorityCaller != 0
binding.checkboxRepeatCallerCanBypass.isChecked = repeatCaller != 0
binding.checkboxRepeatMessengerCanBypass.isChecked = repeatMessenger != 0
binding.checkboxRepeatMessengerCanBypass.isChecked = repeatMessenger != 0
binding.checkboxAlarmsCanBypass.isChecked = alarms != 0
binding.checkboxNotificationsInvisible.isChecked = areAllVisualEffectsSuppressed(suppressedVisuals)

}

/**
* Extracted from the Notification Manager itself. It is useful for me here.
* Version: API 34
*/
fun areAllVisualEffectsSuppressed(effects: Int): Boolean {
var allEffects = getAllVisualEffects()
for (i in allEffects.indices) {
val effect: Int = allEffects[i]
if (effects and effect == 0) {
return false
}
}
return true
}

/**
* Extracted from the Notification Manager itself. It is useful for me here.
* Version: API 34
*/
fun getAllVisualEffects(): IntArray {
return intArrayOf(
SUPPRESSED_EFFECT_SCREEN_OFF,
SUPPRESSED_EFFECT_SCREEN_ON,
SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
SUPPRESSED_EFFECT_LIGHTS,
SUPPRESSED_EFFECT_PEEK,
SUPPRESSED_EFFECT_STATUS_BAR,
SUPPRESSED_EFFECT_BADGE,
SUPPRESSED_EFFECT_AMBIENT,
SUPPRESSED_EFFECT_NOTIFICATION_LIST
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package de.felixnuesse.timedsilence.model.contacts

class Contact(var name: String) {


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package de.felixnuesse.timedsilence.model.contacts

import android.content.ContentResolver
import android.content.Context
import android.provider.ContactsContract
import android.util.Log
import de.felixnuesse.timedsilence.util.PermissionManager


class ContactUtil(private var mContext: Context) {

companion object {
private const val TAG = "ContactUtil"
}


private val PROJECTION = arrayOf(
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.STARRED
)

fun getContactList(): ArrayList<Contact> {
val contactList = arrayListOf<Contact>()

val cr: ContentResolver = mContext.contentResolver
val cursor = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
PROJECTION,
null,
null,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC"
)
cursor?.use { cursor ->
val nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
val starredIndex = cursor.getColumnIndex(ContactsContract.Contacts.STARRED)
while (cursor.moveToNext()) {
if(cursor.getInt(starredIndex) == 1) {
contactList.add(Contact(cursor.getString(nameIndex)))
}
}
}
return contactList
}

}
Loading

0 comments on commit f788e8b

Please sign in to comment.