Skip to content

Commit f9c74ca

Browse files
authored
Merge pull request #30 from it5prasoon/dev/always-store-logs
added logic to store logs alongside of replylogs
2 parents 0ada3ce + 72ecab9 commit f9c74ca

File tree

12 files changed

+146
-126
lines changed

12 files changed

+146
-126
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
xmlns:tools="http://schemas.android.com/tools"
43
package="com.matrix.autoreply">
54

65
<uses-permission android:name="android.permission.INTERNET"/>
76
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
8-
<uses-permission
9-
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
10-
tools:ignore="ScopedStorage"/>
117
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
128

139
<queries>

app/src/main/java/com/matrix/autoreply/services/ForegroundNotificationService.kt

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.matrix.autoreply.services
22

3+
import android.app.Notification
34
import android.app.PendingIntent.CanceledException
45
import android.content.Intent
56
import android.os.Bundle
@@ -8,22 +9,40 @@ import android.service.notification.StatusBarNotification
89
import android.text.SpannableString
910
import android.util.Log
1011
import androidx.core.app.RemoteInput
12+
import com.matrix.autoreply.helpers.NotificationHelper
1113
import com.matrix.autoreply.model.CustomRepliesData
1214
import com.matrix.autoreply.preferences.PreferencesManager
1315
import com.matrix.autoreply.utils.DbUtils
14-
import com.matrix.autoreply.helpers.NotificationHelper
1516
import com.matrix.autoreply.utils.NotificationUtils
1617

