Skip to content

Commit dc0fa8a

Browse files
committed
Add preferences menu
1 parent de9242a commit dc0fa8a

File tree

15 files changed

+181
-40
lines changed

15 files changed

+181
-40
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ dependencies {
4545
implementation(libs.material)
4646
implementation(libs.androidx.activity)
4747
implementation(libs.androidx.constraintlayout)
48+
implementation(libs.androidx.preference.ktx)
4849
testImplementation(libs.junit)
4950
androidTestImplementation(libs.androidx.junit)
5051
androidTestImplementation(libs.androidx.espresso.core)

app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,12 @@
44

55
<uses-feature
66
android:name="android.hardware.telephony"
7-
android:required="false" />
8-
9-
<!-- for call -->
7+
android:required="false" /> <!-- for call -->
108
<uses-permission android:name="android.permission.READ_CALL_LOG" />
119
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
12-
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
13-
14-
<!-- for contacts -->
15-
<uses-permission android:name="android.permission.READ_CONTACTS" />
16-
17-
<!-- for internet access -->
18-
<uses-permission android:name="android.permission.INTERNET" />
19-
20-
<!-- for posting notifications -->
10+
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" /> <!-- for contacts -->
11+
<uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- for internet access -->
12+
<uses-permission android:name="android.permission.INTERNET" /> <!-- for posting notifications -->
2113
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
2214

2315
<application
@@ -29,6 +21,9 @@
2921
android:supportsRtl="true"
3022
android:theme="@style/Theme.ListaSpam"
3123
tools:targetApi="28">
24+
<activity
25+
android:name=".SettingsActivity"
26+
android:exported="false" />
3227
<activity
3328
android:name=".MainActivity"
3429
android:exported="true">

app/src/main/java/com/addev/listaspam/MainActivity.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import android.os.Build
1212
import android.os.Bundle
1313
import android.provider.Settings
1414
import android.telecom.TelecomManager
15+
import android.view.Menu
16+
import android.view.MenuItem
1517
import android.widget.Toast
1618
import androidx.activity.result.ActivityResultLauncher
1719
import androidx.activity.result.contract.ActivityResultContracts
@@ -40,6 +42,22 @@ class MainActivity : AppCompatActivity() {
4042
setupIntentLauncher()
4143
}
4244

45+
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
46+
menuInflater.inflate(R.menu.menu, menu)
47+
return true
48+
}
49+
50+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
51+
return when (item.itemId) {
52+
R.id.action_settings -> {
53+
val intent = Intent(this, SettingsActivity::class.java)
54+
startActivity(intent)
55+
true
56+
}
57+
else -> super.onOptionsItemSelected(item)
58+
}
59+
}
60+
4361
private fun init() {
4462
checkPermissionsAndRequest()
4563

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.addev.listaspam
2+
3+
import android.os.Bundle
4+
import androidx.activity.enableEdgeToEdge
5+
import androidx.appcompat.app.AppCompatActivity
6+
import androidx.core.view.ViewCompat
7+
import androidx.core.view.WindowInsetsCompat
8+
import androidx.preference.PreferenceFragmentCompat
9+
10+
class SettingsActivity : AppCompatActivity() {
11+
override fun onCreate(savedInstanceState: Bundle?) {
12+
super.onCreate(savedInstanceState)
13+
setContentView(R.layout.activity_settings)
14+
15+
supportFragmentManager
16+
.beginTransaction()
17+
.replace(R.id.settings_container, SettingsFragment())
18+
.commit()
19+
}
20+
21+
// Fragmento para cargar las preferencias
22+
class SettingsFragment : PreferenceFragmentCompat() {
23+
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
24+
setPreferencesFromResource(R.xml.preferences, rootKey)
25+
}
26+
}
27+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.addev.listaspam.model
2+
3+
import android.os.Bundle
4+
import androidx.preference.PreferenceFragmentCompat
5+
import com.addev.listaspam.R
6+
7+
class SettingsFragment : PreferenceFragmentCompat() {
8+
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
9+
setPreferencesFromResource(R.xml.preferences, rootKey)
10+
}
11+
}

app/src/main/java/com/addev/listaspam/services/MyCallScreeningService.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class MyCallScreeningService : CallScreeningService() {
7070
details, CallResponse.Builder()
7171
.setDisallowCall(true)
7272
.setRejectCall(true)
73+
.setSkipNotification(true)
7374
.build()
7475
)
7576
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.addev.listaspam.utils
2+
3+
import android.content.Context
4+
import androidx.preference.PreferenceManager
5+
6+
fun isBlockingEnabled(context: Context): Boolean {
7+
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
8+
return sharedPreferences.getBoolean("pref_enable_blocking", true)
9+
}
10+
11+
fun shouldFilterWithListaSpam(context: Context): Boolean {
12+
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
13+
return sharedPreferences.getBoolean("pref_filter_lista_spam", true)
14+
}
15+
16+
fun shouldFilterWithResponderONo(context: Context): Boolean {
17+
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
18+
return sharedPreferences.getBoolean("pref_filter_responder_o_no", true)
19+
}
20+
21+
fun shouldBlockNonContacts(context: Context): Boolean {
22+
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
23+
return sharedPreferences.getBoolean("pref_block_non_contacts", false)
24+
}
25+
26+
fun shouldShowNotification(context: Context): Boolean {
27+
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
28+
return sharedPreferences.getBoolean("pref_show_notification", true)
29+
}

