diff --git a/app/src/main/kotlin/kaist/iclab/abclogger/collector/Commons.kt b/app/src/main/kotlin/kaist/iclab/abclogger/collector/Commons.kt index 0b7caf8..7d3d57b 100644 --- a/app/src/main/kotlin/kaist/iclab/abclogger/collector/Commons.kt +++ b/app/src/main/kotlin/kaist/iclab/abclogger/collector/Commons.kt @@ -6,9 +6,11 @@ import android.database.Cursor import android.net.Uri import android.provider.ContactsContract import androidx.core.database.getIntOrNull +import androidx.core.database.getLongOrNull import androidx.core.database.getStringOrNull import kaist.iclab.abclogger.R import kaist.iclab.abclogger.commons.Formatter +import java.util.concurrent.TimeUnit fun formatDateTime(context: Context, timeInMillis: Long) = timeInMillis.takeIf { it > 0 }?.let { Formatter.formatDateTime(context, timeInMillis) } ?: context.getString(R.string.general_mdash) @@ -20,14 +22,44 @@ internal data class Contact( ) internal suspend fun getRecentContents( - contentResolver: ContentResolver, - uri: Uri, timeColumn: String, columns: Array, - lastTime: Long = -1, block: suspend (cursor: Cursor) -> R): Collection { + contentResolver: ContentResolver, + uri: Uri, timeColumn: String, columns: Array, + lastTimeInMillis: Long = -1, + block: suspend (timeInMillis: Long, cursor: Cursor) -> R +): Collection { val results = mutableListOf() + /** + * At first, retrieve data with milliseconds + */ contentResolver.query( - uri, columns, "$timeColumn > ?", arrayOf(lastTime.toString()), "$timeColumn ASC" + uri, columns, "$timeColumn > ?", arrayOf(lastTimeInMillis.toString()), "$timeColumn ASC" )?.use { cursor -> - while (cursor.moveToNext()) results.add(block.invoke(cursor)) + while (cursor.moveToNext()) { + val time = try { + val idx = cursor.getColumnIndexOrThrow(timeColumn) + cursor.getLongOrNull(idx) ?: Long.MIN_VALUE + } catch (e: Exception) { + null + } ?: Long.MIN_VALUE + results.add(block.invoke(time, cursor)) + } + } + + /** + * And then, retrieve data with seconds-unit + */ + contentResolver.query( + uri, columns, "$timeColumn > ?", arrayOf(TimeUnit.MILLISECONDS.toSeconds(lastTimeInMillis).toString()), "$timeColumn ASC" + )?.use { cursor -> + while (cursor.moveToNext()) { + val time = try { + val idx = cursor.getColumnIndexOrThrow(timeColumn) + cursor.getIntOrNull(idx) ?: Int.MIN_VALUE + } catch (e: Exception) { + null + } ?: Long.MIN_VALUE + results.add(block.invoke(TimeUnit.SECONDS.toMillis(time.toLong()), cursor)) + } } return results } diff --git a/app/src/main/kotlin/kaist/iclab/abclogger/collector/call/CallLogCollector.kt b/app/src/main/kotlin/kaist/iclab/abclogger/collector/call/CallLogCollector.kt index 4f86c0d..ab6a054 100644 --- a/app/src/main/kotlin/kaist/iclab/abclogger/collector/call/CallLogCollector.kt +++ b/app/src/main/kotlin/kaist/iclab/abclogger/collector/call/CallLogCollector.kt @@ -115,9 +115,8 @@ class CallLogCollector( CallLog.Calls.NUMBER_PRESENTATION, CallLog.Calls.DATA_USAGE ), - lastTime = fromTime - ) { cursor -> - val millis = cursor.getLongOrNull(0) ?: 0 + lastTimeInMillis = fromTime + ) { millis, cursor -> val number = cursor.getStringOrNull(2) ?: "" val contact = getContact(contentResolver, number) ?: Contact() diff --git a/app/src/main/kotlin/kaist/iclab/abclogger/collector/embedded/EmbeddedSensorCollector.kt b/app/src/main/kotlin/kaist/iclab/abclogger/collector/embedded/EmbeddedSensorCollector.kt index 2aa47c8..3264a0b 100644 --- a/app/src/main/kotlin/kaist/iclab/abclogger/collector/embedded/EmbeddedSensorCollector.kt +++ b/app/src/main/kotlin/kaist/iclab/abclogger/collector/embedded/EmbeddedSensorCollector.kt @@ -81,15 +81,13 @@ class EmbeddedSensorCollector( ) } - launch { - buffer.buffer( - 10, TimeUnit.SECONDS - ).toFlowable( - BackpressureStrategy.BUFFER - ).asFlow().collect { entities -> - entities.forEach { - put(it) - } + buffer.buffer( + 10, TimeUnit.SECONDS + ).toFlowable( + BackpressureStrategy.BUFFER + ).asFlow().collect { entities -> + entities.forEach { + launch { put(it) } } } } diff --git a/app/src/main/kotlin/kaist/iclab/abclogger/collector/media/MediaCollector.kt b/app/src/main/kotlin/kaist/iclab/abclogger/collector/media/MediaCollector.kt index 52e56a7..e74e5d0 100644 --- a/app/src/main/kotlin/kaist/iclab/abclogger/collector/media/MediaCollector.kt +++ b/app/src/main/kotlin/kaist/iclab/abclogger/collector/media/MediaCollector.kt @@ -3,10 +3,7 @@ package kaist.iclab.abclogger.collector.media import android.Manifest import android.app.AlarmManager import android.app.PendingIntent -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter +import android.content.* import android.provider.MediaStore import androidx.core.content.getSystemService import androidx.core.database.getLongOrNull @@ -18,6 +15,7 @@ import kaist.iclab.abclogger.commons.atLeastPositive import kaist.iclab.abclogger.commons.safeRegisterReceiver import kaist.iclab.abclogger.commons.safeUnregisterReceiver import kaist.iclab.abclogger.core.DataRepository +import kaist.iclab.abclogger.core.Log import kaist.iclab.abclogger.core.collector.* import java.util.concurrent.TimeUnit @@ -64,8 +62,7 @@ class MediaCollector( } } - private val contentResolver by lazy { context.contentResolver } - + private val contentResolver by lazy { context.applicationContext.contentResolver } override fun isAvailable(): Boolean = true @@ -132,18 +129,16 @@ class MediaCollector( /** * Retrieve internal photo */ - val internalPhotos = getRecentContents( contentResolver = contentResolver, uri = MediaStore.Images.Media.INTERNAL_CONTENT_URI, - timeColumn = MediaStore.Images.ImageColumns.DATE_ADDED, + timeColumn = MediaStore.Images.Media.DATE_ADDED, columns = arrayOf( - MediaStore.Images.ImageColumns.DATE_ADDED, - MediaStore.Images.ImageColumns.MIME_TYPE + MediaStore.Images.Media.DATE_ADDED, + MediaStore.Images.Media.MIME_TYPE ), - lastTime = fromTimeInternalPhoto - ) { cursor -> - val millis = cursor.getLongOrNull(0) ?: Long.MIN_VALUE + lastTimeInMillis = fromTimeInternalPhoto + ) { millis, cursor -> MediaEntity( mimeType = cursor.getStringOrNull(1) ?: "image/*" ).apply { @@ -163,14 +158,13 @@ class MediaCollector( val externalPhotos = getRecentContents( contentResolver = contentResolver, uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - timeColumn = MediaStore.Images.ImageColumns.DATE_ADDED, + timeColumn = MediaStore.Images.Media.DATE_ADDED, columns = arrayOf( - MediaStore.Images.ImageColumns.DATE_ADDED, - MediaStore.Images.ImageColumns.MIME_TYPE + MediaStore.Images.Media.DATE_ADDED, + MediaStore.Images.Media.MIME_TYPE, ), - lastTime = fromTimeExternalPhoto - ) { cursor -> - val millis = cursor.getLongOrNull(0) ?: Long.MIN_VALUE + lastTimeInMillis = fromTimeExternalPhoto + ) { millis, cursor -> MediaEntity( mimeType = cursor.getStringOrNull(1) ?: "image/*" ).apply { @@ -189,14 +183,13 @@ class MediaCollector( val internalVideos = getRecentContents( contentResolver = contentResolver, uri = MediaStore.Video.Media.INTERNAL_CONTENT_URI, - timeColumn = MediaStore.Video.VideoColumns.DATE_ADDED, + timeColumn = MediaStore.Video.Media.DATE_ADDED, columns = arrayOf( - MediaStore.Video.VideoColumns.DATE_ADDED, - MediaStore.Video.VideoColumns.MIME_TYPE + MediaStore.Video.Media.DATE_ADDED, + MediaStore.Video.Media.MIME_TYPE ), - lastTime = fromTimeInternalVideo - ) { cursor -> - val millis = cursor.getLongOrNull(0) ?: Long.MIN_VALUE + lastTimeInMillis = fromTimeInternalVideo + ) { millis, cursor -> MediaEntity( mimeType = cursor.getStringOrNull(1) ?: "video/*" ).apply { @@ -216,14 +209,13 @@ class MediaCollector( val externalVideos = getRecentContents( contentResolver = contentResolver, uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI, - timeColumn = MediaStore.Video.VideoColumns.DATE_ADDED, + timeColumn = MediaStore.Video.Media.DATE_ADDED, columns = arrayOf( - MediaStore.Video.VideoColumns.DATE_ADDED, - MediaStore.Video.VideoColumns.MIME_TYPE + MediaStore.Video.Media.DATE_ADDED, + MediaStore.Video.Media.MIME_TYPE ), - lastTime = fromTimeExternalVideo - ) { cursor -> - val millis = cursor.getLongOrNull(0) ?: Long.MIN_VALUE + lastTimeInMillis = fromTimeExternalVideo + ) { millis, cursor -> MediaEntity( mimeType = cursor.getStringOrNull(1) ?: "video/*" ).apply { @@ -236,7 +228,6 @@ class MediaCollector( lastTimeExternalVideoWritten = externalVideos.maxOfOrNull { it.timestamp }?.coerceAtLeast(lastTimeExternalVideoWritten) ?: lastTimeExternalVideoWritten - } companion object { diff --git a/app/src/main/kotlin/kaist/iclab/abclogger/collector/message/MessageCollector.kt b/app/src/main/kotlin/kaist/iclab/abclogger/collector/message/MessageCollector.kt index a9993a8..d0b895b 100644 --- a/app/src/main/kotlin/kaist/iclab/abclogger/collector/message/MessageCollector.kt +++ b/app/src/main/kotlin/kaist/iclab/abclogger/collector/message/MessageCollector.kt @@ -119,15 +119,14 @@ class MessageCollector( val sms = getRecentContents( contentResolver = contentResolver, uri = Telephony.Sms.CONTENT_URI, - lastTime = fromTimeSms, + lastTimeInMillis = fromTimeSms, timeColumn = Telephony.Sms.DATE, columns = arrayOf( Telephony.Sms.DATE, Telephony.Sms.ADDRESS, Telephony.Sms.TYPE ) - ) { cursor -> - val millis = cursor.getLongOrNull(0) ?: Long.MIN_VALUE + ) { millis, cursor -> val number = cursor.getStringOrNull(1) ?: "" val contact = getContact(contentResolver, number) ?: Contact() @@ -158,15 +157,14 @@ class MessageCollector( /** * Time column of MMS messages are stored as second, not millis. */ - lastTime = TimeUnit.MILLISECONDS.toSeconds(fromTimeMms), + lastTimeInMillis = TimeUnit.MILLISECONDS.toSeconds(fromTimeMms), timeColumn = Telephony.Mms.DATE, columns = arrayOf( Telephony.Mms.DATE, Telephony.Mms._ID, Telephony.Mms.MESSAGE_BOX ) - ) { cursor -> - val seconds = cursor.getLongOrNull(0) ?: Long.MIN_VALUE + ) { millis, cursor -> val number = getMmsAddress(contentResolver, cursor.getLongOrNull(1)) ?: "" val contact = getContact(contentResolver, number) ?: Contact() @@ -178,7 +176,7 @@ class MessageCollector( isStarred = contact.isStarred, isPinned = contact.isPinned ).apply { - timestamp = TimeUnit.SECONDS.toMillis(seconds) + timestamp = millis } } diff --git a/app/src/main/kotlin/kaist/iclab/abclogger/ui/main/MainActivity.kt b/app/src/main/kotlin/kaist/iclab/abclogger/ui/main/MainActivity.kt index eeebec0..7f5e643 100644 --- a/app/src/main/kotlin/kaist/iclab/abclogger/ui/main/MainActivity.kt +++ b/app/src/main/kotlin/kaist/iclab/abclogger/ui/main/MainActivity.kt @@ -68,7 +68,6 @@ class MainActivity : BaseActivity() { animateToBottomNav(id == R.id.config_collector || id == R.id.survey_response) } - lifecycleScope.launchWhenCreated { Log.sendReports()