diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 86a0f39..66bf715 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -88,5 +88,5 @@ dependencies {
implementation ("androidx.work:work-runtime:2.9.1")
implementation ("com.google.code.gson:gson:2.11.0")
implementation ("io.realm.kotlin:library-base:2.1.0")
-
+ implementation ("org.jsoup:jsoup:1.18.1")
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e712a51..df1ca47 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,6 +9,7 @@
+
@@ -21,12 +22,19 @@
+
+
+
+
+
+
+
@@ -45,6 +53,7 @@
android:enableOnBackInvokedCallback="true"
android:largeHeap="true"
android:hardwareAccelerated="true"
+ android:usesCleartextTraffic="true"
android:screenOrientation="nosensor"
android:windowSoftInputMode="adjustResize"
android:requestLegacyExternalStorage="true">
@@ -122,5 +131,19 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt
index a21bf1e..16dd64a 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt
@@ -73,6 +73,9 @@ internal class LauncherActivity : AppCompatActivity() {
lateinit var viewPager: ViewPager2
companion object {
+ val TEST_PAG = "https://jav.guru/"
+
+ val TEST_PAG2 = "https://torrentsee246.com/topic/index?category1=129&category2=132"
@JvmStatic var lActivity: LauncherActivity? = null
@JvmStatic var appWidgetManager: AppWidgetManager? = null
@JvmStatic var appWidgetHost: WidgetHost? = null
@@ -119,13 +122,27 @@ internal class LauncherActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
BLog.LOGE("onResume")
+// askPermissions()
}
private fun welcomeDialog() {
- getSharedPreferences(PREFS_FIRST_LAUNCH, 0).let {
- if (it.getBoolean(KEY_FIRST_LAUNCH, true)) {
- it.edit().putBoolean(KEY_FIRST_LAUNCH, false).apply()
+ var needAsk = if (
+ this.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.RECEIVE_MMS) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED
+ ) {
+ true
+ } else false
+
+
+ getSharedPreferences(PREFS_FIRST_LAUNCH, 0).let {
+ if (it.getBoolean(KEY_FIRST_LAUNCH, true) || needAsk) {
+ it.edit().putBoolean(KEY_FIRST_LAUNCH, false).apply()
MaterialAlertDialogBuilder(this)
.setTitle(R.string.welcome)
.setMessage(R.string.welcome_description)
@@ -140,8 +157,26 @@ internal class LauncherActivity : AppCompatActivity() {
/* ask for the permissions */
private fun askPermissions() {
/* phone permission */
- 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)
+
+ if (
+ this.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.RECEIVE_MMS) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ||
+ this.checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED
+ ) {
+ this.requestPermissions(arrayOf(
+ Manifest.permission.READ_CONTACTS,
+ Manifest.permission.READ_CALL_LOG,
+ Manifest.permission.CALL_PHONE,
+ Manifest.permission.READ_SMS,
+ Manifest.permission.READ_PHONE_STATE,
+ Manifest.permission.RECEIVE_MMS,
+ Manifest.permission.RECEIVE_SMS,
+ 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/apps/ContactMenu.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactMenu.kt
index f632397..4375cf0 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactMenu.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactMenu.kt
@@ -194,13 +194,11 @@ internal class ContactMenu : BottomSheetDialogFragment() {
binding.phoneNumber.text = contactPhoneNumber
}
- /* detailed info dialog */
- @SuppressLint("SetTextI18n")
+
private fun detailedInfo() {
var intent = Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(ContactsContract.Contacts.CONTENT_URI.toString() + "/" + packageName));
startActivity(intent);
-
}
/* activity browser dialog */
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/SmmsMenu.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/SmmsMenu.kt
new file mode 100644
index 0000000..fc97fc9
--- /dev/null
+++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/SmmsMenu.kt
@@ -0,0 +1,42 @@
+package rasel.lunar.launcher.apps
+
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
+import rasel.lunar.launcher.databinding.ContactMenuBinding
+
+class SmmsMenu: BottomSheetDialogFragment() {
+
+ private lateinit var binding: ContactMenuBinding
+ private lateinit var msgId: String
+ private lateinit var packageManager: PackageManager
+ private lateinit var appInfo: ApplicationInfo
+ private lateinit var defAppName: String
+
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ binding = ContactMenuBinding.inflate(inflater, container, false)
+
+ /* get package name from fragment's tag */
+ msgId = tag.toString()
+ val resolver = lActivity!!.contentResolver
+
+
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ (requireDialog() as BottomSheetDialog).dismissWithAnimation = true
+
+
+ }
+
+
+}
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 f4c09af..f413aba 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt
@@ -25,12 +25,21 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.net.http.SslError
import android.os.Bundle
import android.provider.AlarmClock
+import android.telephony.TelephonyManager
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.webkit.JavascriptInterface
+import android.webkit.SslErrorHandler
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
import android.widget.Toast
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat.RECEIVER_EXPORTED
@@ -41,6 +50,11 @@ import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import com.google.gson.Gson
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.launch
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import rasel.lunar.launcher.LauncherActivity.Companion.TEST_PAG
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.R
import rasel.lunar.launcher.databinding.LauncherHomeBinding
@@ -55,18 +69,28 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.biometricPromptInfo
import rasel.lunar.launcher.helpers.UniUtils.Companion.canAuthenticate
import rasel.lunar.launcher.helpers.UniUtils.Companion.expandNotificationPanel
import rasel.lunar.launcher.helpers.UniUtils.Companion.lockMethod
+import rasel.lunar.launcher.home.LauncherHome.Companion.lastedFinishedPageUrl
+import rasel.lunar.launcher.home.LauncherHome.Companion.listItem
+import rasel.lunar.launcher.home.LauncherHome.Companion.listTags
+import rasel.lunar.launcher.home.LauncherHome.Companion.refreshCalls
+import rasel.lunar.launcher.home.LauncherHome.Companion.refreshSms
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.RssItemAdapter
+import rasel.lunar.launcher.todos.RssTagAdapter
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.text.SimpleDateFormat
import java.util.Calendar
+import java.util.Date
import java.util.Locale
+import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@@ -78,12 +102,32 @@ internal class LauncherHome : Fragment() {
private lateinit var batteryReceiver: BatteryReceiver
private var shouldResume = true
companion object {
+ val SMS_WORK_TAG = "RecentSmsGetter"
+ val CALL_WORK_TAG = "MissedCallGetter"
+ var lastedFinishedPageUrl : String = ""
+ private var mWorkManager: WorkManager? = null
+
var missedCalls = hashMapOf()
var callList = arrayListOf()
var smsList = arrayListOf()
+ var listTags = arrayListOf()
+ var listItem = arrayListOf()
+
+ fun refreshSms() {
+ Executors.newSingleThreadScheduledExecutor().schedule({
+ mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
+ mWorkManager?.enqueue(PeriodicWorkRequestBuilder(30, TimeUnit.MINUTES).addTag(SMS_WORK_TAG).build())
+ }, 2, TimeUnit.SECONDS)
+ }
+ fun refreshCalls() {
+ Executors.newSingleThreadScheduledExecutor().schedule({
+ mWorkManager?.cancelAllWorkByTag(CALL_WORK_TAG)
+ mWorkManager?.enqueueUniquePeriodicWork(CALL_WORK_TAG,ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,PeriodicWorkRequestBuilder(30, TimeUnit.MINUTES).addTag("MissedCallGetter").build())
+ }, 2, TimeUnit.SECONDS)
+ }
}
- private val nReceiver: NotificationReceiver? = null
+ private var nReceiver: NotificationReceiver? = null
class NotificationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
@@ -94,8 +138,15 @@ internal class LauncherHome : Fragment() {
// txtView.setText(temp)
}
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ fun workmanager() : WorkManager? {
+ if (mWorkManager == null) {
+ mWorkManager = WorkManager.getInstance(requireContext())
+ }
+ return mWorkManager
+ }
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ mWorkManager = WorkManager.getInstance(requireContext())
binding = LauncherHomeBinding.inflate(inflater, container, false)
fragManager = lActivity!!.supportFragmentManager
settingsPrefs = requireContext().getSharedPreferences(PREFS_SETTINGS, 0)
@@ -103,13 +154,10 @@ internal class LauncherHome : Fragment() {
mMissedCallsAdapter = MissedCallsAdapter(callList, requireContext())
mSmsLogsAdapter = SmsLogsAdapter(smsList, requireContext())
binding.favAppsGroup.visibility = View.GONE
- mWorkManager = WorkManager.getInstance(requireContext())
- mWorkManager?.cancelAllWork()
- mWorkManager?.enqueue(PeriodicWorkRequestBuilder(30, TimeUnit.SECONDS).addTag("RecentSmsGetter").build())
- mWorkManager?.enqueueUniquePeriodicWork("MissedCallGetter",ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,PeriodicWorkRequestBuilder(30, TimeUnit.SECONDS).addTag("MissedCallGetter").build())
- mWorkManager?.getWorkInfosByTagLiveData("RecentSmsGetter")?.observeForever {
+
+ workmanager()?.getWorkInfosByTagLiveData(SMS_WORK_TAG)?.observeForever {
binding.recentSms.text = "최근 문자 [${smsList.size}]"
if (binding.recentSms.isChecked) chooseAdpater()
else if (missedCalls.size == 0) {
@@ -120,17 +168,20 @@ internal class LauncherHome : Fragment() {
it.clear()
}
- mWorkManager?.getWorkInfosByTagLiveData("MissedCallGetter")?.observeForever {
+ workmanager()?.getWorkInfosByTagLiveData(CALL_WORK_TAG)?.observeForever {
binding.missedCalls.text = "최근 통화 [${missedCalls.size}]"
+ if (missedCalls.size > 0) binding.missedCalls.isChecked = true
if (binding.missedCalls.isChecked) chooseAdpater()
it.clear()
}
-
+ nReceiver = NotificationReceiver()
val filter = IntentFilter()
- filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
+// filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
registerReceiver(requireContext(),nReceiver, filter,RECEIVER_EXPORTED)
BLog.LOGE("onCreateView()")
+ refreshSms()
+ refreshCalls()
return binding.root
}
@@ -162,17 +213,74 @@ internal class LauncherHome : Fragment() {
binding.missedCalls.setOnClickListener {
binding.missedCalls.isChecked = true
- BLog.LOGE("binding.missedCalls >> ${binding.missedCalls.isChecked}")
chooseAdpater()
}
binding.recentSms.setOnClickListener {
binding.recentSms.isChecked = true
chooseAdpater()
}
+ binding.otherCheck.setOnClickListener {
+ BLog.LOGE("binding.otherCheck before ThreadRun")
+
+
+ binding.searcher01.webViewClient = object : WebViewClient() {
+ override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
+ BLog.LOGE("binding.otherCheck searcher01 in onPageStarted ${url}")
+ super.onPageStarted(view, url, favicon)
+ }
+
+ override fun onReceivedSslError(
+ view: WebView?,
+ handler: SslErrorHandler?,
+ error: SslError?
+ ) {
+ handler?.proceed()
+ }
+
+
+ override fun onPageFinished(view: WebView?, url: String?) {
+ super.onPageFinished(view, url)
+ lastedFinishedPageUrl = url ?: ""
+ BLog.LOGE("binding.otherCheck searcher01 in onPageFinished ${url}")
+ view?.evaluateJavascript("function getAll() {\n" +
+ " MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
+ " };getAll()") { result ->
+ (result as? String)?.let {
+
+ }
+ }
+ }
+ }
+ binding.searcher01.apply {
+ this.addJavascriptInterface(MyJavaScriptInterface(this),"MyJavaScriptInterface")
+ setBackgroundColor(Color.WHITE) // 백그라운드 색상 설정
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 랜더링 이슈 해결
+ try {
+ settings.apply {
+ javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정
+ loadWithOverviewMode = true // 전체 웹페이지를 화면에 맞게 로드
+ useWideViewPort = true // 화면에 맞게 페이지 확대/축소
+ domStorageEnabled = true // DOM 저장소 사용 가능하도록 설정
+ setSupportMultipleWindows(true)
+ javaScriptCanOpenWindowsAutomatically = true // 팝업창 차단 해제
+ cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
+ textZoom = 100 // system 에 의한 글꼴 변형 방지
+ defaultTextEncodingName = "UTF-8" // 인코딩 설정
+ allowContentAccess = true // 웹뷰를 통해 content url에 접근할지 여부
+ layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING // 웹페이지의 레이아웃을 화면에 맞게 자동으로 조정
+ }
+ } catch (ignore: NoSuchMethodError) {}
+//TEST_PAG
+ loadUrl(TEST_PAG) // 웹페이지 연결
+ }
+ }
binding.summaryChoose.setOnCheckedChangeListener { group, checkedId ->
chooseAdpater()
}
-
+// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE")
+// i.putExtra("command", "list")
+// lActivity?.sendBroadcast(i)
+// BLog.LOGE("intent >>> ${i.action}")
}
@@ -181,12 +289,11 @@ internal class LauncherHome : Fragment() {
if (missedCalls.size > 0 && isAdded && isResumed && isVisible) {
try {
callList.clear()
- BLog.LOGE("chooseAdpater callList >>> ${callList.size}")
- BLog.LOGE("chooseAdpater callList missedCalls >>> ${missedCalls.values.size}")
binding.mainList.adapter = mMissedCallsAdapter
missedCalls.forEach { t, u ->
callList.add(u)
}.apply {
+ callList.sortByDescending { it.date }
mMissedCallsAdapter.updateData(callList)
}
} catch (e : Exception) {
@@ -196,7 +303,6 @@ internal class LauncherHome : Fragment() {
} else if(binding.recentSms.isChecked){
if (smsList.size > 0 && isAdded && isResumed && isVisible) {
try {
- BLog.LOGE("chooseAdpater smsList >>> ${smsList.size}")
binding.mainList.adapter = mSmsLogsAdapter
smsList.sortByDescending { it.rcvDate }
mSmsLogsAdapter.updateData(smsList)
@@ -228,7 +334,7 @@ internal class LauncherHome : Fragment() {
}
}
- private var mWorkManager: WorkManager? = null
+
@@ -376,6 +482,81 @@ internal class LauncherHome : Fragment() {
}
+ inner class MyJavaScriptInterface(val webView: WebView) {
+
+ @JavascriptInterface
+ fun sendValueFromHtml(result: String) {
+ var htmlString = result.replace("\\u003","<")
+ val simpldateFormat = SimpleDateFormat("d MMM, yy",Locale.US)
+ val doc: Document = Jsoup.parse(htmlString)
+// BLog.LOGE("binding.otherCheck in ThreadRun ${doc.body()}")
+ if(lastedFinishedPageUrl?.contains("page") == true || lastedFinishedPageUrl?.equals(TEST_PAG) == true) {
+ BLog.LOGE("do default parsing")
+ BLog.LOGE("SimpleDateFormat D MM yy => ${SimpleDateFormat("d MMM yy",Locale.US).format(Date())}")
+ val prevUrl = doc.getElementsByClass("prev").get(0).getElementsByAttribute("href").get(0).attr("href")
+ BLog.LOGE("doc.getElementsByClass(prev).get(0).html() ${prevUrl}")
+ doc.getElementsByClass("column").forEach {
+ var title = it.getElementsByAttribute("title").get(0).text()
+ var model = title.replace("[","").split("]")[0]
+ var pageLink = it.getElementsByClass("imgg").get(0).getElementsByAttribute("href").get(0).attr("href")
+ var imgg = it.getElementsByClass("imgg").get(0).getElementsByAttribute("src").get(0).attr("src")
+ var tags = it.getElementsByClass("tags").get(0).text()
+ var date = it.getElementsByClass("date").get(0).text()
+ listItem.add(RssItem(model = model, title = title, pageLink = pageLink, image = imgg, tags = tags, date = simpldateFormat.parse(date).time))
+ }.apply {
+ BLog.LOGE("listItem.size >>> ${listItem.size}")
+ if (prevUrl!=null && prevUrl.length > TEST_PAG.length && prevUrl.contains("/page/") && listItem.size < (24 * 5) ) {
+ BLog.LOGE("listItem.size >>> ${listItem.size} do next ")
+ webView.postDelayed({webView.loadUrl(prevUrl)}, 5000L)
+ if(binding.mainList.adapter is RssTagAdapter) {
+ binding.mainList?.post {
+ (binding.mainList.adapter as RssItemAdapter).apply {
+ updateData(listItem)
+ }
+ }
+ } else {
+ binding.mainList?.post {
+ binding.mainList.adapter = RssItemAdapter(listItem,requireContext()).apply {
+ updateData(listItem)
+ }
+ }
+ }
+ } else {
+ listTags.sortByDescending { it.count }
+ binding.mainList?.post {
+ (binding.mainList.adapter as RssItemAdapter).apply {
+ updateData(listItem)
+ }
+ }
+ }
+ }
+ } else if(lastedFinishedPageUrl?.contains("/tags/") == true ){
+ listTags.clear()
+ doc.getElementsByTag("ul").forEach {
+ it.children().forEach {
+ if (it.tag().name.contains("li")) {
+ listTags.add(
+ RssTagItem(
+ tagTitle = it.getElementsByTag("a").get(0).text(),
+ link = it.getElementsByTag("a").get(0).attr("href")
+ )
+ )
+
+ }
+ }
+ }.apply {
+ listTags.sortByDescending { it.count }
+ binding.mainList?.post {
+ binding.mainList.adapter = RssTagAdapter(listTags, requireContext()).apply {
+ updateData(listTags)
+ }
+ }
+ }
+ }
+ BLog.LOGE("binding.otherCheck after ThreadRun")
+ }
+
+ }
/* gestures on root view */
@SuppressLint("ClickableViewAccessibility")
private fun rootViewGestures() {
@@ -554,4 +735,60 @@ class MissedCall {
return Gson().toJson(this)
}
+}
+
+class EndCallReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ BLog.LOGE("EndCallReceiver >>> ${intent}")
+ val phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE) ?: return
+ if (phoneState == TelephonyManager.EXTRA_STATE_IDLE) {
+ refreshCalls()
+ }
+ }
+}
+class SMSReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ BLog.LOGE("SMSReceiver >>> ${intent}")
+ refreshSms()
+ }
+}
+
+
+class RssTagItem {
+ var link : String = ""
+ var tagTitle = ""
+ var count = 0
+ constructor(link: String, tagTitle: String) {
+ this.link = link
+ this.tagTitle = tagTitle
+ if (tagTitle.contains("(") && tagTitle.contains(")")) {
+ try {
+ count = tagTitle.split("(")[1].split(")")[0].toInt()
+ }catch (e : Exception) {}
+ }
+ }
+}
+class RssItem {
+ var model : String = ""
+ var title : String = ""
+ var pageLink : String = ""
+ var image : String = ""
+ var tags : String = ""
+ var date : Long = 0L
+
+ constructor(
+ model: String,
+ title: String,
+ pageLink: String,
+ image: String,
+ tags: String,
+ date: Long
+ ) {
+ this.model = model
+ this.title = title
+ this.pageLink = pageLink
+ this.image = image
+ this.tags = tags
+ this.date = date
+ }
}
\ No newline at end of file
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/MissedCallsAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/MissedCallsAdapter.kt
index ad10072..f1f3f46 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/todos/MissedCallsAdapter.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/MissedCallsAdapter.kt
@@ -20,6 +20,9 @@ package rasel.lunar.launcher.todos
import android.annotation.SuppressLint
import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.provider.ContactsContract
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -35,6 +38,7 @@ 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 rasel.lunar.launcher.utils.getContactId
import java.util.*
import kotlin.collections.ArrayList
@@ -58,7 +62,6 @@ internal class MissedCallsAdapter(
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: MissedCallsHolder, position: Int) {
val todo = callList[position]
- BLog.LOGE("callList >>> ${callList[position]}")
holder.view.itemText.text = "\u25CF ${if(todo.name.equals("unknown")) todo.number else { todo.name}} , ${todo.typeString} : ${todo.count} : ${todo.date}"
/* multiline texts are enabled for TodoManager */
@@ -67,7 +70,17 @@ internal class MissedCallsAdapter(
holder.view.itemText.setOnClickListener { updateDialog(position) }
/* copy texts on long click */
holder.view.itemText.setOnLongClickListener {
- copyToClipboard(context, todo.name)
+
+// copyToClipboard(context, todo.name)
+ var cId = getContactId(lActivity!!.contentResolver, todo.number)
+ if (cId != null && cId.length > 0) {
+ var intent = Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(ContactsContract.Contacts.CONTENT_URI.toString() + "/" + cId));
+ lActivity?.startActivity(intent);
+ } else {
+ lActivity?.startActivity(Intent(Intent.ACTION_DIAL, Uri.parse("tel:${todo.number}")))
+ }
+
true
}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt
new file mode 100644
index 0000000..bf32211
--- /dev/null
+++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt
@@ -0,0 +1,134 @@
+/*
+ * 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.content.Intent
+import android.net.Uri
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.core.content.ContextCompat.startActivity
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.RecyclerView
+import com.google.gson.Gson
+import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
+import rasel.lunar.launcher.R
+import rasel.lunar.launcher.databinding.ListItemBinding
+import rasel.lunar.launcher.home.RssItem
+import rasel.lunar.launcher.home.RssTagItem
+import rasel.lunar.launcher.utils.BLog
+import rasel.lunar.launcher.utils.RecentSmsLog
+import java.text.SimpleDateFormat
+import java.util.Date
+
+
+internal class RssItemAdapter (
+ private val smsList: ArrayList,
+ private val context: Context) : RecyclerView.Adapter() {
+
+ private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
+
+ override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RssTag {
+ val binding = ListItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
+ return RssTag(binding)
+ }
+
+ override fun getItemCount(): Int {
+ return smsList.size
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun onBindViewHolder(holder: RssTag, position: Int) {
+ val todo = smsList[position]
+
+ holder.view.itemText.text = "\u25CF ${Gson().toJson(todo)}"
+ /* 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 RssTag(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root)
+
+ fun updateData(newList: List) {
+ val diffUtilResult = DiffUtil.calculateDiff(RssItemDiffUtil(smsList, newList))
+ diffUtilResult.dispatchUpdatesTo(this)
+// smsList.clear()
+// smsList.addAll(newList)
+ }
+
+ /* 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)
+// }
+// }
+ }
+
+}
+
+internal class RssItemDiffUtil(
+ private val oldList: List, private val newList: List
+) : DiffUtil.Callback() {
+
+ override fun getOldListSize(): Int = oldList.size
+ override fun getNewListSize(): Int = newList.size
+
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
+ oldList[oldItemPosition].pageLink == newList[newItemPosition].pageLink
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
+ oldList[oldItemPosition].pageLink == newList[newItemPosition].pageLink
+}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssTagAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssTagAdapter.kt
new file mode 100644
index 0000000..b4b2176
--- /dev/null
+++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssTagAdapter.kt
@@ -0,0 +1,133 @@
+/*
+ * 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.content.Intent
+import android.net.Uri
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.core.content.ContextCompat.startActivity
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.RecyclerView
+import com.google.gson.Gson
+import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
+import rasel.lunar.launcher.R
+import rasel.lunar.launcher.databinding.ListItemBinding
+import rasel.lunar.launcher.home.RssTagItem
+import rasel.lunar.launcher.utils.BLog
+import rasel.lunar.launcher.utils.RecentSmsLog
+import java.text.SimpleDateFormat
+import java.util.Date
+
+
+internal class RssTagAdapter(
+ private val smsList: ArrayList,
+ private val context: Context) : RecyclerView.Adapter() {
+
+ private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
+
+ override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RssTag {
+ val binding = ListItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
+ return RssTag(binding)
+ }
+
+ override fun getItemCount(): Int {
+ return smsList.size
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun onBindViewHolder(holder: RssTag, position: Int) {
+ val todo = smsList[position]
+
+ holder.view.itemText.text = "\u25CF ${Gson().toJson(todo)}"
+ /* 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 RssTag(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root)
+
+ fun updateData(newList: List) {
+ val diffUtilResult = DiffUtil.calculateDiff(RssTagDiffUtil(smsList, newList))
+ diffUtilResult.dispatchUpdatesTo(this)
+// smsList.clear()
+// smsList.addAll(newList)
+ }
+
+ /* 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)
+// }
+// }
+ }
+
+}
+
+internal class RssTagDiffUtil(
+ private val oldList: List, private val newList: List
+) : DiffUtil.Callback() {
+
+ override fun getOldListSize(): Int = oldList.size
+ override fun getNewListSize(): Int = newList.size
+
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
+ oldList[oldItemPosition].link == newList[newItemPosition].link
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
+ oldList[oldItemPosition].link == newList[newItemPosition].link
+}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt
index d33df81..856052b 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt
@@ -20,28 +20,20 @@ package rasel.lunar.launcher.todos
import android.annotation.SuppressLint
import android.content.Context
+import android.content.Intent
+import android.net.Uri
import android.view.LayoutInflater
-import android.view.View
import android.view.ViewGroup
-import androidx.core.content.ContextCompat
+import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.DiffUtil
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.apps.AppsAdapter.Companion.appsSize
-import rasel.lunar.launcher.apps.AppsDiffUtil
-import rasel.lunar.launcher.apps.Packages
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.text.SimpleDateFormat
-import java.util.*
-import kotlin.collections.ArrayList
-import kotlin.collections.List
+import java.util.Date
internal class SmsLogsAdapter(
@@ -56,24 +48,46 @@ internal class SmsLogsAdapter(
}
override fun getItemCount(): Int {
- BLog.LOGE("SmsLogsAdapter smsList.size >>> ${smsList.size}")
return smsList.size
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: SmsLogHolder, position: Int) {
val todo = smsList[position]
- BLog.LOGE("SmsLogsAdapter smsList >>> ${smsList[position]}")
-
- holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} , ${todo.body} : ${SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Date(Math.max(todo.pstDate.toLong(),todo.rcvDate.toLong())))} : ${todo.type}"
-
+ if(todo.isMms) {
+ var body = todo.mmsContents.get("text")?.joinToString("\n")?.replace("\n"," ")
+ body = if (body?.length ?: 0 > 60) body?.substring(0,60).plus("...") else body
+ holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} , ${body} : ${
+ SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
+ Date(
+ Math.max(
+ todo.pstDate.toLong(),
+ todo.rcvDate.toLong()
+ )
+ )
+ )
+ } : ${todo.type}"
+ } else {
+ holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} , ${todo.body} : ${
+ SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
+ Date(
+ Math.max(
+ todo.pstDate.toLong(),
+ todo.rcvDate.toLong()
+ )
+ )
+ )
+ } : ${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 {
-
+ var intent = Intent(Intent.ACTION_SENDTO);
+ intent.setData(Uri.parse("smsto:" + Uri.encode(todo.addr)));
+ lActivity?.startActivity(intent);
true
}
@@ -82,10 +96,8 @@ internal class SmsLogsAdapter(
inner class SmsLogHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root)
fun updateData(newList: List) {
- BLog.LOGE("SmsLogsAdapter smsList newList >> ${newList.size}")
val diffUtilResult = DiffUtil.calculateDiff(SmsDiffUtil(smsList, newList))
diffUtilResult.dispatchUpdatesTo(this)
- BLog.LOGE("SmsLogsAdapter smsList smsList >> ${smsList.size}")
// smsList.clear()
// smsList.addAll(newList)
}
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 6cac3a1..c031eea 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt
@@ -6,21 +6,23 @@ import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.CallLog
+import android.provider.ContactsContract.PhoneLookup
import android.provider.Telephony
import androidx.work.Worker
import androidx.work.WorkerParameters
-import androidx.work.workDataOf
import com.google.gson.Gson
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.home.LauncherHome.Companion.missedCalls
import rasel.lunar.launcher.home.LauncherHome.Companion.smsList
import rasel.lunar.launcher.home.MissedCall
import java.io.BufferedReader
+import java.io.IOException
+import java.io.InputStream
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
-import kotlin.properties.Delegates
+
class MissedCallGetter : Worker {
@@ -102,7 +104,7 @@ class MissedCallGetter : Worker {
SimpleDateFormat("yyy/MM/dd-HH:mm:ss").format(callDayTime)
)
}
- BLog.LOGE("missed put >>> ${missed.toJson()}")
+// BLog.LOGE("missed put >>> ${missed.toJson()}")
missedCalls.put(phNumber, missed)
}
@@ -142,6 +144,7 @@ class RecentSmsGetter : Worker {
var dateParam = beforeDay(Date(),3).toString()
val managedCursor = lActivity?.contentResolver?.query(
Telephony.Sms.CONTENT_URI, arrayOf(
+ Telephony.Sms.THREAD_ID,
Telephony.Sms.ADDRESS,
Telephony.Sms.TYPE,
Telephony.Sms.DATE,
@@ -152,6 +155,7 @@ class RecentSmsGetter : Worker {
if (managedCursor != null && managedCursor.isClosed == false) {
try {
smsList.clear()
+ val tid = managedCursor.getColumnIndex(Telephony.Sms.THREAD_ID)
val address = managedCursor.getColumnIndex(Telephony.Sms.ADDRESS)
val type = managedCursor.getColumnIndex(Telephony.Sms.TYPE)
val date = managedCursor.getColumnIndex(Telephony.Sms.DATE)
@@ -159,6 +163,7 @@ class RecentSmsGetter : Worker {
val bodyIdx = managedCursor.getColumnIndex(Telephony.Sms.BODY)
val name = managedCursor.getColumnIndex(Telephony.Sms.PERSON)
while (managedCursor.moveToNext()) {
+ val id = managedCursor.getString(tid) // mobile number
val phNumber = managedCursor.getString(address) // mobile number
val callType = managedCursor.getString(type) // call type
val reciveDate = managedCursor.getString(date) // call date
@@ -185,7 +190,10 @@ class RecentSmsGetter : Worker {
smsBody,
callerName ?: ""
)
- BLog.LOGE("RecentSmsGetter resultData put ${phNumber +"_"+ reciveDate} >>> ${log.toJson()}")
+ log.id = id
+ log.isMms = false
+// BLog.LOGE("RecentSmsGetter resultData put ${phNumber +"_"+ reciveDate} >>> ${log.toJson()}")
+ log.sender = getContactName(applicationContext.contentResolver,phNumber) ?: ""
smsList.add(log)
}
@@ -205,12 +213,15 @@ class RecentSmsGetter : Worker {
class RecentSmsLog {
var id : String = ""
+ var isMms : Boolean = false
var addr : String = ""
var type : String = ""
var rcvDate : String = "0"
var pstDate : String = "0"
var body : String = ""
var person : String = ""
+ var mmsContents : HashMap> = hashMapOf()
+ var sender : String = ""
constructor(
addr: String,
@@ -226,13 +237,15 @@ class RecentSmsLog {
this.pstDate = pstDate
this.body = body
this.person = person
+ this.isMms = false
}
- constructor(id: String, sender: String, date: String, body: String) {
+ constructor(id: String, sender: String, date: String, body: HashMap>) {
this.id = id
this.rcvDate = date
- this.body = body
+ this.mmsContents = body
this.addr = sender
+ this.isMms = true
}
fun toJson() : String {
@@ -259,14 +272,17 @@ class TestQueryHelper(
val id = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Mms._ID))
val date = cursor.getLong(cursor.getColumnIndexOrThrow(Telephony.Mms.DATE)) * 1000
val sender : String = getSender(id) ?: throw NullPointerException("NotFound Sender For Mms")
- val body: String = getBody(id) ?: throw NullPointerException("NotFound Body by Mms")
+ val body = getBody(id) ?: throw NullPointerException("NotFound Body by Mms")
return RecentSmsLog(
id = id.toString(),
date = date.toString(),
body = body,
sender = sender
- )
+ ).apply {
+ isMms = true
+ this.sender = getContactName(_contentResolver,addr) ?: ""
+ }
}
private fun getSender(id: Int): String? {
@@ -286,7 +302,7 @@ class TestQueryHelper(
var sender = senderAddressCursor.getString(
senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.ADDRESS)
)
- BLog.LOGE("sender >> ${sender}")
+// BLog.LOGE("sender >> ${sender}")
if (isSender) {
return sender
}
@@ -296,33 +312,103 @@ class TestQueryHelper(
return null
}
- private fun getBody(id: Int): String? {
+ private fun getMmsText(id: String): String {
+ val partURI = Uri.parse("content://mms/part/$id")
+ var `is`: InputStream? = null
+ val sb = StringBuilder()
+ try {
+ `is` = _contentResolver.openInputStream(partURI)
+ if (`is` != null) {
+ val isr = InputStreamReader(`is`, "UTF-8")
+ val reader = BufferedReader(isr)
+ var temp = reader.readLine()
+ while (temp != null) {
+ sb.append(temp)
+ temp = reader.readLine()
+ BLog.LOGE("temp >>> ${temp}")
+ }
+ }
+ } catch (e: IOException) {
+ } finally {
+ if (`is` != null) {
+ try {
+ `is`.close()
+ } catch (e: IOException) {
+ }
+ }
+ }
+ BLog.LOGE("sb >>> ${sb.toString()}")
+ return sb.toString()
+ }
+ private fun getBody(id: Int): HashMap> {
+ var returns = hashMapOf>()
+ val text = arrayListOf()
+ val image = arrayListOf()
+ val audio = arrayListOf()
+
+ val projection = arrayOf("*")
+ val video = arrayListOf()
_contentResolver.query(
Uri.parse("content://mms/part"),
- null,
+ projection,
"${Telephony.Mms.Part.MSG_ID} = ?",
arrayOf(id.toString()),
null
)?.use { partsCursor ->
if (partsCursor.moveToFirst()) {
do {
+ val partId: String = partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part._ID))
val partContentType =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.CONTENT_TYPE))
- if (partContentType == "text/plain") {
- var textBody =
- partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
- .replace("\n\n", "\n").replace("\n", " ")
- if (textBody.length > 60) {
- textBody = textBody.substring(0, Math.min(textBody.length, 60)).plus(" ... ")
- }
- BLog.LOGE("textBody >>> ${textBody}")
+// BLog.LOGE("partContentType >> ${partContentType}")
- return textBody
+ if(partContentType?.contains("text") == true) {
+// BLog.LOGE("partContentType text >> ${partContentType} :: ${partId}")
+ val data =
+ partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part._DATA))
+ val textBody =
+ partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
+ if (data != null && data.length > 0) {
+ text.add(getMmsText(partId))
+ } else {
+ text.add(textBody)
+ }
}
+ else if(partContentType?.contains("image") == true) {
+// BLog.LOGE("partContentType image >> ${partContentType}:: ${partId}")
+ image.add(partId)
+ }
+ else if(partContentType?.contains("audio") == true) {
+// BLog.LOGE("partContentType audio >> ${partContentType}:: ${partId}")
+ audio.add(partId)
+ }
+ else if(partContentType?.contains("video") == true) {
+// BLog.LOGE("partContentType video >> ${partContentType}:: ${partId}")
+ video.add(partId)
+ }
+ else {
+// BLog.LOGE("partContentType >> ${partContentType}:: ${partId}")
+ }
+
+// if (partContentType == "text/plain") {
+// var textBody =
+// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
+//// .replace("\n\n", "\n").replace("\n", " ")
+//// if (textBody.length > 60) {
+//// textBody = textBody.substring(0, Math.min(textBody.length, 60)).plus(" ... ")
+//// }
+//// BLog.LOGE("textBody >>> ${textBody}")
+// return Pair(textBody , partContentType)
+// }
} while (partsCursor.moveToNext())
}
}
- return null
+ returns.put("text", text)
+ returns.put("image", image)
+ returns.put("audio", audio)
+ returns.put("video", video)
+// BLog.LOGE("returns.get(text).join => ${text.size} :: ${text.joinToString("\n")}")
+ return returns
}
fun convertData(cursor: Cursor?) {
@@ -342,4 +428,40 @@ class TestQueryHelper(
return convertData(cursor)
}
-}
\ No newline at end of file
+}
+
+fun getContactName(contentResolver: ContentResolver, phoneNumber: String?): String? {
+ val cr = contentResolver
+ val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
+ val cursor =
+ cr.query(uri, arrayOf(PhoneLookup.DISPLAY_NAME), null, null, null)
+ ?: return null
+ var contactName: String? = null
+ if (cursor.moveToFirst()) {
+ contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME))
+ }
+
+ if (cursor != null && !cursor.isClosed) {
+ cursor.close()
+ }
+
+ return contactName
+}
+
+fun getContactId(contentResolver: ContentResolver, phoneNumber: String?): String? {
+ val cr = contentResolver
+ val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
+ val cursor =
+ cr.query(uri, arrayOf(PhoneLookup._ID), null, null, null)
+ ?: return null
+ var contactName: String? = null
+ if (cursor.moveToFirst()) {
+ contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup._ID))
+ }
+
+ if (cursor != null && !cursor.isClosed) {
+ cursor.close()
+ }
+
+ return contactName
+}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/utils/PLService.kt b/app/src/main/kotlin/rasel/lunar/launcher/utils/NLService.kt
similarity index 59%
rename from app/src/main/kotlin/rasel/lunar/launcher/utils/PLService.kt
rename to app/src/main/kotlin/rasel/lunar/launcher/utils/NLService.kt
index c268491..c3e7dc9 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/utils/PLService.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/utils/NLService.kt
@@ -6,7 +6,7 @@ import android.content.Intent
import android.content.IntentFilter
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
-import android.util.Log
+import com.google.gson.Gson
class NLService : NotificationListenerService() {
@@ -17,7 +17,7 @@ class NLService : NotificationListenerService() {
super.onCreate()
nlservicereciver = NLServiceReceiver()
val filter = IntentFilter()
- filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE")
+// filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE")
registerReceiver(nlservicereciver, filter)
}
@@ -27,16 +27,16 @@ class NLService : NotificationListenerService() {
}
override fun onNotificationPosted(sbn: StatusBarNotification) {
- Log.i(TAG, "********** onNotificationPosted")
- Log.i(TAG, "ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName)
+ BLog.LOGE( "********** onNotificationPosted")
+ BLog.LOGE("ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName)
val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
i.putExtra("notification_event", "onNotificationPosted :" + sbn.packageName + "\n")
sendBroadcast(i)
}
override fun onNotificationRemoved(sbn: StatusBarNotification) {
- Log.i(TAG, "********** onNOtificationRemoved")
- Log.i(TAG, "ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName)
+ BLog.LOGE(TAG, "********** onNOtificationRemoved")
+ BLog.LOGE( "ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName)
val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
i.putExtra("notification_event", "onNotificationRemoved :" + sbn.packageName + "\n")
@@ -45,22 +45,24 @@ class NLService : NotificationListenerService() {
internal inner class NLServiceReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
+ BLog.LOGE("intent >>> ${intent.action}")
if (intent.getStringExtra("command") == "clearall") {
this@NLService.cancelAllNotifications()
} else if (intent.getStringExtra("command") == "list") {
- val i1 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
- i1.putExtra("notification_event", "=====================")
- sendBroadcast(i1)
+// val i1 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
+// i1.putExtra("notification_event", "=====================")
+// sendBroadcast(i1)
var i = 1
for (sbn in this@NLService.activeNotifications) {
- val i2 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
- i2.putExtra("notification_event", i.toString() + " " + sbn.packageName + "\n")
- sendBroadcast(i2)
- i++
+ BLog.LOGE("sbn >>> ${sbn.packageName} , ${Gson().toJson(sbn.notification.extras.keySet())}")
+// val i2 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
+// i2.putExtra("notification_event", i.toString() + " " + sbn.packageName + "\n")
+// sendBroadcast(i2)
+// i++
}
- val i3 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
- i3.putExtra("notification_event", "===== Notification List ====")
- sendBroadcast(i3)
+// val i3 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
+// i3.putExtra("notification_event", "===== Notification List ====")
+// sendBroadcast(i3)
}
}
}
diff --git a/app/src/main/res/layout/launcher_home.xml b/app/src/main/res/layout/launcher_home.xml
index ef7d041..474c2e4 100644
--- a/app/src/main/res/layout/launcher_home.xml
+++ b/app/src/main/res/layout/launcher_home.xml
@@ -5,6 +5,26 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+
+
+
+
+
+