app/src/main/java/com/addev/listaspam/utils/SpamUtils.kt

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import android.app.NotificationManager
66
import android.content.Context
77
import android.content.pm.PackageManager
88
import android.database.Cursor
9-
import android.os.Build
109
import android.os.Handler
1110
import android.os.Looper
1211
import android.provider.ContactsContract
@@ -16,7 +15,6 @@ import androidx.core.app.NotificationCompat
1615
import androidx.core.app.NotificationManagerCompat
1716
import androidx.core.content.ContextCompat
1817
import com.addev.listaspam.R
19-
import com.addev.listaspam.model.SpamData
2018
import kotlinx.coroutines.CoroutineScope
2119
import kotlinx.coroutines.Dispatchers
2220
import kotlinx.coroutines.launch
@@ -56,6 +54,10 @@ class SpamUtils {
5654
*/
5755
fun checkSpamNumber(context: Context, number: String, callback: (isSpam: Boolean) -> Unit) {
5856
CoroutineScope(Dispatchers.IO).launch {
57+
if (!isBlockingEnabled(context)) {
58+
return@launch
59+
}
60+
5961
if (isNumberBlockedLocally(context, number)) {
6062
handleSpamNumber(context, number, callback)
6163
return@launch
@@ -65,13 +67,24 @@ class SpamUtils {
6567
if (isNumberInAgenda(context, number)) {
6668
handleNonSpamNumber(context, number, callback)
6769
return@launch
70+
} else if (shouldBlockNonContacts(context)) {
71+
handleSpamNumber(context, number, callback)
6872
}
73+
74+
6975
}
7076

71-
val spamCheckers = listOf(
72-
::checkListaSpam,
73-
::checkResponderono,
74-
)
77+
// List to hold the functions that should be used
78+
val spamCheckers = mutableListOf<suspend (String) -> Boolean>()
79+
80+
// Add functions based on preferences
81+
if (shouldFilterWithListaSpam(context)) {
82+
spamCheckers.add(::checkListaSpam)
83+
}
84+
85+
if (shouldFilterWithResponderONo(context)) {
86+
spamCheckers.add(::checkResponderono)
87+
}
7588

7689
val isSpam = spamCheckers.any { checker ->
7790
runCatching { checker(number) }.getOrDefault(false)
@@ -271,38 +284,32 @@ class SpamUtils {
271284
}
272285
}
273286

274-
/**
275-
* Sends a notification indicating that a spam number has been blocked.
276-
* @param context Context for sending the notification.
277-
* @param number Phone number that was blocked.
278-
*/
279287
private fun sendNotification(context: Context, number: String) {
280288
createNotificationChannel(context)
281-
val notification = NotificationCompat.Builder(context, context.getString(R.string.notification_channel_id))
282-
.setSmallIcon(R.mipmap.ic_launcher)
283-
.setContentTitle(context.getString(R.string.notification_title_spam_blocked))
284-
.setContentText(context.getString(R.string.notification_text_spam_blocked, number))
285-
.setPriority(NotificationCompat.PRIORITY_HIGH)
286-
.build()
287289

288290
if (ActivityCompat.checkSelfPermission(
289291
context,
290292
Manifest.permission.POST_NOTIFICATIONS
291-
) != PackageManager.PERMISSION_GRANTED
293+
) != PackageManager.PERMISSION_GRANTED ||
294+
!shouldShowNotification(context)
292295
) {
296+
// Aquí deberías solicitar el permiso si no está concedido.
293297
return
294298
}
295299

300+
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
301+
.setSmallIcon(R.mipmap.ic_launcher)
302+
.setContentTitle(context.getString(R.string.notification_title_spam_blocked))
303+
.setContentText(context.getString(R.string.notification_text_spam_blocked, number))
304+
.setPriority(NotificationCompat.PRIORITY_HIGH)
305+
.build()
306+
296307
NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, notification)
297308
}
298309

299-
/**
300-
* Creates a notification channel for spam notifications.
301-
* @param context Context for creating the notification channel.
302-
*/
303310
private fun createNotificationChannel(context: Context) {
304-
val name = context.getString(R.string.notification_channel_id)
305-
val descriptionText = context.getString(R.string.notification_channel_id)
311+
val name = context.getString(R.string.notification_channel_name)
312+
val descriptionText = context.getString(R.string.notification_channel_name)
306313
val importance = NotificationManager.IMPORTANCE_HIGH
307314
val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance).apply {
308315
description = descriptionText
@@ -312,4 +319,5 @@ class SpamUtils {
312319
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
313320
notificationManager.createNotificationChannel(channel)
314321
}
322+
315323
}

app/src/main/res/layout/activity_main.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
android:layout_height="match_parent"
88
tools:context=".MainActivity">
99

10-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
11-
xmlns:tools="http://schemas.android.com/tools"
10+
<LinearLayout
1211
android:layout_width="match_parent"
1312
android:layout_height="match_parent"
1413
android:orientation="vertical"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:id="@+id/settings_container"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent" />

0 commit comments

Comments
 (0)