From 75df1bf3246fc7d6276d0e1bdd4a0966f86ee8b0 Mon Sep 17 00:00:00 2001 From: lunaticbum <> Date: Tue, 27 Aug 2024 19:00:43 +0900 Subject: [PATCH] ... --- app/build.gradle.kts | 2 +- app/src/main/AndroidManifest.xml | 23 ++ .../rasel/lunar/launcher/LauncherActivity.kt | 45 ++- .../rasel/lunar/launcher/apps/ContactMenu.kt | 4 +- .../rasel/lunar/launcher/apps/SmmsMenu.kt | 42 +++ .../rasel/lunar/launcher/home/LauncherHome.kt | 269 ++++++++++++++++-- .../launcher/todos/MissedCallsAdapter.kt | 17 +- .../lunar/launcher/todos/RssItemAdapter.kt | 134 +++++++++ .../lunar/launcher/todos/RssTagAdapter.kt | 133 +++++++++ .../lunar/launcher/todos/SmsLogsAdapter.kt | 52 ++-- .../rasel/lunar/launcher/utils/DataManager.kt | 166 +++++++++-- .../utils/{PLService.kt => NLService.kt} | 34 +-- app/src/main/res/layout/launcher_home.xml | 24 ++ 13 files changed, 860 insertions(+), 85 deletions(-) create mode 100644 app/src/main/kotlin/rasel/lunar/launcher/apps/SmmsMenu.kt create mode 100644 app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt create mode 100644 app/src/main/kotlin/rasel/lunar/launcher/todos/RssTagAdapter.kt rename app/src/main/kotlin/rasel/lunar/launcher/utils/{PLService.kt => NLService.kt} (59%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 86a0f39d..66bf715c 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 e712a516..df1ca47f 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 a21bf1e5..16dd64a0 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 f6323976..4375cf00 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 00000000..fc97fc9b --- /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 f4c09aff..f413aba1 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 ad100721..f1f3f466 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 00000000..bf32211c --- /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 00000000..b4b2176f --- /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 d33df81b..856052b1 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 6cac3a10..c031eeaf 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 c268491c..c3e7dc9f 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 ef7d0418..474c2e4d 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"> + + + + + + +