diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 026ec98..20f2e1c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,7 +24,9 @@ - + diff --git a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt index 043de94..a21bf1e 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt @@ -140,8 +140,8 @@ internal class LauncherActivity : AppCompatActivity() { /* ask for the permissions */ private fun askPermissions() { /* phone permission */ - if (this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { - this.requestPermissions(arrayOf(Manifest.permission.CALL_PHONE), 1) + if (this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED || this.checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) { + this.requestPermissions(arrayOf(Manifest.permission.CALL_PHONE,Manifest.permission.READ_SMS), 1) } /* modify system settings */ if (!Settings.System.canWrite(this)) { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt index 1b4aa5c..75d2679 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt @@ -58,8 +58,11 @@ import rasel.lunar.launcher.home.weather.WeatherExecutor import rasel.lunar.launcher.qaccess.QuickAccess import rasel.lunar.launcher.settings.SettingsActivity import rasel.lunar.launcher.todos.MissedCallsAdapter +import rasel.lunar.launcher.todos.SmsLogsAdapter import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.MissedCallGetter +import rasel.lunar.launcher.utils.RecentSmsGetter +import rasel.lunar.launcher.utils.RecentSmsLog import rasel.lunar.launcher.utils.SimpleFingerGestures import java.util.Calendar import java.util.Locale @@ -84,7 +87,9 @@ internal class LauncherHome : Fragment() { binding.favAppsGroup.visibility = View.GONE mWorkManager = WorkManager.getInstance(lActivity!!.application); + mWorkManager?.enqueue(PeriodicWorkRequestBuilder(30, TimeUnit.MINUTES).addTag("RecentSmsGetter").build()) mWorkManager?.enqueue(PeriodicWorkRequestBuilder(30, TimeUnit.MINUTES).addTag("MissedCallGetter").build()) + mSmsWorkInfo = mWorkManager?.getWorkInfosByTagLiveData("RecentSmsGetter"); mSavedWorkInfo = mWorkManager?.getWorkInfosByTagLiveData("MissedCallGetter"); getOutputWorkInfo().observeForever { it.last()?.outputData?.keyValueMap?.forEach { t, u -> @@ -101,15 +106,37 @@ internal class LauncherHome : Fragment() { } } } + + getSmsInfos().observeForever { + it.last()?.outputData?.keyValueMap?.forEach { t, u -> + try { + if (u is String) { + Gson().fromJson(u,RecentSmsLog::class.java)?.let { + smsList.add(it) + } + } + } catch (e : Exception) { + + } finally { + showTodoList() + } + } + } + BLog.LOGE("onCreateView()") return binding.root } private var mSavedWorkInfo: LiveData>? = null + private var mSmsWorkInfo: LiveData>? = null fun getOutputWorkInfo(): LiveData> { return mSavedWorkInfo!! } + fun getSmsInfos(): LiveData> { + return mSmsWorkInfo!! + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) /* handle gesture events */ @@ -131,6 +158,55 @@ internal class LauncherHome : Fragment() { false } } + binding.missedCalls.setOnClickListener { + binding.missedCalls.isChecked = true + BLog.LOGE("binding.missedCalls >> ${binding.missedCalls.isChecked}") + if (callList.size > 0 && isAdded && isResumed && isVisible) { + try { + BLog.LOGE("callList >>> ${callList.size}") + binding.notes.adapter = MissedCallsAdapter(callList, requireContext()) + binding.notes.invalidate() + } catch (e : Exception) { + + } + }} + binding.recentSms.setOnClickListener { + binding.recentSms.isChecked = true + BLog.LOGE("binding.recentSms >> ${binding.recentSms.isChecked}") + if (smsList.size > 0 && isAdded && isResumed && isVisible) { + try { + BLog.LOGE("callList >>> ${smsList.size}") + binding.notes.adapter = SmsLogsAdapter(smsList, requireContext()) + binding.notes.invalidate() + } catch (e : Exception) { + + } + } + } + binding.summaryChoose.setOnCheckedChangeListener { group, checkedId -> + if (binding.missedCalls.isChecked) { + if (callList.size > 0 && isAdded && isResumed && isVisible) { + try { + BLog.LOGE("callList >>> ${callList.size}") + binding.notes.adapter = MissedCallsAdapter(callList, requireContext()) + binding.notes.invalidate() + } catch (e : Exception) { + + } + } + } else if(binding.recentSms.isChecked){ + //binding.notes.adapter = TodoAdapter(null, requireContext()) + if (smsList.size > 0 && isAdded && isResumed && isVisible) { + try { + BLog.LOGE("callList >>> ${callList.size}") + binding.notes.adapter = SmsLogsAdapter(smsList, requireContext()) + binding.notes.invalidate() + } catch (e : Exception) { + + } + } + } + } } override fun onResume() { @@ -160,7 +236,7 @@ internal class LauncherHome : Fragment() { private var mWorkManager: WorkManager? = null var callList = arrayListOf() - + var smsList = arrayListOf() @@ -434,8 +510,16 @@ internal class LauncherHome : Fragment() { } } - } else { + } else if(binding.recentSms.isChecked){ //binding.notes.adapter = TodoAdapter(null, requireContext()) + if (smsList.size > 0 && isAdded && isResumed && isVisible) { + try { + BLog.LOGE("callList >>> ${callList.size}") + binding.notes.adapter = SmsLogsAdapter(smsList, requireContext()) + } catch (e : Exception) { + + } + } } } diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt new file mode 100644 index 0000000..7a82d4f --- /dev/null +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt @@ -0,0 +1,114 @@ +/* + * Lunar Launcher + * Copyright (C) 2022 Md Rasel Hossain + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package rasel.lunar.launcher.todos + +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.bottomsheet.BottomSheetDialog +import rasel.lunar.launcher.LauncherActivity.Companion.lActivity +import rasel.lunar.launcher.R +import rasel.lunar.launcher.databinding.ListItemBinding +import rasel.lunar.launcher.databinding.TodoDialogBinding +import rasel.lunar.launcher.helpers.UniUtils.Companion.copyToClipboard +import rasel.lunar.launcher.home.MissedCall +import rasel.lunar.launcher.utils.BLog +import rasel.lunar.launcher.utils.RecentSmsLog +import java.util.* +import kotlin.collections.ArrayList + + +internal class SmsLogsAdapter( + private val callList: ArrayList, + private val context: Context) : RecyclerView.Adapter() { + + private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer) + + override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): SmsLogHolder { + val binding = ListItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + return SmsLogHolder(binding) + } + + override fun getItemCount(): Int { +// BLog.LOGE("callList.size >>> ${callList.size}") + return callList.size + } + + @SuppressLint("SetTextI18n") + override fun onBindViewHolder(holder: SmsLogHolder, position: Int) { + val todo = callList[position] + BLog.LOGE("callList >>> ${callList[position]}") + holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} , ${todo.body} : ${todo.pstDate} : ${todo.type}" + + /* multiline texts are enabled for TodoManager */ + holder.view.itemText.isSingleLine = false + /* launch edit or update dialog on item click */ + holder.view.itemText.setOnClickListener { updateDialog(position) } + /* copy texts on long click */ + holder.view.itemText.setOnLongClickListener { + + true + } + + } + + inner class SmsLogHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root) + + /* update dialog */ + private fun updateDialog(position: Int) { +// val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog) +// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context)) +// bottomSheetDialog.setContentView(dialogBinding.root) +// bottomSheetDialog.show() +// bottomSheetDialog.dismissWithAnimation = true +// +// val databaseHandler = DatabaseHandler(context) +// val todo = databaseHandler.todos[position] +// +// dialogBinding.apply { +// deleteAllConfirmation.visibility = View.GONE +// todoInput.setText(todo.name) +// todoCancel.text = context.getString(R.string.delete) +// todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light)) +// todoOk.text = context.getString(R.string.update) +// } +// +// /* delete the item */ +// dialogBinding.todoCancel.setOnClickListener { +// +// } +// +// /* update the item */ +// dialogBinding.todoOk.setOnClickListener { +// val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' } +// if (updatedTodoString.isNotEmpty()) { +// todo.name = updatedTodoString +// databaseHandler.updateTodo(todo) +// bottomSheetDialog.dismiss() +// } else { +// dialogBinding.todoInput.error = context.getString(R.string.empty_text_field) +// } +// } + } + +} diff --git a/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt b/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt index 617cdd1..be426d9 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt @@ -1,15 +1,12 @@ package rasel.lunar.launcher.utils -import android.annotation.SuppressLint -import android.app.IntentService import android.content.Context -import android.content.Intent -import android.database.Cursor -import android.os.IBinder import android.provider.CallLog +import android.provider.Telephony import androidx.work.Data import androidx.work.Worker import androidx.work.WorkerParameters +import com.google.gson.Gson import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.home.MissedCall import java.text.SimpleDateFormat @@ -110,4 +107,116 @@ class MissedCallGetter : Worker { return Result.success(resultData.build()); } -} \ No newline at end of file +} + + +class RecentSmsGetter : Worker { + + constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) { + + } + + + override fun doWork(): Result { + BLog.LOGE("phNumber == onStart") + var resultData = Data.Builder() + var dateParam = Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24 * 3)).time.toString() + lActivity?.contentResolver?.query( + Telephony.Sms.CONTENT_URI, arrayOf( + Telephony.Sms.ADDRESS, + Telephony.Sms.TYPE, + Telephony.Sms.DATE, + Telephony.Sms.DATE_SENT, + Telephony.Sms.BODY, + Telephony.Sms.PERSON, + ), Telephony.Sms.DATE + ">= ? OR " + Telephony.Sms.DATE_SENT + " >= ?", arrayOf(dateParam, dateParam), Telephony.Sms.DEFAULT_SORT_ORDER)?.let { managedCursor -> + try { + BLog.LOGE("phNumber == onResult") + val address = managedCursor.getColumnIndex(Telephony.Sms.ADDRESS) + val type = managedCursor.getColumnIndex(Telephony.Sms.TYPE) + val date = managedCursor.getColumnIndex(Telephony.Sms.DATE) + val sendDate = managedCursor.getColumnIndex(Telephony.Sms.DATE_SENT) + val bodyIdx = managedCursor.getColumnIndex(Telephony.Sms.BODY) + val name = managedCursor.getColumnIndex(Telephony.Sms.PERSON) + var missedCalls = arrayListOf() + while (managedCursor.moveToNext()) { + val phNumber = managedCursor.getString(address) // mobile number + val callType = managedCursor.getString(type) // call type + val reciveDate = managedCursor.getString(date) // call date + val sendedDate = managedCursor.getString(sendDate) // call date + val smsBody = managedCursor.getString(bodyIdx) + val callerName = managedCursor.getString(name) + + var dir: String = "" + val dircode = callType.toInt() + when (dircode) { + Telephony.Sms.MESSAGE_TYPE_ALL -> {dir = "MESSAGE_TYPE_ALL"} + Telephony.Sms.MESSAGE_TYPE_INBOX -> {dir = "MESSAGE_TYPE_INBOX"} + Telephony.Sms.MESSAGE_TYPE_SENT -> {dir = "MESSAGE_TYPE_SENT"} + Telephony.Sms.MESSAGE_TYPE_DRAFT -> {dir = "MESSAGE_TYPE_DRAFT"} + Telephony.Sms.MESSAGE_TYPE_OUTBOX -> {dir = "MESSAGE_TYPE_OUTBOX"} + Telephony.Sms.MESSAGE_TYPE_FAILED -> {dir = "MESSAGE_TYPE_FAILED"} + Telephony.Sms.MESSAGE_TYPE_QUEUED -> {dir = "MESSAGE_TYPE_QUEUED"} + } + + BLog.LOGE("phNumber == ${phNumber}\n" + + " dir == ${dir}\n" + + " reciveDate == ${reciveDate}\n" + + " sendedDate == ${sendedDate}\n" + + " smsBody == ${smsBody}\n" + + " callerName == ${callerName}\n") + + var log = RecentSmsLog( + phNumber, + dir, + reciveDate, + sendedDate, + smsBody, + callerName ?: "" + ) + resultData.put(phNumber +" _"+ reciveDate, log.toJson()) + } + + + + +// resultData.put() + } catch (e: Exception) { + + } finally { + managedCursor.close() + } + } + return Result.success(resultData.build()); + } + +} + +class RecentSmsLog { + var addr : String = "" + var type : String = "" + var rcvDate : String = "" + var pstDate : String = "" + var body : String = "" + var person : String = "" + + constructor( + addr: String, + type: String, + rcvDate: String, + pstDate: String, + body: String, + person: String + ) { + this.addr = addr + this.type = type + this.rcvDate = rcvDate + this.pstDate = pstDate + this.body = body + this.person = person + } + + fun toJson() : String { + return Gson().toJson(this) + } +} diff --git a/app/src/main/res/layout/launcher_home.xml b/app/src/main/res/layout/launcher_home.xml index dda4a51..ba2c9ad 100644 --- a/app/src/main/res/layout/launcher_home.xml +++ b/app/src/main/res/layout/launcher_home.xml @@ -94,6 +94,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content"/>