18+
1719
class ForegroundNotificationService : NotificationListenerService() {
1820

1921
private val TAG = ForegroundNotificationService::class.java.simpleName
2022
private var customRepliesData: CustomRepliesData? = null
2123
private var dbUtils: DbUtils? = null
24+
2225
override fun onNotificationPosted(sbn: StatusBarNotification) {
2326
super.onNotificationPosted(sbn)
2427
if (canReply(sbn)) {
2528
sendReply(sbn)
2629
}
30+
31+
if ((sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY) != 0) {
32+
//Ignore the notification
33+
return
34+
}
35+
36+
if (canSaveLogs(sbn)) {
37+
saveLogs(sbn)
38+
}
39+
}
40+
41+
private fun canSaveLogs(sbn: StatusBarNotification): Boolean {
42+
return isServiceEnabled &&
43+
isSupportedPackage(sbn) &&
44+
NotificationUtils.isNewNotification(sbn) &&
45+
isGroupMessageAndReplyAllowed(sbn)
2746
}
2847

2948
private fun canReply(sbn: StatusBarNotification): Boolean {
@@ -40,6 +59,10 @@ class ForegroundNotificationService : NotificationListenerService() {
4059
return START_STICKY
4160
}
4261

62+
private fun saveLogs(sbn: StatusBarNotification) {
63+
dbUtils!!.saveLogs(sbn, NotificationUtils.getTitle(sbn), NotificationUtils.getMessage(sbn))
64+
}
65+
4366
private fun sendReply(sbn: StatusBarNotification) {
4467
val (_, pendingIntent, remoteInputs1) = NotificationUtils.extractWearNotification(sbn)
4568
if (remoteInputs1.isEmpty()) {
@@ -66,7 +89,7 @@ class ForegroundNotificationService : NotificationListenerService() {
6689
if (dbUtils == null) {
6790
dbUtils = DbUtils(applicationContext)
6891
}
69-
dbUtils!!.logReply(sbn, NotificationUtils.getTitle(sbn), NotificationUtils.getMessage(sbn))
92+
dbUtils!!.logReply(sbn, NotificationUtils.getTitle(sbn))
7093
pendingIntent.send(this, 0, localIntent)
7194
if (PreferencesManager.getPreferencesInstance(this)!!.isShowNotificationEnabled) {
7295
sbn.notification?.extras?.getString("android.title")
@@ -117,8 +140,10 @@ class ForegroundNotificationService : NotificationListenerService() {
117140
}
118141

119142
val timeDelay = PreferencesManager.getPreferencesInstance(this)!!.autoReplyDelay
120-
return System.currentTimeMillis() - dbUtils!!.getLastRepliedTime(sbn.packageName, title) >= Math.max(
121-
timeDelay,
143+
return System.currentTimeMillis() - dbUtils!!.getLastRepliedTime(
144+
sbn.packageName,
145+
title
146+
) >= timeDelay.coerceAtLeast(
122147
DELAY_BETWEEN_REPLY_IN_MILLISEC.toLong()
123148
)
124149
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.matrix.autoreply.store.data
2+
3+
import androidx.room.*
4+
5+
@Entity(
6+
tableName = "message_logs",
7+
foreignKeys = [ForeignKey(
8+
entity = AppPackage::class,
9+
parentColumns = arrayOf("index"),
10+
childColumns = arrayOf("index"),
11+
onDelete = ForeignKey.CASCADE
12+
)],
13+
indices = [Index(value = arrayOf("index"))]
14+
)
15+
data class MessageLogs(
16+
var index: Int,
17+
@field:ColumnInfo(name = "notif_title") var notifTitle: String,
18+
@field:ColumnInfo(name = "notif_message") var notifMessage: String?,
19+
@field:ColumnInfo(name = "notif_arrived_time") var notifArrivedTime: Long,
20+
@field:ColumnInfo(name = "notif_id") var notifId: Int?,
21+
) {
22+
@PrimaryKey(autoGenerate = true)
23+
var id = 0
24+
}

app/src/main/java/com/matrix/autoreply/store/data/MessageLog.kt renamed to app/src/main/java/com/matrix/autoreply/store/data/ReplyLogs.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.matrix.autoreply.store.data
33
import androidx.room.*
44

55
@Entity(
6-
tableName = "message_logs",
6+
tableName = "reply_logs",
77
foreignKeys = [ForeignKey(
88
entity = AppPackage::class,
99
parentColumns = arrayOf("index"),
@@ -12,10 +12,9 @@ import androidx.room.*
1212
)],
1313
indices = [Index(value = arrayOf("index"))]
1414
)
15-
data class MessageLog(
15+
data class ReplyLogs(
1616
var index: Int,
1717
@field:ColumnInfo(name = "notif_title") var notifTitle: String,
18-
@field:ColumnInfo(name = "notif_message") var notifMessage: String?,
1918
@field:ColumnInfo(name = "notif_arrived_time") var notifArrivedTime: Long,
2019
@field:ColumnInfo(name = "notif_replied_msg") var notifRepliedMsg: String,
2120
@field:ColumnInfo(name = "notif_reply_time") var notifReplyTime: Long

app/src/main/java/com/matrix/autoreply/store/database/MessageLogsDB.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@ import androidx.room.RoomDatabase
66
import kotlin.jvm.Synchronized
77
import androidx.room.Room
88
import com.matrix.autoreply.store.data.AppPackage
9-
import com.matrix.autoreply.store.data.MessageLog
9+
import com.matrix.autoreply.store.data.ReplyLogs
1010
import com.matrix.autoreply.store.repository.AppPackageDao
11-
import com.matrix.autoreply.store.repository.MessageLogsDao
11+
import com.matrix.autoreply.store.repository.ReplyLogsDao
1212
import com.matrix.autoreply.constants.Constants
13+
import com.matrix.autoreply.store.data.MessageLogs
14+
import com.matrix.autoreply.store.repository.MessageLogsDao
1315

14-
@Database(entities = [MessageLog::class, AppPackage::class], version = 3)
16+
@Database(entities = [MessageLogs::class, ReplyLogs::class, AppPackage::class], version = 6)
1517
abstract class MessageLogsDB : RoomDatabase() {
16-
abstract fun logsDao(): MessageLogsDao?
18+
19+
abstract fun messageLogsDao(): MessageLogsDao?
20+
abstract fun replyLogsDao(): ReplyLogsDao?
1721
abstract fun appPackageDao(): AppPackageDao?
1822

1923
companion object {

app/src/main/java/com/matrix/autoreply/store/repository/MessageLogsDao.kt

100755100644
Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,20 @@ package com.matrix.autoreply.store.repository
33
import androidx.room.Dao
44
import androidx.room.Insert
55
import androidx.room.Query
6-
import com.matrix.autoreply.store.data.MessageLog
6+
import com.matrix.autoreply.store.data.MessageLogs
77

88
@Dao
99
interface MessageLogsDao {
10-
@Query(
11-
"SELECT message_logs.notif_reply_time FROM MESSAGE_LOGS " +
12-
"INNER JOIN app_packages ON app_packages.`index` = message_logs.`index` " +
13-
"WHERE app_packages.package_name=:packageName AND message_logs.notif_title=:title " +
14-
"ORDER BY notif_reply_time DESC LIMIT 1"
15-
)
16-
fun getLastReplyTimeStamp(title: String?, packageName: String?): Long
1710

1811
@Insert
19-
fun logReply(log: MessageLog?)
20-
21-
@get:Query("SELECT COUNT(id) FROM MESSAGE_LOGS")
22-
val numReplies: Long
12+
fun logMessage(log: MessageLogs?)
2313

2414
// retrieve the distinct notif_title values from the message_logs
2515
@Query("SELECT DISTINCT notif_title FROM message_logs")
2616
fun getDistinctNotificationTitles(): List<String>
2717

2818
// retrieve the notif_message items for a given notif_title
2919
@Query("SELECT * FROM message_logs WHERE notif_title = :notifTitle")
30-
fun getMessageLogsWithTitle(notifTitle: String): List<MessageLog>
31-
32-
//https://stackoverflow.com/questions/11771580/deleting-android-sqlite-rows-older-than-x-days
33-
@Query("DELETE FROM message_logs WHERE notif_reply_time <= strftime('%s', datetime('now', '-30 days'));")
34-
fun purgeMessageLogs()
20+
fun getMessageLogsWithTitle(notifTitle: String): List<MessageLogs>
3521

36-
@get:Query("SELECT notif_reply_time FROM MESSAGE_LOGS ORDER BY notif_reply_time DESC LIMIT 1")
37-
val firstRepliedTime: Long
3822
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.matrix.autoreply.store.repository
2+
3+
import androidx.room.Dao
4+
import androidx.room.Insert
5+
import androidx.room.Query
6+
import com.matrix.autoreply.store.data.ReplyLogs
7+
8+
@Dao
9+
interface ReplyLogsDao {
10+
@Query(
11+
"SELECT reply_logs.notif_reply_time FROM REPLY_LOGS " +
12+
"INNER JOIN app_packages ON app_packages.`index` = reply_logs.`index` " +
13+
"WHERE app_packages.package_name=:packageName AND reply_logs.notif_title=:title " +
14+
"ORDER BY notif_reply_time DESC LIMIT 1"
15+
)
16+
fun getLastReplyTimeStamp(title: String?, packageName: String?): Long
17+
18+
@Insert
19+
fun logReply(log: ReplyLogs?)
20+
21+
@get:Query("SELECT COUNT(id) FROM MESSAGE_LOGS")
22+
val numReplies: Long
23+
24+
//https://stackoverflow.com/questions/11771580/deleting-android-sqlite-rows-older-than-x-days
25+
@Query("DELETE FROM reply_logs WHERE notif_reply_time <= strftime('%s', datetime('now', '-30 days'));")
26+
fun purgeMessageLogs()
27+
28+
@get:Query("SELECT notif_reply_time FROM REPLY_LOGS ORDER BY notif_reply_time DESC LIMIT 1")
29+
val firstRepliedTime: Long
30+
}

app/src/main/java/com/matrix/autoreply/ui/activity/TabbedActivity.kt

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.matrix.autoreply.ui.activity
22

3-
import android.Manifest
43
import android.content.Intent
54
import android.content.IntentSender.SendIntentException
6-
import android.content.pm.PackageManager
75
import android.content.res.Configuration
86
import android.os.Bundle
97
import android.util.Log
@@ -12,8 +10,6 @@ import android.view.MenuItem
1210
import android.widget.Toast
1311
import androidx.appcompat.app.AppCompatActivity
1412
import androidx.appcompat.app.AppCompatDelegate
15-
import androidx.core.app.ActivityCompat
16-
import androidx.core.content.ContextCompat
1713
import com.google.android.play.core.appupdate.AppUpdateInfo
1814
import com.google.android.play.core.appupdate.AppUpdateManager
1915
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
@@ -23,18 +19,13 @@ import com.matrix.autoreply.R
2319
import com.matrix.autoreply.databinding.ActivityTabbedBinding
2420
import com.matrix.autoreply.helpers.AlertDialogHelper
2521
import com.matrix.autoreply.ui.activity.main.SectionsPagerAdapter
26-
import java.io.File
2722

2823
class TabbedActivity : AppCompatActivity() {
29-
private val msgLogFileName = "msgLog.txt"
30-
private val signalMsgLogFileName = "signalMsgLog.txt"
31-
private val w4bMsgLogFileName = "waBusMsgLog.txt"
3224
private var appUpdateManager: AppUpdateManager? = null
3325
private lateinit var binding: ActivityTabbedBinding
3426

3527
companion object {
3628
private const val TOOLBAR_TITLE_TEXT = "Auto Reply"
37-
private const val MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 0
3829
private const val IMMEDIATE_APP_UPDATE_REQ_CODE = 124
3930
private const val TAG = "AppUpdate"
4031
}
@@ -52,10 +43,6 @@ class TabbedActivity : AppCompatActivity() {
5243
binding.viewPager.adapter = sectionsPagerAdapter
5344
binding.tabs.setupWithViewPager(binding.viewPager)
5445

55-
// Request Storage Permission
56-
requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
57-
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE)
58-
5946
window.statusBarColor = resources.getColor(R.color.colorPrimary)
6047
}
6148

@@ -101,56 +88,6 @@ class TabbedActivity : AppCompatActivity() {
10188
}
10289
}
10390

104-
105-
private fun createBackups() {
106-
if (!File(this.filesDir, msgLogFileName).exists()) {
107-
if (!File(this.filesDir, msgLogFileName).createNewFile())
108-
Toast.makeText(applicationContext, getString(R.string.create_msg_log_failed),
109-
Toast.LENGTH_SHORT).show()
110-
}
111-
112-
if (!File(this.filesDir, signalMsgLogFileName).exists()) {
113-
if (!File(this.filesDir, signalMsgLogFileName).createNewFile())
114-
Toast.makeText(applicationContext, getString(R.string.create_msg_log_failed),
115-
Toast.LENGTH_SHORT).show()
116-
}
117-
118-
if (!File(this.filesDir, w4bMsgLogFileName).exists()) {
119-
if (!File(this.filesDir, w4bMsgLogFileName).createNewFile())
120-
Toast.makeText(applicationContext, getString(R.string.create_msg_log_failed),
121-
Toast.LENGTH_SHORT).show()
122-
}
123-
}
124-
125-
@Suppress("SameParameterValue")
126-
private fun requestPermission(permission: String, requestCode: Int) {
127-
if (ContextCompat.checkSelfPermission(this,
128-
permission) != PackageManager.PERMISSION_GRANTED) {
129-
ActivityCompat.requestPermissions(this,
130-
arrayOf(permission), requestCode)
131-
} else {
132-
createBackups()
133-
}
134-
}
135-
136-
override fun onRequestPermissionsResult(
137-
requestCode: Int,
138-
permissions: Array<out String>,
139-
grantResults: IntArray
140-
) {
141-
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
142-
143-
if (requestCode == MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE) {
144-
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
145-
Toast.makeText(applicationContext, getString(R.string.create_backup_dir), Toast.LENGTH_SHORT).show()
146-
createBackups()
147-
} else {
148-
Toast.makeText(applicationContext, getString(R.string.allow_storage_permission_msg), Toast.LENGTH_LONG).show()
149-
}
150-
return
151-
}
152-
}
153-
15491
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
15592
menuInflater.inflate(R.menu.menu_light_dark, menu)
15693
return true
@@ -189,8 +126,6 @@ class TabbedActivity : AppCompatActivity() {
189126

190127
return true
191128
}
192-
193-
194129
else -> super.onOptionsItemSelected(item)
195130
}
196131
}

app/src/main/java/com/matrix/autoreply/ui/activity/logsViewer/ContactNameFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class ContactNameFragment : Fragment(), RefreshListener {
5959
private fun updateUserNameList() {
6060
// TODO: 1. To make all the calls using suspend function and coroutines to make database IO calls
6161
// TODO: 2. To use Dagger Dependency Injection to get singleton of DB
62-
contactNameList = MessageLogsDB.getInstance(requireContext())!!.logsDao()!!.getDistinctNotificationTitles()
62+
contactNameList = MessageLogsDB.getInstance(requireContext())!!.messageLogsDao()!!.getDistinctNotificationTitles()
6363
}
6464

6565
override fun onDestroyView() {

app/src/main/java/com/matrix/autoreply/ui/activity/logsViewer/MessageListFragment.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,19 @@ class MessageListFragment : Fragment(), RefreshListener {
4444
// TODO: 1. To make all the calls using suspend function and coroutines to make database IO calls
4545
// TODO: 2. To use Dagger Dependency Injection to get singleton of DB
4646
val messageLogWithTitleList =
47-
MessageLogsDB.getInstance(requireContext())!!.logsDao()!!.getMessageLogsWithTitle(contactName)
47+
MessageLogsDB.getInstance(requireContext())!!.messageLogsDao()!!.getMessageLogsWithTitle(contactName)
4848

49-
return messageLogWithTitleList.map { messageLog ->
50-
val message = messageLog.notifMessage
51-
val timestamp = messageLog.notifArrivedTime
49+
return messageLogWithTitleList
50+
.filter { it.notifMessage != null }
51+
.map { messageLog ->
52+
val message = messageLog.notifMessage
53+
val timestamp = messageLog.notifArrivedTime
5254

53-
// Return the extracted items as a pair or any other desired structure
54-
Pair(message, timestamp)
55-
}.reversed()
55+
// Return the extracted items as a pair or any other desired structure
56+
Pair(message, timestamp)
57+
}.reversed()
5658
}
57-
59+
5860
companion object {
5961
private const val ARG_SELECTED_TITLE = "selected_title"
6062

0 commit comments

Comments
 (0)