From f5de522967f070c813902480741808d98ca6e775 Mon Sep 17 00:00:00 2001
From: pppscn <35696959@qq.com>
Date: Tue, 9 May 2023 09:43:26 +0800
Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=EF=BC=9Acode=20review=20&=20?=
=?UTF-8?q?=E7=B2=BE=E7=AE=80=E6=97=A0=E7=94=A8=E8=B5=84=E6=BA=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/build.gradle | 2 +-
.../sms/forwarder/ExampleInstrumentedTest.kt | 39 -
app/src/main/assets/tips.json | 34 +-
.../main/java/com/idormy/sms/forwarder/App.kt | 1 -
.../sms/forwarder/activity/MainActivity.kt | 1 -
.../forwarder/adapter/LogsPagingAdapter.kt | 1 +
.../adapter/base/delegate/XDelegateAdapter.kt | 6 +-
.../adapter/spinner/AppListAdapterItem.kt | 85 +-
.../adapter/spinner/AppListSpinnerAdapter.kt | 313 +++--
.../adapter/spinner/SenderSpinnerAdapter.kt | 333 +++--
.../com/idormy/sms/forwarder/core/Core.kt | 1 +
.../core/webview/XPageWebViewFragment.kt | 1190 ++++++++---------
.../sms/forwarder/database/dao/RuleDao.kt | 8 +-
.../sms/forwarder/database/entity/Logs.kt | 14 +-
.../sms/forwarder/database/entity/Sender.kt | 23 -
.../database/repository/FrpcRepository.kt | 70 +-
.../database/repository/LogsRepository.kt | 8 +-
.../database/repository/RuleRepository.kt | 4 +-
.../database/repository/SenderRepository.kt | 2 +-
.../sms/forwarder/fragment/ClientFragment.kt | 2 +-
.../forwarder/fragment/FrpcEditFragment.kt | 2 +-
.../sms/forwarder/fragment/FrpcFragment.kt | 1 -
.../sms/forwarder/fragment/LogcatFragment.kt | 215 ++-
.../sms/forwarder/fragment/ServerFragment.kt | 2 -
.../fragment/client/CloneFragment.kt | 1 -
.../fragment/client/ContactQueryFragment.kt | 1 -
.../fragment/client/SmsQueryFragment.kt | 1 -
.../sms/forwarder/receiver/SmsReceiver.kt | 2 +-
.../server/component/AppMessageConverter.kt | 1 -
.../server/controller/LocationController.kt | 2 +-
.../sms/forwarder/service/BatteryService.kt | 2 +-
.../forwarder/service/NetworkStateService.kt | 2 +-
.../idormy/sms/forwarder/utils/CertUtils.kt | 53 -
.../sms/forwarder/utils/DataProvider.kt | 145 +-
.../sms/forwarder/utils/HistoryUtils.kt | 2 +-
.../com/idormy/sms/forwarder/utils/Logger.kt | 56 -
.../idormy/sms/forwarder/utils/NetUtils.kt | 74 -
.../idormy/sms/forwarder/utils/PrefsHelper.kt | 67 -
.../sms/forwarder/utils/SettingUtils.kt | 2 +-
.../sms/forwarder/utils/sdkinit/UMengInit.kt | 3 -
.../sms/forwarder/utils/sender/BarkUtils.kt | 1 -
.../utils/sender/DingtalkGroupRobotUtils.kt | 1 -
.../utils/sender/DingtalkInnerRobotUtils.kt | 1 -
.../sms/forwarder/utils/sender/EmailUtils.kt | 3 +-
.../forwarder/utils/sender/FeishuAppUtils.kt | 1 -
.../sms/forwarder/utils/sender/FeishuUtils.kt | 1 -
.../sms/forwarder/utils/sender/GotifyUtils.kt | 1 -
.../forwarder/utils/sender/PushplusUtils.kt | 2 -
.../forwarder/utils/sender/ServerchanUtils.kt | 1 -
.../sms/forwarder/utils/sender/SmsUtils.kt | 1 -
.../sms/forwarder/utils/sender/SocketUtils.kt | 1 -
.../forwarder/utils/sender/TelegramUtils.kt | 2 -
.../forwarder/utils/sender/UrlSchemeUtils.kt | 2 -
.../forwarder/utils/sender/WebhookUtils.kt | 5 +-
.../utils/sender/WeworkAgentUtils.kt | 1 -
.../utils/service/JsonSerializationService.kt | 42 -
.../utils/tinker/ShareReflectUtil.kt | 478 +++----
.../sms/forwarder/widget/GuideTipsDialog.kt | 2 +-
.../forwarder/workers/LoadAppListWorker.kt | 2 +-
.../drawable-v24/ic_launcher_foreground.xml | 34 -
.../res/drawable/ic_launcher_background.xml | 170 ---
.../res/drawable/ic_launcher_foreground.xml | 13 -
app/src/main/res/drawable/ic_login_close.xml | 9 -
app/src/main/res/drawable/ic_password.xml | 18 -
app/src/main/res/drawable/ic_phone.xml | 9 -
.../idormy/sms/forwarder/ExampleUnitTest.kt | 46 -
66 files changed, 1458 insertions(+), 2160 deletions(-)
delete mode 100644 app/src/androidTest/java/com/idormy/sms/forwarder/ExampleInstrumentedTest.kt
delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/utils/CertUtils.kt
delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/utils/Logger.kt
delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/utils/NetUtils.kt
delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/utils/PrefsHelper.kt
delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/utils/service/JsonSerializationService.kt
delete mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml
delete mode 100644 app/src/main/res/drawable/ic_launcher_background.xml
delete mode 100644 app/src/main/res/drawable/ic_launcher_foreground.xml
delete mode 100644 app/src/main/res/drawable/ic_login_close.xml
delete mode 100644 app/src/main/res/drawable/ic_password.xml
delete mode 100644 app/src/main/res/drawable/ic_phone.xml
delete mode 100644 app/src/test/java/com/idormy/sms/forwarder/ExampleUnitTest.kt
diff --git a/app/build.gradle b/app/build.gradle
index 34889d2e..116370f4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -249,7 +249,7 @@ dependencies {
//MarkdownView:https://github.com/tiagohm/MarkdownView
implementation 'com.github.tiagohm.MarkdownView:library:0.19.0'
- implementation 'com.github.tiagohm.MarkdownView:emoji:0.19.0'
+ //implementation 'com.github.tiagohm.MarkdownView:emoji:0.19.0'
def retrofit2_version = '2.9.0'
implementation "com.squareup.retrofit2:retrofit:$retrofit2_version"
diff --git a/app/src/androidTest/java/com/idormy/sms/forwarder/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/idormy/sms/forwarder/ExampleInstrumentedTest.kt
deleted file mode 100644
index 02b5e3a6..00000000
--- a/app/src/androidTest/java/com/idormy/sms/forwarder/ExampleInstrumentedTest.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.idormy.sms.forwarder
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.platform.app.InstrumentationRegistry
-import org.junit.Assert
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * @see [Testing documentation](http://d.android.com/tools/testing)
- */
-@RunWith(AndroidJUnit4::class)
-class ExampleInstrumentedTest {
- @Test
- fun useAppContext() {
- // Context of the app under test.
- val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- Assert.assertEquals("com.idormy.sms.forwarder", appContext.packageName)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/assets/tips.json b/app/src/main/assets/tips.json
index 5a77023d..f0a67e6e 100644
--- a/app/src/main/assets/tips.json
+++ b/app/src/main/assets/tips.json
@@ -1,17 +1,17 @@
-{
- "Code": 0,
- "Data": [
- {
- "title": "新用户必读",
- "content": "开始设置之前,请您认真地看一遍 Wiki !
\n遇到问题,请按照 常见问题 章节进行排查!
\n没找到答案的,再加入QQ互助交流群里提问,请清楚地描述问题,并给出对应的配置截图与相关日志,方便大家直观的判断问题! "
- },
- {
- "title": "QQ互助交流群",
- "content": "QQ互助交流①群
QQ互助交流②群
QQ互助交流③群
QQ互助交流④群
QQ互助交流⑤群"
- },
- {
- "title": "打赏名单",
- "content": "感谢热心网友们对开源项目的喜爱和支持!查看赞助名单!"
- }
- ]
-}
+{
+ "Code": 0,
+ "Data": [
+ {
+ "title": "新用户必读",
+ "content": "开始设置之前,请您认真地看一遍 Wiki !
\n遇到问题,请按照 常见问题 章节进行排查!
\n没找到答案的,再加入QQ互助交流群里提问,请清楚地描述问题,并给出对应的配置截图与相关日志,方便大家直观的判断问题! "
+ },
+ {
+ "title": "互助交流群",
+ "content": "QQ互助交流①群
QQ互助交流②群
QQ互助交流③群
QQ互助交流④群
QQ互助交流⑤群"
+ },
+ {
+ "title": "打赏名单",
+ "content": "感谢热心网友们对开源项目的喜爱和支持!查看赞助名单!"
+ }
+ ]
+}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/App.kt b/app/src/main/java/com/idormy/sms/forwarder/App.kt
index eeb84289..43532b0d 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/App.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/App.kt
@@ -40,7 +40,6 @@ import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
-@Suppress("PrivatePropertyName")
class App : Application(), CactusCallback, Configuration.Provider by Core {
val applicationScope = CoroutineScope(SupervisorJob())
diff --git a/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt b/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt
index 6f148688..d92adfe6 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt
@@ -59,7 +59,6 @@ import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File
-
@Suppress("DEPRECATION", "PrivatePropertyName")
class MainActivity : BaseActivity(),
View.OnClickListener,
diff --git a/app/src/main/java/com/idormy/sms/forwarder/adapter/LogsPagingAdapter.kt b/app/src/main/java/com/idormy/sms/forwarder/adapter/LogsPagingAdapter.kt
index e8c1c78a..4e448663 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/adapter/LogsPagingAdapter.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/adapter/LogsPagingAdapter.kt
@@ -12,6 +12,7 @@ import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
import com.idormy.sms.forwarder.databinding.AdapterLogsCardViewListItemBinding
import com.xuexiang.xutil.data.DateUtils
+@Suppress("unused")
class LogsPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter(diffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/adapter/base/delegate/XDelegateAdapter.kt b/app/src/main/java/com/idormy/sms/forwarder/adapter/base/delegate/XDelegateAdapter.kt
index 1b4dfaba..fd726850 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/adapter/base/delegate/XDelegateAdapter.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/adapter/base/delegate/XDelegateAdapter.kt
@@ -36,7 +36,7 @@ abstract class XDelegateAdapter : DelegateAdapt
}
constructor(data: Array?) {
- if (data != null && data.isNotEmpty()) {
+ if (!data.isNullOrEmpty()) {
mData.addAll(listOf(*data))
}
}
@@ -180,7 +180,7 @@ abstract class XDelegateAdapter : DelegateAdapt
*/
@SuppressLint("NotifyDataSetChanged")
fun refresh(array: Array?): XDelegateAdapter<*, *> {
- if (array != null && array.isNotEmpty()) {
+ if (!array.isNullOrEmpty()) {
mData.clear()
mData.addAll(listOf(*array))
selectPosition = -1
@@ -212,7 +212,7 @@ abstract class XDelegateAdapter : DelegateAdapt
*/
@SuppressLint("NotifyDataSetChanged")
fun loadMore(array: Array?): XDelegateAdapter<*, *> {
- if (array != null && array.isNotEmpty()) {
+ if (!array.isNullOrEmpty()) {
mData.addAll(listOf(*array))
notifyDataSetChanged()
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListAdapterItem.kt b/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListAdapterItem.kt
index eddfba29..63a21a18 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListAdapterItem.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListAdapterItem.kt
@@ -1,45 +1,40 @@
-package com.idormy.sms.forwarder.adapter.spinner
-
-import android.graphics.drawable.Drawable
-import com.xuexiang.xui.utils.ResUtils
-
-@Suppress("unused")
-class AppListAdapterItem {
-
- var name: String = ""
- var icon: Drawable? = null
- var packageName: String? = null
- //var packagePath: String? = null
- //var versionName: String? = null
- //var versionCode: Int = 0
- //var isSystem: Boolean = false
-
-
- constructor(name: String, icon: Drawable?, packageName: String?) {
- this.name = name
- this.icon = icon
- this.packageName = packageName
- }
-
- constructor(name: String) : this(name, null, null)
- constructor(name: String, drawableId: Int, packageName: String) : this(name, ResUtils.getDrawable(drawableId), packageName)
-
- //注意:自定义实体需要重写对象的toString方法
- override fun toString(): String {
- return name
- }
-
- companion object {
- fun of(name: String): AppListAdapterItem {
- return AppListAdapterItem(name)
- }
-
- fun arrayof(title: Array): Array {
- val array = arrayOfNulls(title.size)
- for (i in array.indices) {
- array[i] = AppListAdapterItem(title[i])
- }
- return array
- }
- }
-}
+package com.idormy.sms.forwarder.adapter.spinner
+
+import android.graphics.drawable.Drawable
+import com.xuexiang.xui.utils.ResUtils
+
+@Suppress("unused")
+class AppListAdapterItem {
+
+ var name: String = ""
+ var icon: Drawable? = null
+ var packageName: String? = null
+
+ constructor(name: String, icon: Drawable?, packageName: String?) {
+ this.name = name
+ this.icon = icon
+ this.packageName = packageName
+ }
+
+ constructor(name: String) : this(name, null, null)
+ constructor(name: String, drawableId: Int, packageName: String) : this(name, ResUtils.getDrawable(drawableId), packageName)
+
+ //注意:自定义实体需要重写对象的toString方法
+ override fun toString(): String {
+ return name
+ }
+
+ companion object {
+ fun of(name: String): AppListAdapterItem {
+ return AppListAdapterItem(name)
+ }
+
+ fun arrayof(title: Array): Array {
+ val array = arrayOfNulls(title.size)
+ for (i in array.indices) {
+ array[i] = AppListAdapterItem(title[i])
+ }
+ return array
+ }
+ }
+}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListSpinnerAdapter.kt b/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListSpinnerAdapter.kt
index f3daca6b..e632c9c4 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListSpinnerAdapter.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/AppListSpinnerAdapter.kt
@@ -1,157 +1,156 @@
-package com.idormy.sms.forwarder.adapter.spinner
-
-import android.annotation.SuppressLint
-import android.os.Build
-import android.text.Html
-import android.text.TextUtils
-import android.util.Log
-import android.util.TypedValue
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.annotation.ColorInt
-import androidx.annotation.DrawableRes
-import com.idormy.sms.forwarder.R
-import com.xuexiang.xui.utils.CollectionUtils
-import com.xuexiang.xui.widget.spinner.editspinner.BaseEditSpinnerAdapter
-import com.xuexiang.xui.widget.spinner.editspinner.EditSpinnerFilter
-
-@Suppress("unused", "NAME_SHADOWING", "SENSELESS_COMPARISON", "DEPRECATION")
-class AppListSpinnerAdapter : BaseEditSpinnerAdapter, EditSpinnerFilter {
- /**
- * 选项的文字颜色
- */
- private var mTextColor = 0
-
- /**
- * 选项的文字大小
- */
- private var mTextSize = 0f
-
- /**
- * 背景颜色
- */
- private var mBackgroundSelector = 0
-
- /**
- * 过滤关键词的选中颜色
- */
- private var mFilterColor = "#F15C58"
- private var mIsFilterKey = false
-
- /**
- * 构造方法
- *
- * @param data 选项数据
- */
- constructor(data: List?) : super(data)
-
- /**
- * 构造方法
- *
- * @param data 选项数据
- */
- constructor(data: Array?) : super(data)
-
- override fun getEditSpinnerFilter(): EditSpinnerFilter {
- return this
- }
-
- override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
- var convertView = convertView
- val holder: ViewHolder
- if (convertView == null) {
- convertView = LayoutInflater.from(parent.context).inflate(R.layout.item_spinner_with_icon, parent, false)
- holder = ViewHolder(convertView, mTextColor, mTextSize, mBackgroundSelector)
- convertView.tag = holder
- } else {
- holder = convertView.tag as ViewHolder
- }
- val item = CollectionUtils.getListItem(mDataSource, mIndexs[position]) as AppListAdapterItem
- holder.iconView.setImageDrawable(item.icon)
- //holder.titleView.text = Html.fromHtml(item.toString())
- holder.titleView.text = Html.fromHtml(getItem(position))
- return convertView
- }
-
- override fun onFilter(keyword: String): Boolean {
- mDisplayData.clear()
- Log.d("AppListSpinnerAdapter", "keyword = $keyword")
- Log.d("AppListSpinnerAdapter", "mIndexs.indices = ${mIndexs.indices}")
- if (TextUtils.isEmpty(keyword)) {
- initDisplayData(mDataSource)
- for (i in mIndexs.indices) {
- mIndexs[i] = i
- }
- } else {
- try {
- for (i in mDataSource.indices) {
- if (getDataSourceString(i).contains(keyword, ignoreCase = true)) {
- mIndexs[mDisplayData.size] = i
- if (mIsFilterKey) {
- mDisplayData.add(getDataSourceString(i).replaceFirst(keyword.toRegex(), "$keyword"))
- } else {
- mDisplayData.add(getDataSourceString(i))
- }
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- Log.d("AppListSpinnerAdapter", "mDisplayData = $mDisplayData")
- notifyDataSetChanged()
- return mDisplayData.size > 0
- }
-
- fun setTextColor(@ColorInt textColor: Int): AppListSpinnerAdapter<*> {
- mTextColor = textColor
- return this
- }
-
- fun setTextSize(textSize: Float): AppListSpinnerAdapter<*> {
- mTextSize = textSize
- return this
- }
-
- fun setBackgroundSelector(@DrawableRes backgroundSelector: Int): AppListSpinnerAdapter<*> {
- mBackgroundSelector = backgroundSelector
- return this
- }
-
- fun setFilterColor(filterColor: String): AppListSpinnerAdapter<*> {
- mFilterColor = filterColor
- return this
- }
-
- fun setIsFilterKey(isFilterKey: Boolean): AppListSpinnerAdapter<*> {
- mIsFilterKey = isFilterKey
- return this
- }
-
- @Suppress("DEPRECATION")
- @SuppressLint("ObsoleteSdkInt")
- private class ViewHolder(convertView: View, @ColorInt textColor: Int, textSize: Float, @DrawableRes backgroundSelector: Int) {
- val iconView: ImageView = convertView.findViewById(R.id.iv_icon)
- val statusView: ImageView = convertView.findViewById(R.id.iv_status)
- val titleView: TextView = convertView.findViewById(R.id.tv_title)
-
- init {
- if (textColor > 0) titleView.setTextColor(textColor)
- if (textSize > 0F) titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
- if (backgroundSelector != 0) titleView.setBackgroundResource(backgroundSelector)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- val config = convertView.resources.configuration
- if (config.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
- titleView.textDirection = View.TEXT_DIRECTION_RTL
- }
- }
- }
- }
-
- fun getItemSource(position: Int): T {
- return mDataSource[mIndexs[position]]
- }
-}
+package com.idormy.sms.forwarder.adapter.spinner
+
+import android.annotation.SuppressLint
+import android.os.Build
+import android.text.Html
+import android.text.TextUtils
+import android.util.Log
+import android.util.TypedValue
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.ColorInt
+import androidx.annotation.DrawableRes
+import com.idormy.sms.forwarder.R
+import com.xuexiang.xui.utils.CollectionUtils
+import com.xuexiang.xui.widget.spinner.editspinner.BaseEditSpinnerAdapter
+import com.xuexiang.xui.widget.spinner.editspinner.EditSpinnerFilter
+
+@Suppress("unused", "NAME_SHADOWING", "DEPRECATION")
+class AppListSpinnerAdapter : BaseEditSpinnerAdapter, EditSpinnerFilter {
+ /**
+ * 选项的文字颜色
+ */
+ private var mTextColor = 0
+
+ /**
+ * 选项的文字大小
+ */
+ private var mTextSize = 0f
+
+ /**
+ * 背景颜色
+ */
+ private var mBackgroundSelector = 0
+
+ /**
+ * 过滤关键词的选中颜色
+ */
+ private var mFilterColor = "#F15C58"
+ private var mIsFilterKey = false
+
+ /**
+ * 构造方法
+ *
+ * @param data 选项数据
+ */
+ constructor(data: List?) : super(data)
+
+ /**
+ * 构造方法
+ *
+ * @param data 选项数据
+ */
+ constructor(data: Array?) : super(data)
+
+ override fun getEditSpinnerFilter(): EditSpinnerFilter {
+ return this
+ }
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
+ var convertView = convertView
+ val holder: ViewHolder
+ if (convertView == null) {
+ convertView = LayoutInflater.from(parent.context).inflate(R.layout.item_spinner_with_icon, parent, false)
+ holder = ViewHolder(convertView, mTextColor, mTextSize, mBackgroundSelector)
+ convertView.tag = holder
+ } else {
+ holder = convertView.tag as ViewHolder
+ }
+ val item = CollectionUtils.getListItem(mDataSource, mIndexs[position]) as AppListAdapterItem
+ holder.iconView.setImageDrawable(item.icon)
+ //holder.titleView.text = Html.fromHtml(item.toString())
+ holder.titleView.text = Html.fromHtml(getItem(position))
+ return convertView
+ }
+
+ override fun onFilter(keyword: String): Boolean {
+ mDisplayData.clear()
+ Log.d("AppListSpinnerAdapter", "keyword = $keyword")
+ Log.d("AppListSpinnerAdapter", "mIndexs.indices = ${mIndexs.indices}")
+ if (TextUtils.isEmpty(keyword)) {
+ initDisplayData(mDataSource)
+ for (i in mIndexs.indices) {
+ mIndexs[i] = i
+ }
+ } else {
+ try {
+ for (i in mDataSource.indices) {
+ if (getDataSourceString(i).contains(keyword, ignoreCase = true)) {
+ mIndexs[mDisplayData.size] = i
+ if (mIsFilterKey) {
+ mDisplayData.add(getDataSourceString(i).replaceFirst(keyword.toRegex(), "$keyword"))
+ } else {
+ mDisplayData.add(getDataSourceString(i))
+ }
+ }
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ Log.d("AppListSpinnerAdapter", "mDisplayData = $mDisplayData")
+ notifyDataSetChanged()
+ return mDisplayData.size > 0
+ }
+
+ fun setTextColor(@ColorInt textColor: Int): AppListSpinnerAdapter<*> {
+ mTextColor = textColor
+ return this
+ }
+
+ fun setTextSize(textSize: Float): AppListSpinnerAdapter<*> {
+ mTextSize = textSize
+ return this
+ }
+
+ fun setBackgroundSelector(@DrawableRes backgroundSelector: Int): AppListSpinnerAdapter<*> {
+ mBackgroundSelector = backgroundSelector
+ return this
+ }
+
+ fun setFilterColor(filterColor: String): AppListSpinnerAdapter<*> {
+ mFilterColor = filterColor
+ return this
+ }
+
+ fun setIsFilterKey(isFilterKey: Boolean): AppListSpinnerAdapter<*> {
+ mIsFilterKey = isFilterKey
+ return this
+ }
+
+ @SuppressLint("ObsoleteSdkInt")
+ private class ViewHolder(convertView: View, @ColorInt textColor: Int, textSize: Float, @DrawableRes backgroundSelector: Int) {
+ val iconView: ImageView = convertView.findViewById(R.id.iv_icon)
+ val statusView: ImageView = convertView.findViewById(R.id.iv_status)
+ val titleView: TextView = convertView.findViewById(R.id.tv_title)
+
+ init {
+ if (textColor > 0) titleView.setTextColor(textColor)
+ if (textSize > 0F) titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
+ if (backgroundSelector != 0) titleView.setBackgroundResource(backgroundSelector)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ val config = convertView.resources.configuration
+ if (config.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
+ titleView.textDirection = View.TEXT_DIRECTION_RTL
+ }
+ }
+ }
+ }
+
+ fun getItemSource(position: Int): T {
+ return mDataSource[mIndexs[position]]
+ }
+}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/SenderSpinnerAdapter.kt b/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/SenderSpinnerAdapter.kt
index 2f1477f7..8769118d 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/SenderSpinnerAdapter.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/adapter/spinner/SenderSpinnerAdapter.kt
@@ -1,167 +1,166 @@
-package com.idormy.sms.forwarder.adapter.spinner
-
-import android.annotation.SuppressLint
-import android.os.Build
-import android.text.Html
-import android.text.TextUtils
-import android.util.Log
-import android.util.TypedValue
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.annotation.ColorInt
-import androidx.annotation.DrawableRes
-import com.idormy.sms.forwarder.R
-import com.idormy.sms.forwarder.utils.STATUS_OFF
-import com.xuexiang.xui.utils.CollectionUtils
-import com.xuexiang.xui.utils.ResUtils
-import com.xuexiang.xui.widget.spinner.editspinner.BaseEditSpinnerAdapter
-import com.xuexiang.xui.widget.spinner.editspinner.EditSpinnerFilter
-
-@Suppress("unused", "NAME_SHADOWING", "SENSELESS_COMPARISON", "DEPRECATION")
-class SenderSpinnerAdapter : BaseEditSpinnerAdapter, EditSpinnerFilter {
- /**
- * 选项的文字颜色
- */
- private var mTextColor = 0
-
- /**
- * 选项的文字大小
- */
- private var mTextSize = 0f
-
- /**
- * 背景颜色
- */
- private var mBackgroundSelector = 0
-
- /**
- * 过滤关键词的选中颜色
- */
- private var mFilterColor = "#F15C58"
- private var mIsFilterKey = false
-
- /**
- * 构造方法
- *
- * @param data 选项数据
- */
- constructor(data: List?) : super(data)
-
- /**
- * 构造方法
- *
- * @param data 选项数据
- */
- constructor(data: Array?) : super(data)
-
- override fun getEditSpinnerFilter(): EditSpinnerFilter {
- return this
- }
-
- override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
- var convertView = convertView
- val holder: ViewHolder
- if (convertView == null) {
- convertView = LayoutInflater.from(parent.context).inflate(R.layout.item_spinner_with_icon, parent, false)
- holder = ViewHolder(convertView, mTextColor, mTextSize, mBackgroundSelector)
- convertView.tag = holder
- } else {
- holder = convertView.tag as ViewHolder
- }
- val item = CollectionUtils.getListItem(mDataSource, mIndexs[position]) as SenderAdapterItem
- holder.iconView.setImageDrawable(item.icon)
- holder.statusView.setImageDrawable(
- ResUtils.getDrawable(
- when (item.status) {
- STATUS_OFF -> R.drawable.icon_off
- else -> R.drawable.icon_on
- }
- )
- )
- //holder.titleView.text = Html.fromHtml(item.toString())
- holder.titleView.text = Html.fromHtml(getItem(position))
- return convertView
- }
-
- override fun onFilter(keyword: String): Boolean {
- mDisplayData.clear()
- Log.d("SenderSpinnerAdapter", "keyword = $keyword")
- Log.d("SenderSpinnerAdapter", "mIndexs.indices = ${mIndexs.indices}")
- if (TextUtils.isEmpty(keyword)) {
- initDisplayData(mDataSource)
- for (i in mIndexs.indices) {
- mIndexs[i] = i
- }
- } else {
- try {
- for (i in mDataSource.indices) {
- if (getDataSourceString(i).contains(keyword, ignoreCase = true)) {
- mIndexs[mDisplayData.size] = i
- if (mIsFilterKey) {
- mDisplayData.add(getDataSourceString(i).replaceFirst(keyword.toRegex(), "$keyword"))
- } else {
- mDisplayData.add(getDataSourceString(i))
- }
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- Log.d("SenderSpinnerAdapter", "mDisplayData = $mDisplayData")
- notifyDataSetChanged()
- return mDisplayData.size > 0
- }
-
- fun setTextColor(@ColorInt textColor: Int): SenderSpinnerAdapter<*> {
- mTextColor = textColor
- return this
- }
-
- fun setTextSize(textSize: Float): SenderSpinnerAdapter<*> {
- mTextSize = textSize
- return this
- }
-
- fun setBackgroundSelector(@DrawableRes backgroundSelector: Int): SenderSpinnerAdapter<*> {
- mBackgroundSelector = backgroundSelector
- return this
- }
-
- fun setFilterColor(filterColor: String): SenderSpinnerAdapter<*> {
- mFilterColor = filterColor
- return this
- }
-
- fun setIsFilterKey(isFilterKey: Boolean): SenderSpinnerAdapter<*> {
- mIsFilterKey = isFilterKey
- return this
- }
-
- @Suppress("DEPRECATION")
- @SuppressLint("ObsoleteSdkInt")
- private class ViewHolder(convertView: View, @ColorInt textColor: Int, textSize: Float, @DrawableRes backgroundSelector: Int) {
- val iconView: ImageView = convertView.findViewById(R.id.iv_icon)
- val statusView: ImageView = convertView.findViewById(R.id.iv_status)
- val titleView: TextView = convertView.findViewById(R.id.tv_title)
-
- init {
- if (textColor > 0) titleView.setTextColor(textColor)
- if (textSize > 0F) titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
- if (backgroundSelector != 0) titleView.setBackgroundResource(backgroundSelector)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- val config = convertView.resources.configuration
- if (config.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
- titleView.textDirection = View.TEXT_DIRECTION_RTL
- }
- }
- }
- }
-
- fun getItemSource(position: Int): T {
- return mDataSource[mIndexs[position]]
- }
-}
+package com.idormy.sms.forwarder.adapter.spinner
+
+import android.annotation.SuppressLint
+import android.os.Build
+import android.text.Html
+import android.text.TextUtils
+import android.util.Log
+import android.util.TypedValue
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.ColorInt
+import androidx.annotation.DrawableRes
+import com.idormy.sms.forwarder.R
+import com.idormy.sms.forwarder.utils.STATUS_OFF
+import com.xuexiang.xui.utils.CollectionUtils
+import com.xuexiang.xui.utils.ResUtils
+import com.xuexiang.xui.widget.spinner.editspinner.BaseEditSpinnerAdapter
+import com.xuexiang.xui.widget.spinner.editspinner.EditSpinnerFilter
+
+@Suppress("unused", "NAME_SHADOWING", "DEPRECATION")
+class SenderSpinnerAdapter : BaseEditSpinnerAdapter, EditSpinnerFilter {
+ /**
+ * 选项的文字颜色
+ */
+ private var mTextColor = 0
+
+ /**
+ * 选项的文字大小
+ */
+ private var mTextSize = 0f
+
+ /**
+ * 背景颜色
+ */
+ private var mBackgroundSelector = 0
+
+ /**
+ * 过滤关键词的选中颜色
+ */
+ private var mFilterColor = "#F15C58"
+ private var mIsFilterKey = false
+
+ /**
+ * 构造方法
+ *
+ * @param data 选项数据
+ */
+ constructor(data: List?) : super(data)
+
+ /**
+ * 构造方法
+ *
+ * @param data 选项数据
+ */
+ constructor(data: Array?) : super(data)
+
+ override fun getEditSpinnerFilter(): EditSpinnerFilter {
+ return this
+ }
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
+ var convertView = convertView
+ val holder: ViewHolder
+ if (convertView == null) {
+ convertView = LayoutInflater.from(parent.context).inflate(R.layout.item_spinner_with_icon, parent, false)
+ holder = ViewHolder(convertView, mTextColor, mTextSize, mBackgroundSelector)
+ convertView.tag = holder
+ } else {
+ holder = convertView.tag as ViewHolder
+ }
+ val item = CollectionUtils.getListItem(mDataSource, mIndexs[position]) as SenderAdapterItem
+ holder.iconView.setImageDrawable(item.icon)
+ holder.statusView.setImageDrawable(
+ ResUtils.getDrawable(
+ when (item.status) {
+ STATUS_OFF -> R.drawable.icon_off
+ else -> R.drawable.icon_on
+ }
+ )
+ )
+ //holder.titleView.text = Html.fromHtml(item.toString())
+ holder.titleView.text = Html.fromHtml(getItem(position))
+ return convertView
+ }
+
+ override fun onFilter(keyword: String): Boolean {
+ mDisplayData.clear()
+ Log.d("SenderSpinnerAdapter", "keyword = $keyword")
+ Log.d("SenderSpinnerAdapter", "mIndexs.indices = ${mIndexs.indices}")
+ if (TextUtils.isEmpty(keyword)) {
+ initDisplayData(mDataSource)
+ for (i in mIndexs.indices) {
+ mIndexs[i] = i
+ }
+ } else {
+ try {
+ for (i in mDataSource.indices) {
+ if (getDataSourceString(i).contains(keyword, ignoreCase = true)) {
+ mIndexs[mDisplayData.size] = i
+ if (mIsFilterKey) {
+ mDisplayData.add(getDataSourceString(i).replaceFirst(keyword.toRegex(), "$keyword"))
+ } else {
+ mDisplayData.add(getDataSourceString(i))
+ }
+ }
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ Log.d("SenderSpinnerAdapter", "mDisplayData = $mDisplayData")
+ notifyDataSetChanged()
+ return mDisplayData.size > 0
+ }
+
+ fun setTextColor(@ColorInt textColor: Int): SenderSpinnerAdapter<*> {
+ mTextColor = textColor
+ return this
+ }
+
+ fun setTextSize(textSize: Float): SenderSpinnerAdapter<*> {
+ mTextSize = textSize
+ return this
+ }
+
+ fun setBackgroundSelector(@DrawableRes backgroundSelector: Int): SenderSpinnerAdapter<*> {
+ mBackgroundSelector = backgroundSelector
+ return this
+ }
+
+ fun setFilterColor(filterColor: String): SenderSpinnerAdapter<*> {
+ mFilterColor = filterColor
+ return this
+ }
+
+ fun setIsFilterKey(isFilterKey: Boolean): SenderSpinnerAdapter<*> {
+ mIsFilterKey = isFilterKey
+ return this
+ }
+
+ @SuppressLint("ObsoleteSdkInt")
+ private class ViewHolder(convertView: View, @ColorInt textColor: Int, textSize: Float, @DrawableRes backgroundSelector: Int) {
+ val iconView: ImageView = convertView.findViewById(R.id.iv_icon)
+ val statusView: ImageView = convertView.findViewById(R.id.iv_status)
+ val titleView: TextView = convertView.findViewById(R.id.tv_title)
+
+ init {
+ if (textColor > 0) titleView.setTextColor(textColor)
+ if (textSize > 0F) titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
+ if (backgroundSelector != 0) titleView.setBackgroundResource(backgroundSelector)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ val config = convertView.resources.configuration
+ if (config.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
+ titleView.textDirection = View.TEXT_DIRECTION_RTL
+ }
+ }
+ }
+ }
+
+ fun getItemSource(position: Int): T {
+ return mDataSource[mIndexs[position]]
+ }
+}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt b/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt
index 244717c4..5d858e72 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt
@@ -11,6 +11,7 @@ import com.idormy.sms.forwarder.database.repository.*
import com.idormy.sms.forwarder.service.ForegroundService
import kotlinx.coroutines.launch
+@Suppress("unused")
object Core : Configuration.Provider {
lateinit var app: Application
val frpc: FrpcRepository by lazy { (app as App).frpcRepository }
diff --git a/app/src/main/java/com/idormy/sms/forwarder/core/webview/XPageWebViewFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/core/webview/XPageWebViewFragment.kt
index 86fd4495..1c0bcde6 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/core/webview/XPageWebViewFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/core/webview/XPageWebViewFragment.kt
@@ -1,596 +1,596 @@
-package com.idormy.sms.forwarder.core.webview
-
-import android.content.ClipData
-import android.content.ClipboardManager
-import android.content.Context
-import android.content.Intent
-import android.graphics.Bitmap
-import android.graphics.Color
-import android.net.Uri
-import android.os.Build
-import android.text.TextUtils
-import android.view.*
-import android.webkit.*
-import android.widget.FrameLayout
-import android.widget.LinearLayout
-import android.widget.TextView
-import androidx.annotation.RequiresApi
-import androidx.appcompat.widget.PopupMenu
-import androidx.fragment.app.Fragment
-import com.idormy.sms.forwarder.R
-import com.idormy.sms.forwarder.core.BaseFragment
-import com.idormy.sms.forwarder.databinding.FragmentAgentwebBinding
-import com.idormy.sms.forwarder.utils.XToastUtils
-import com.just.agentweb.action.PermissionInterceptor
-import com.just.agentweb.core.AgentWeb
-import com.just.agentweb.core.client.DefaultWebClient
-import com.just.agentweb.core.client.MiddlewareWebChromeBase
-import com.just.agentweb.core.client.MiddlewareWebClientBase
-import com.just.agentweb.core.client.WebListenerManager
-import com.just.agentweb.core.web.AbsAgentWebSettings
-import com.just.agentweb.core.web.AgentWebConfig
-import com.just.agentweb.core.web.IAgentWebSettings
-import com.just.agentweb.download.AgentWebDownloader.Extra
-import com.just.agentweb.download.DefaultDownloadImpl
-import com.just.agentweb.download.DownloadListenerAdapter
-import com.just.agentweb.download.DownloadingService
-import com.just.agentweb.widget.IWebLayout
-import com.xuexiang.xaop.annotation.SingleClick
-import com.xuexiang.xpage.annotation.Page
-import com.xuexiang.xpage.base.XPageActivity
-import com.xuexiang.xpage.base.XPageFragment
-import com.xuexiang.xpage.core.PageOption
-import com.xuexiang.xui.widget.actionbar.TitleBar
-import com.xuexiang.xutil.common.logger.Logger
-import com.xuexiang.xutil.net.JsonUtil
-
-/**
- * 使用XPageFragment
- *
- * @author xuexiang
- * @since 2019-05-26 18:15
- */
-@Suppress("DEPRECATION", "unused", "UNUSED_PARAMETER", "NAME_SHADOWING", "OVERRIDE_DEPRECATION")
-@Page(params = [AgentWebFragment.KEY_URL])
-class XPageWebViewFragment : BaseFragment(), View.OnClickListener {
- private var mAgentWeb: AgentWeb? = null
- private var mPopupMenu: PopupMenu? = null
- private var mDownloadingService: DownloadingService? = null
- override fun viewBindingInflate(
- inflater: LayoutInflater,
- container: ViewGroup,
- ): FragmentAgentwebBinding {
- return FragmentAgentwebBinding.inflate(inflater, container, false)
- }
-
- override fun initTitle(): TitleBar? {
- return null
- }
-
- /**
- * 初始化控件
- */
- override fun initViews() {
- mAgentWeb = AgentWeb.with(this) //传入AgentWeb的父控件。
- .setAgentWebParent(
- (rootView as LinearLayout),
- -1,
- LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT
- )
- ) //设置进度条颜色与高度,-1为默认值,高度为2,单位为dp。
- .useDefaultIndicator(-1, 3) //设置 IAgentWebSettings。
- .setAgentWebWebSettings(settings) //WebViewClient , 与 WebView 使用一致 ,但是请勿获取WebView调用setWebViewClient(xx)方法了,会覆盖AgentWeb DefaultWebClient,同时相应的中间件也会失效。
- .setWebViewClient(mWebViewClient) //WebChromeClient
- .setWebChromeClient(mWebChromeClient) //设置WebChromeClient中间件,支持多个WebChromeClient,AgentWeb 3.0.0 加入。
- .useMiddlewareWebChrome(middlewareWebChrome) //设置WebViewClient中间件,支持多个WebViewClient, AgentWeb 3.0.0 加入。
- .useMiddlewareWebClient(middlewareWebClient) //权限拦截 2.0.0 加入。
- .setPermissionInterceptor(mPermissionInterceptor) //严格模式 Android 4.2.2 以下会放弃注入对象 ,使用AgentWebView没影响。
- .setSecurityType(AgentWeb.SecurityType.STRICT_CHECK) //自定义UI AgentWeb3.0.0 加入。
- .setAgentWebUIController(UIController(requireActivity())) //参数1是错误显示的布局,参数2点击刷新控件ID -1表示点击整个布局都刷新, AgentWeb 3.0.0 加入。
- .setMainFrameErrorView(R.layout.agentweb_error_page, -1)
- .setWebLayout(webLayout) //打开其他页面时,弹窗质询用户前往其他应用 AgentWeb 3.0.0 加入。
- .setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.DISALLOW) //拦截找不到相关页面的Url AgentWeb 3.0.0 加入。
- .interceptUnkownUrl() //创建AgentWeb。
- .createAgentWeb()
- .ready() //设置 WebSettings。
- //WebView载入该url地址的页面并显示。
- .go(url)
- if (com.idormy.sms.forwarder.App.isDebug) {
- AgentWebConfig.debug()
- }
- pageNavigator(View.GONE)
- // 得到 AgentWeb 最底层的控件
- addBackgroundChild(mAgentWeb!!.webCreator.webParentLayout)
-
- // AgentWeb 没有把WebView的功能全面覆盖 ,所以某些设置 AgentWeb 没有提供,请从WebView方面入手设置。
- mAgentWeb!!.webCreator.webView.overScrollMode = WebView.OVER_SCROLL_NEVER
- }
-
- private val webLayout: IWebLayout<*, *>
- get() = WebLayout(activity)
-
- private fun addBackgroundChild(frameLayout: FrameLayout) {
- val textView = TextView(frameLayout.context)
- textView.text = getString(R.string.provided_by_agentweb)
- textView.textSize = 16f
- textView.setTextColor(Color.parseColor("#727779"))
- frameLayout.setBackgroundColor(Color.parseColor("#272b2d"))
- val params = FrameLayout.LayoutParams(-2, -2)
- params.gravity = Gravity.CENTER_HORIZONTAL
- val scale = frameLayout.context.resources.displayMetrics.density
- params.topMargin = (15 * scale + 0.5f).toInt()
- frameLayout.addView(textView, 0, params)
- }
-
- override fun initListeners() {
- binding!!.includeTitle.ivBack.setOnClickListener(this)
- binding!!.includeTitle.ivFinish.setOnClickListener(this)
- binding!!.includeTitle.ivMore.setOnClickListener(this)
- }
-
- private fun pageNavigator(tag: Int) {
- //返回的导航按钮
- binding!!.includeTitle.ivBack.visibility = tag
- binding!!.includeTitle.viewLine.visibility = tag
- }
-
- @SingleClick
- override fun onClick(view: View) {
- val id = view.id
- if (id == R.id.iv_back) {
- // true表示AgentWeb处理了该事件
- if (!mAgentWeb!!.back()) {
- popToBack()
- }
- } else if (id == R.id.iv_finish) {
- popToBack()
- } else if (id == R.id.iv_more) {
- showPoPup(view)
- }
- }
- //=====================下载============================//
- /**
- * 更新于 AgentWeb 4.0.0,下载监听
- */
- private var mDownloadListenerAdapter: DownloadListenerAdapter =
- object : DownloadListenerAdapter() {
- /**
- *
- * @param url 下载链接
- * @param userAgent UserAgent
- * @param contentDisposition ContentDisposition
- * @param mimeType 资源的媒体类型
- * @param contentLength 文件长度
- * @param extra 下载配置 , 用户可以通过 Extra 修改下载icon , 关闭进度条 , 是否强制下载。
- * @return true 表示用户处理了该下载事件 , false 交给 AgentWeb 下载
- */
- override fun onStart(
- url: String,
- userAgent: String,
- contentDisposition: String,
- mimeType: String,
- contentLength: Long,
- extra: Extra,
- ): Boolean {
- Logger.i("onStart:$url")
- // 是否开启断点续传
- extra.setOpenBreakPointDownload(true) //下载通知的icon
- .setIcon(R.drawable.ic_file_download_black_24dp) // 连接的超时时间
- .setConnectTimeOut(6000) // 以8KB位单位,默认60s ,如果60s内无法从网络流中读满8KB数据,则抛出异常
- .setBlockMaxTime(10 * 60 * 1000) // 下载的超时时间
- .setDownloadTimeOut(Long.MAX_VALUE) // 串行下载更节省资源哦
- .setParallelDownload(false) // false 关闭进度通知
- .setEnableIndicator(true) // 自定义请求头
- .addHeader("Cookie", "xx") // 下载完成自动打开
- .setAutoOpen(true).isForceDownload = true
- return false
- }
-
- /**
- *
- * 不需要暂停或者停止下载该方法可以不必实现
- * @param url
- * @param downloadingService 用户可以通过 DownloadingService#shutdownNow 终止下载
- */
- override fun onBindService(url: String, downloadingService: DownloadingService) {
- super.onBindService(url, downloadingService)
- mDownloadingService = downloadingService
- Logger.i("onBindService:$url DownloadingService:$downloadingService")
- }
-
- /**
- * 回调onUnbindService方法,让用户释放掉 DownloadingService。
- * @param url
- * @param downloadingService
- */
- override fun onUnbindService(url: String, downloadingService: DownloadingService) {
- super.onUnbindService(url, downloadingService)
- mDownloadingService = null
- Logger.i("onUnbindService:$url")
- }
-
- /**
- *
- * @param url 下载链接
- * @param loaded 已经下载的长度
- * @param length 文件的总大小
- * @param usedTime 耗时 ,单位ms
- * 注意该方法回调在子线程 ,线程名 AsyncTask #XX 或者 AgentWeb # XX
- */
- override fun onProgress(url: String, loaded: Long, length: Long, usedTime: Long) {
- val mProgress = (loaded / length.toFloat() * 100).toInt()
- Logger.i("onProgress:$mProgress")
- super.onProgress(url, loaded, length, usedTime)
- }
-
- /**
- *
- * @param path 文件的绝对路径
- * @param url 下载地址
- * @param throwable 如果异常,返回给用户异常
- * @return true 表示用户处理了下载完成后续的事件 ,false 默认交给AgentWeb 处理
- */
- override fun onResult(path: String, url: String, throwable: Throwable): Boolean {
- //下载成功
- //if (null == throwable) {
- //do you work
- //} else { //下载失败
- //}
- // true 不会发出下载完成的通知 , 或者打开文件
- return false
- }
- }
- /**
- * AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
- * 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
- * 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
- * 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
- * @return WebListenerManager
- */
- /**
- * 下载服务设置
- *
- * @return IAgentWebSettings
- */
- val settings: IAgentWebSettings<*>
- get() = object : AbsAgentWebSettings() {
- private val mAgentWeb: AgentWeb? = null
- override fun bindAgentWebSupport(agentWeb: AgentWeb) {
- this.mAgentWeb = agentWeb
- }
-
- /**
- * AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
- * 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
- * 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
- * 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
- * @return WebListenerManager
- */
- override fun setDownloader(
- webView: WebView,
- downloadListener: DownloadListener,
- ): WebListenerManager {
- return super.setDownloader(
- webView,
- DefaultDownloadImpl
- .create(
- activity!!,
- webView,
- mDownloadListenerAdapter,
- mDownloadListenerAdapter,
- mAgentWeb.permissionInterceptor
- )
- )
- }
- }
- //===================WebChromeClient 和 WebViewClient===========================//
- /**
- * 页面空白,请检查scheme是否加上, scheme://host:port/path?query&query 。
- *
- * @return mUrl
- */
- val url: String
- get() {
- var target = ""
- val bundle = arguments
- if (bundle != null) {
- target = bundle.getString(AgentWebFragment.KEY_URL).toString()
- }
- if (TextUtils.isEmpty(target)) {
- target = "https://github.com/xuexiangjys"
- }
- return target
- }
-
- /**
- * 和浏览器相关,包括和JS的交互
- */
- private var mWebChromeClient: WebChromeClient = object : WebChromeClient() {
- override fun onProgressChanged(view: WebView, newProgress: Int) {
- super.onProgressChanged(view, newProgress)
- //网页加载进度
- }
-
- override fun onReceivedTitle(view: WebView, title: String) {
- var title = title
- super.onReceivedTitle(view, title)
- if (!TextUtils.isEmpty(title)) {
- if (title.length > 10) {
- title = title.substring(0, 10) + "..."
- }
- binding!!.includeTitle.toolbarTitle.text = title
- }
- }
- }
-
- /**
- * 和网页url加载相关,统计加载时间
- */
- @Suppress("DEPRECATION")
- private var mWebViewClient: WebViewClient = object : WebViewClient() {
- private val mTimer = HashMap()
- override fun onReceivedError(
- view: WebView,
- request: WebResourceRequest,
- error: WebResourceError,
- ) {
- super.onReceivedError(view, request, error)
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
- return shouldOverrideUrlLoading(view, request.url.toString() + "")
- }
-
- override fun shouldInterceptRequest(
- view: WebView,
- request: WebResourceRequest,
- ): WebResourceResponse? {
- return super.shouldInterceptRequest(view, request)
- }
-
- override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
- //intent:// scheme的处理 如果返回false , 则交给 DefaultWebClient 处理 , 默认会打开该Activity , 如果Activity不存在则跳到应用市场上去. true 表示拦截
- //例如优酷视频播放 ,intent://play?...package=com.youku.phone;end;
- //优酷想唤起自己应用播放该视频 , 下面拦截地址返回 true 则会在应用内 H5 播放 ,禁止优酷唤起播放该视频, 如果返回 false , DefaultWebClient 会根据intent 协议处理 该地址 , 首先匹配该应用存不存在 ,如果存在 , 唤起该应用播放 , 如果不存在 , 则跳到应用市场下载该应用 .
- return url.startsWith("intent://") && url.contains("com.youku.phone")
- }
-
- override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {
- mTimer[url] = System.currentTimeMillis()
- //if (url == url) {
- // pageNavigator(View.GONE)
- //} else {
- pageNavigator(View.VISIBLE)
- //}
- }
-
- override fun onPageFinished(view: WebView, url: String) {
- super.onPageFinished(view, url)
- if (mTimer[url] != null) {
- val overTime = System.currentTimeMillis()
- val startTime = mTimer[url]
- //统计页面的使用时长
- Logger.i(" page mUrl:" + url + " used time:" + (overTime - startTime!!))
- }
- }
-
- override fun onReceivedHttpError(
- view: WebView,
- request: WebResourceRequest,
- errorResponse: WebResourceResponse,
- ) {
- super.onReceivedHttpError(view, request, errorResponse)
- }
-
- override fun onReceivedError(
- view: WebView,
- errorCode: Int,
- description: String,
- failingUrl: String,
- ) {
- super.onReceivedError(view, errorCode, description, failingUrl)
- }
- }
- //=====================菜单========================//
- /**
- * 显示更多菜单
- *
- * @param view 菜单依附在该View下面
- */
- private fun showPoPup(view: View) {
- if (mPopupMenu == null) {
- mPopupMenu = PopupMenu(requireContext(), view)
- mPopupMenu!!.inflate(R.menu.menu_toolbar_web)
- mPopupMenu!!.setOnMenuItemClickListener(mOnMenuItemClickListener)
- }
- mPopupMenu!!.show()
- }
-
- /**
- * 菜单事件
- */
- private val mOnMenuItemClickListener = PopupMenu.OnMenuItemClickListener { item ->
- when (item.itemId) {
- R.id.refresh -> {
- if (mAgentWeb != null) {
- mAgentWeb!!.urlLoader.reload() // 刷新
- }
- return@OnMenuItemClickListener true
- }
- R.id.copy -> {
- if (mAgentWeb != null) {
- mAgentWeb!!.webCreator.webView.url?.let { toCopy(context, it) }
- }
- return@OnMenuItemClickListener true
- }
- R.id.default_browser -> {
- if (mAgentWeb != null) {
- mAgentWeb!!.webCreator.webView.url?.let { openBrowser(it) }
- }
- return@OnMenuItemClickListener true
- }
- R.id.share -> {
- if (mAgentWeb != null) {
- mAgentWeb!!.webCreator.webView.url?.let { shareWebUrl(it) }
- }
- return@OnMenuItemClickListener true
- }
- else -> false
- }
- }
-
- /**
- * 打开浏览器
- *
- * @param targetUrl 外部浏览器打开的地址
- */
- private fun openBrowser(targetUrl: String) {
- if (TextUtils.isEmpty(targetUrl) || targetUrl.startsWith("file://")) {
- XToastUtils.toast(targetUrl + getString(R.string.cannot_open_with_browser))
- return
- }
- val intent = Intent()
- intent.action = "android.intent.action.VIEW"
- val uri = Uri.parse(targetUrl)
- intent.data = uri
- startActivity(intent)
- }
-
- /**
- * 分享网页链接
- *
- * @param url 网页链接
- */
- private fun shareWebUrl(url: String) {
- val shareIntent = Intent()
- shareIntent.action = Intent.ACTION_SEND
- shareIntent.putExtra(Intent.EXTRA_TEXT, url)
- shareIntent.type = "text/plain"
- //设置分享列表的标题,并且每次都显示分享列表
- startActivity(Intent.createChooser(shareIntent, getString(R.string.share_to)))
- }
-
- /**
- * 复制字符串
- *
- * @param context
- * @param text
- */
- private fun toCopy(context: Context?, text: String) {
- val manager =
- requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
- manager.setPrimaryClip(ClipData.newPlainText(null, text))
- }
-
- //===================生命周期管理===========================//
- override fun onResume() {
- if (mAgentWeb != null) {
- mAgentWeb!!.webLifeCycle.onResume() //恢复
- }
- super.onResume()
- }
-
- override fun onPause() {
- if (mAgentWeb != null) {
- mAgentWeb!!.webLifeCycle.onPause() //暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
- }
- super.onPause()
- }
-
- override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
- return mAgentWeb != null && mAgentWeb!!.handleKeyEvent(keyCode, event)
- }
-
- override fun onDestroyView() {
- if (mAgentWeb != null) {
- mAgentWeb!!.destroy()
- }
- super.onDestroyView()
- }
- //===================中间键===========================//// 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
- // 执行 DefaultWebClient#shouldOverrideUrlLoading
- // do you work
- /**
- * MiddlewareWebClientBase 是 AgentWeb 3.0.0 提供一个强大的功能,
- * 如果用户需要使用 AgentWeb 提供的功能, 不想重写 WebClientView方
- * 法覆盖AgentWeb提供的功能,那么 MiddlewareWebClientBase 是一个
- * 不错的选择 。
- */
- private val middlewareWebClient: MiddlewareWebClientBase
- get() = object : MiddlewareWebViewClient() {
- override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
- // 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
- if (url.startsWith("agentweb")) {
- return true
- }
- // 执行 DefaultWebClient#shouldOverrideUrlLoading
- return super.shouldOverrideUrlLoading(view, url)
- // do you work
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- override fun shouldOverrideUrlLoading(
- view: WebView,
- request: WebResourceRequest,
- ): Boolean {
- return super.shouldOverrideUrlLoading(view, request)
- }
- }
- private val middlewareWebChrome: MiddlewareWebChromeBase
- get() = object : MiddlewareChromeClient() {}
-
- /**
- * 权限申请拦截器
- */
- private var mPermissionInterceptor = PermissionInterceptor { url, permissions, action ->
-
- /**
- * PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
- * @param url
- * @param permissions
- * @param action
- * @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
- */
- /**
- * PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
- * @param url
- * @param permissions
- * @param action
- * @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
- */
- Logger.i("mUrl:" + url + " permission:" + JsonUtil.toJson(permissions) + " action:" + action)
- false
- }
-
- companion object {
- /**
- * 打开网页
- *
- * @param xPageActivity
- * @param url
- * @return
- */
- fun openUrl(xPageActivity: XPageActivity?, url: String?): Fragment {
- return PageOption.to(XPageWebViewFragment::class.java)
- .putString(AgentWebFragment.KEY_URL, url)
- .open(xPageActivity!!)
- }
-
- /**
- * 打开网页
- *
- * @param fragment
- * @param url
- * @return
- */
- fun openUrl(fragment: XPageFragment?, url: String?): Fragment {
- return PageOption.to(XPageWebViewFragment::class.java)
- .setNewActivity(true)
- .putString(AgentWebFragment.KEY_URL, url)
- .open(fragment!!)
- }
- }
+package com.idormy.sms.forwarder.core.webview
+
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.content.Context
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.net.Uri
+import android.os.Build
+import android.text.TextUtils
+import android.view.*
+import android.webkit.*
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.annotation.RequiresApi
+import androidx.appcompat.widget.PopupMenu
+import androidx.fragment.app.Fragment
+import com.idormy.sms.forwarder.R
+import com.idormy.sms.forwarder.core.BaseFragment
+import com.idormy.sms.forwarder.databinding.FragmentAgentwebBinding
+import com.idormy.sms.forwarder.utils.XToastUtils
+import com.just.agentweb.action.PermissionInterceptor
+import com.just.agentweb.core.AgentWeb
+import com.just.agentweb.core.client.DefaultWebClient
+import com.just.agentweb.core.client.MiddlewareWebChromeBase
+import com.just.agentweb.core.client.MiddlewareWebClientBase
+import com.just.agentweb.core.client.WebListenerManager
+import com.just.agentweb.core.web.AbsAgentWebSettings
+import com.just.agentweb.core.web.AgentWebConfig
+import com.just.agentweb.core.web.IAgentWebSettings
+import com.just.agentweb.download.AgentWebDownloader.Extra
+import com.just.agentweb.download.DefaultDownloadImpl
+import com.just.agentweb.download.DownloadListenerAdapter
+import com.just.agentweb.download.DownloadingService
+import com.just.agentweb.widget.IWebLayout
+import com.xuexiang.xaop.annotation.SingleClick
+import com.xuexiang.xpage.annotation.Page
+import com.xuexiang.xpage.base.XPageActivity
+import com.xuexiang.xpage.base.XPageFragment
+import com.xuexiang.xpage.core.PageOption
+import com.xuexiang.xui.widget.actionbar.TitleBar
+import com.xuexiang.xutil.common.logger.Logger
+import com.xuexiang.xutil.net.JsonUtil
+
+/**
+ * 使用XPageFragment
+ *
+ * @author xuexiang
+ * @since 2019-05-26 18:15
+ */
+@Suppress("DEPRECATION", "unused", "UNUSED_PARAMETER", "NAME_SHADOWING", "OVERRIDE_DEPRECATION")
+@Page(params = [AgentWebFragment.KEY_URL])
+class XPageWebViewFragment : BaseFragment(), View.OnClickListener {
+ private var mAgentWeb: AgentWeb? = null
+ private var mPopupMenu: PopupMenu? = null
+ private var mDownloadingService: DownloadingService? = null
+ override fun viewBindingInflate(
+ inflater: LayoutInflater,
+ container: ViewGroup,
+ ): FragmentAgentwebBinding {
+ return FragmentAgentwebBinding.inflate(inflater, container, false)
+ }
+
+ override fun initTitle(): TitleBar? {
+ return null
+ }
+
+ /**
+ * 初始化控件
+ */
+ override fun initViews() {
+ mAgentWeb = AgentWeb.with(this) //传入AgentWeb的父控件。
+ .setAgentWebParent(
+ (rootView as LinearLayout),
+ -1,
+ LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT
+ )
+ ) //设置进度条颜色与高度,-1为默认值,高度为2,单位为dp。
+ .useDefaultIndicator(-1, 3) //设置 IAgentWebSettings。
+ .setAgentWebWebSettings(settings) //WebViewClient , 与 WebView 使用一致 ,但是请勿获取WebView调用setWebViewClient(xx)方法了,会覆盖AgentWeb DefaultWebClient,同时相应的中间件也会失效。
+ .setWebViewClient(mWebViewClient) //WebChromeClient
+ .setWebChromeClient(mWebChromeClient) //设置WebChromeClient中间件,支持多个WebChromeClient,AgentWeb 3.0.0 加入。
+ .useMiddlewareWebChrome(middlewareWebChrome) //设置WebViewClient中间件,支持多个WebViewClient, AgentWeb 3.0.0 加入。
+ .useMiddlewareWebClient(middlewareWebClient) //权限拦截 2.0.0 加入。
+ .setPermissionInterceptor(mPermissionInterceptor) //严格模式 Android 4.2.2 以下会放弃注入对象 ,使用AgentWebView没影响。
+ .setSecurityType(AgentWeb.SecurityType.STRICT_CHECK) //自定义UI AgentWeb3.0.0 加入。
+ .setAgentWebUIController(UIController(requireActivity())) //参数1是错误显示的布局,参数2点击刷新控件ID -1表示点击整个布局都刷新, AgentWeb 3.0.0 加入。
+ .setMainFrameErrorView(R.layout.agentweb_error_page, -1)
+ .setWebLayout(webLayout) //打开其他页面时,弹窗质询用户前往其他应用 AgentWeb 3.0.0 加入。
+ .setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.DISALLOW) //拦截找不到相关页面的Url AgentWeb 3.0.0 加入。
+ .interceptUnkownUrl() //创建AgentWeb。
+ .createAgentWeb()
+ .ready() //设置 WebSettings。
+ //WebView载入该url地址的页面并显示。
+ .go(url)
+ if (com.idormy.sms.forwarder.App.isDebug) {
+ AgentWebConfig.debug()
+ }
+ pageNavigator(View.GONE)
+ // 得到 AgentWeb 最底层的控件
+ addBackgroundChild(mAgentWeb!!.webCreator.webParentLayout)
+
+ // AgentWeb 没有把WebView的功能全面覆盖 ,所以某些设置 AgentWeb 没有提供,请从WebView方面入手设置。
+ mAgentWeb!!.webCreator.webView.overScrollMode = WebView.OVER_SCROLL_NEVER
+ }
+
+ private val webLayout: IWebLayout<*, *>
+ get() = WebLayout(activity)
+
+ private fun addBackgroundChild(frameLayout: FrameLayout) {
+ val textView = TextView(frameLayout.context)
+ textView.text = getString(R.string.provided_by_agentweb)
+ textView.textSize = 16f
+ textView.setTextColor(Color.parseColor("#727779"))
+ frameLayout.setBackgroundColor(Color.parseColor("#272b2d"))
+ val params = FrameLayout.LayoutParams(-2, -2)
+ params.gravity = Gravity.CENTER_HORIZONTAL
+ val scale = frameLayout.context.resources.displayMetrics.density
+ params.topMargin = (15 * scale + 0.5f).toInt()
+ frameLayout.addView(textView, 0, params)
+ }
+
+ override fun initListeners() {
+ binding!!.includeTitle.ivBack.setOnClickListener(this)
+ binding!!.includeTitle.ivFinish.setOnClickListener(this)
+ binding!!.includeTitle.ivMore.setOnClickListener(this)
+ }
+
+ private fun pageNavigator(tag: Int) {
+ //返回的导航按钮
+ binding!!.includeTitle.ivBack.visibility = tag
+ binding!!.includeTitle.viewLine.visibility = tag
+ }
+
+ @SingleClick
+ override fun onClick(view: View) {
+ val id = view.id
+ if (id == R.id.iv_back) {
+ // true表示AgentWeb处理了该事件
+ if (!mAgentWeb!!.back()) {
+ popToBack()
+ }
+ } else if (id == R.id.iv_finish) {
+ popToBack()
+ } else if (id == R.id.iv_more) {
+ showPoPup(view)
+ }
+ }
+ //=====================下载============================//
+ /**
+ * 更新于 AgentWeb 4.0.0,下载监听
+ */
+ private var mDownloadListenerAdapter: DownloadListenerAdapter =
+ object : DownloadListenerAdapter() {
+ /**
+ *
+ * @param url 下载链接
+ * @param userAgent UserAgent
+ * @param contentDisposition ContentDisposition
+ * @param mimeType 资源的媒体类型
+ * @param contentLength 文件长度
+ * @param extra 下载配置 , 用户可以通过 Extra 修改下载icon , 关闭进度条 , 是否强制下载。
+ * @return true 表示用户处理了该下载事件 , false 交给 AgentWeb 下载
+ */
+ override fun onStart(
+ url: String,
+ userAgent: String,
+ contentDisposition: String,
+ mimeType: String,
+ contentLength: Long,
+ extra: Extra,
+ ): Boolean {
+ Logger.i("onStart:$url")
+ // 是否开启断点续传
+ extra.setOpenBreakPointDownload(true) //下载通知的icon
+ .setIcon(R.drawable.ic_file_download_black_24dp) // 连接的超时时间
+ .setConnectTimeOut(6000) // 以8KB位单位,默认60s ,如果60s内无法从网络流中读满8KB数据,则抛出异常
+ .setBlockMaxTime(10 * 60 * 1000) // 下载的超时时间
+ .setDownloadTimeOut(Long.MAX_VALUE) // 串行下载更节省资源哦
+ .setParallelDownload(false) // false 关闭进度通知
+ .setEnableIndicator(true) // 自定义请求头
+ .addHeader("Cookie", "xx") // 下载完成自动打开
+ .setAutoOpen(true).isForceDownload = true
+ return false
+ }
+
+ /**
+ *
+ * 不需要暂停或者停止下载该方法可以不必实现
+ * @param url
+ * @param downloadingService 用户可以通过 DownloadingService#shutdownNow 终止下载
+ */
+ override fun onBindService(url: String, downloadingService: DownloadingService) {
+ super.onBindService(url, downloadingService)
+ mDownloadingService = downloadingService
+ Logger.i("onBindService:$url DownloadingService:$downloadingService")
+ }
+
+ /**
+ * 回调onUnbindService方法,让用户释放掉 DownloadingService。
+ * @param url
+ * @param downloadingService
+ */
+ override fun onUnbindService(url: String, downloadingService: DownloadingService) {
+ super.onUnbindService(url, downloadingService)
+ mDownloadingService = null
+ Logger.i("onUnbindService:$url")
+ }
+
+ /**
+ *
+ * @param url 下载链接
+ * @param loaded 已经下载的长度
+ * @param length 文件的总大小
+ * @param usedTime 耗时 ,单位ms
+ * 注意该方法回调在子线程 ,线程名 AsyncTask #XX 或者 AgentWeb # XX
+ */
+ override fun onProgress(url: String, loaded: Long, length: Long, usedTime: Long) {
+ val mProgress = (loaded / length.toFloat() * 100).toInt()
+ Logger.i("onProgress:$mProgress")
+ super.onProgress(url, loaded, length, usedTime)
+ }
+
+ /**
+ *
+ * @param path 文件的绝对路径
+ * @param url 下载地址
+ * @param throwable 如果异常,返回给用户异常
+ * @return true 表示用户处理了下载完成后续的事件 ,false 默认交给AgentWeb 处理
+ */
+ override fun onResult(path: String, url: String, throwable: Throwable): Boolean {
+ //下载成功
+ //if (null == throwable) {
+ //do you work
+ //} else { //下载失败
+ //}
+ // true 不会发出下载完成的通知 , 或者打开文件
+ return false
+ }
+ }
+ /**
+ * AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
+ * 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
+ * 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
+ * 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
+ * @return WebListenerManager
+ */
+ /**
+ * 下载服务设置
+ *
+ * @return IAgentWebSettings
+ */
+ private val settings: IAgentWebSettings<*>
+ get() = object : AbsAgentWebSettings() {
+ private val mAgentWeb: AgentWeb? = null
+ override fun bindAgentWebSupport(agentWeb: AgentWeb) {
+ this.mAgentWeb = agentWeb
+ }
+
+ /**
+ * AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
+ * 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
+ * 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
+ * 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
+ * @return WebListenerManager
+ */
+ override fun setDownloader(
+ webView: WebView,
+ downloadListener: DownloadListener,
+ ): WebListenerManager {
+ return super.setDownloader(
+ webView,
+ DefaultDownloadImpl
+ .create(
+ activity!!,
+ webView,
+ mDownloadListenerAdapter,
+ mDownloadListenerAdapter,
+ mAgentWeb.permissionInterceptor
+ )
+ )
+ }
+ }
+ //===================WebChromeClient 和 WebViewClient===========================//
+ /**
+ * 页面空白,请检查scheme是否加上, scheme://host:port/path?query&query 。
+ *
+ * @return mUrl
+ */
+ val url: String
+ get() {
+ var target = ""
+ val bundle = arguments
+ if (bundle != null) {
+ target = bundle.getString(AgentWebFragment.KEY_URL).toString()
+ }
+ if (TextUtils.isEmpty(target)) {
+ target = "https://github.com/xuexiangjys"
+ }
+ return target
+ }
+
+ /**
+ * 和浏览器相关,包括和JS的交互
+ */
+ private var mWebChromeClient: WebChromeClient = object : WebChromeClient() {
+ override fun onProgressChanged(view: WebView, newProgress: Int) {
+ super.onProgressChanged(view, newProgress)
+ //网页加载进度
+ }
+
+ override fun onReceivedTitle(view: WebView, title: String) {
+ var title = title
+ super.onReceivedTitle(view, title)
+ if (!TextUtils.isEmpty(title)) {
+ if (title.length > 10) {
+ title = title.substring(0, 10) + "..."
+ }
+ binding!!.includeTitle.toolbarTitle.text = title
+ }
+ }
+ }
+
+ /**
+ * 和网页url加载相关,统计加载时间
+ */
+ @Suppress("DEPRECATION")
+ private var mWebViewClient: WebViewClient = object : WebViewClient() {
+ private val mTimer = HashMap()
+ override fun onReceivedError(
+ view: WebView,
+ request: WebResourceRequest,
+ error: WebResourceError,
+ ) {
+ super.onReceivedError(view, request, error)
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
+ return shouldOverrideUrlLoading(view, request.url.toString() + "")
+ }
+
+ override fun shouldInterceptRequest(
+ view: WebView,
+ request: WebResourceRequest,
+ ): WebResourceResponse? {
+ return super.shouldInterceptRequest(view, request)
+ }
+
+ override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
+ //intent:// scheme的处理 如果返回false , 则交给 DefaultWebClient 处理 , 默认会打开该Activity , 如果Activity不存在则跳到应用市场上去. true 表示拦截
+ //例如优酷视频播放 ,intent://play?...package=com.youku.phone;end;
+ //优酷想唤起自己应用播放该视频 , 下面拦截地址返回 true 则会在应用内 H5 播放 ,禁止优酷唤起播放该视频, 如果返回 false , DefaultWebClient 会根据intent 协议处理 该地址 , 首先匹配该应用存不存在 ,如果存在 , 唤起该应用播放 , 如果不存在 , 则跳到应用市场下载该应用 .
+ return url.startsWith("intent://") && url.contains("com.youku.phone")
+ }
+
+ override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {
+ mTimer[url] = System.currentTimeMillis()
+ //if (url == url) {
+ // pageNavigator(View.GONE)
+ //} else {
+ pageNavigator(View.VISIBLE)
+ //}
+ }
+
+ override fun onPageFinished(view: WebView, url: String) {
+ super.onPageFinished(view, url)
+ if (mTimer[url] != null) {
+ val overTime = System.currentTimeMillis()
+ val startTime = mTimer[url]
+ //统计页面的使用时长
+ Logger.i(" page mUrl:" + url + " used time:" + (overTime - startTime!!))
+ }
+ }
+
+ override fun onReceivedHttpError(
+ view: WebView,
+ request: WebResourceRequest,
+ errorResponse: WebResourceResponse,
+ ) {
+ super.onReceivedHttpError(view, request, errorResponse)
+ }
+
+ override fun onReceivedError(
+ view: WebView,
+ errorCode: Int,
+ description: String,
+ failingUrl: String,
+ ) {
+ super.onReceivedError(view, errorCode, description, failingUrl)
+ }
+ }
+ //=====================菜单========================//
+ /**
+ * 显示更多菜单
+ *
+ * @param view 菜单依附在该View下面
+ */
+ private fun showPoPup(view: View) {
+ if (mPopupMenu == null) {
+ mPopupMenu = PopupMenu(requireContext(), view)
+ mPopupMenu!!.inflate(R.menu.menu_toolbar_web)
+ mPopupMenu!!.setOnMenuItemClickListener(mOnMenuItemClickListener)
+ }
+ mPopupMenu!!.show()
+ }
+
+ /**
+ * 菜单事件
+ */
+ private val mOnMenuItemClickListener = PopupMenu.OnMenuItemClickListener { item ->
+ when (item.itemId) {
+ R.id.refresh -> {
+ if (mAgentWeb != null) {
+ mAgentWeb!!.urlLoader.reload() // 刷新
+ }
+ return@OnMenuItemClickListener true
+ }
+ R.id.copy -> {
+ if (mAgentWeb != null) {
+ mAgentWeb!!.webCreator.webView.url?.let { toCopy(context, it) }
+ }
+ return@OnMenuItemClickListener true
+ }
+ R.id.default_browser -> {
+ if (mAgentWeb != null) {
+ mAgentWeb!!.webCreator.webView.url?.let { openBrowser(it) }
+ }
+ return@OnMenuItemClickListener true
+ }
+ R.id.share -> {
+ if (mAgentWeb != null) {
+ mAgentWeb!!.webCreator.webView.url?.let { shareWebUrl(it) }
+ }
+ return@OnMenuItemClickListener true
+ }
+ else -> false
+ }
+ }
+
+ /**
+ * 打开浏览器
+ *
+ * @param targetUrl 外部浏览器打开的地址
+ */
+ private fun openBrowser(targetUrl: String) {
+ if (TextUtils.isEmpty(targetUrl) || targetUrl.startsWith("file://")) {
+ XToastUtils.toast(targetUrl + getString(R.string.cannot_open_with_browser))
+ return
+ }
+ val intent = Intent()
+ intent.action = "android.intent.action.VIEW"
+ val uri = Uri.parse(targetUrl)
+ intent.data = uri
+ startActivity(intent)
+ }
+
+ /**
+ * 分享网页链接
+ *
+ * @param url 网页链接
+ */
+ private fun shareWebUrl(url: String) {
+ val shareIntent = Intent()
+ shareIntent.action = Intent.ACTION_SEND
+ shareIntent.putExtra(Intent.EXTRA_TEXT, url)
+ shareIntent.type = "text/plain"
+ //设置分享列表的标题,并且每次都显示分享列表
+ startActivity(Intent.createChooser(shareIntent, getString(R.string.share_to)))
+ }
+
+ /**
+ * 复制字符串
+ *
+ * @param context
+ * @param text
+ */
+ private fun toCopy(context: Context?, text: String) {
+ val manager =
+ requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ manager.setPrimaryClip(ClipData.newPlainText(null, text))
+ }
+
+ //===================生命周期管理===========================//
+ override fun onResume() {
+ if (mAgentWeb != null) {
+ mAgentWeb!!.webLifeCycle.onResume() //恢复
+ }
+ super.onResume()
+ }
+
+ override fun onPause() {
+ if (mAgentWeb != null) {
+ mAgentWeb!!.webLifeCycle.onPause() //暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
+ }
+ super.onPause()
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
+ return mAgentWeb != null && mAgentWeb!!.handleKeyEvent(keyCode, event)
+ }
+
+ override fun onDestroyView() {
+ if (mAgentWeb != null) {
+ mAgentWeb!!.destroy()
+ }
+ super.onDestroyView()
+ }
+ //===================中间键===========================//// 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
+ // 执行 DefaultWebClient#shouldOverrideUrlLoading
+ // do you work
+ /**
+ * MiddlewareWebClientBase 是 AgentWeb 3.0.0 提供一个强大的功能,
+ * 如果用户需要使用 AgentWeb 提供的功能, 不想重写 WebClientView方
+ * 法覆盖AgentWeb提供的功能,那么 MiddlewareWebClientBase 是一个
+ * 不错的选择 。
+ */
+ private val middlewareWebClient: MiddlewareWebClientBase
+ get() = object : MiddlewareWebViewClient() {
+ override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
+ // 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
+ if (url.startsWith("agentweb")) {
+ return true
+ }
+ // 执行 DefaultWebClient#shouldOverrideUrlLoading
+ return super.shouldOverrideUrlLoading(view, url)
+ // do you work
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ override fun shouldOverrideUrlLoading(
+ view: WebView,
+ request: WebResourceRequest,
+ ): Boolean {
+ return super.shouldOverrideUrlLoading(view, request)
+ }
+ }
+ private val middlewareWebChrome: MiddlewareWebChromeBase
+ get() = object : MiddlewareChromeClient() {}
+
+ /**
+ * 权限申请拦截器
+ */
+ private var mPermissionInterceptor = PermissionInterceptor { url, permissions, action ->
+
+ /**
+ * PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
+ * @param url
+ * @param permissions
+ * @param action
+ * @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
+ */
+ /**
+ * PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
+ * @param url
+ * @param permissions
+ * @param action
+ * @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
+ */
+ Logger.i("mUrl:" + url + " permission:" + JsonUtil.toJson(permissions) + " action:" + action)
+ false
+ }
+
+ companion object {
+ /**
+ * 打开网页
+ *
+ * @param xPageActivity
+ * @param url
+ * @return
+ */
+ fun openUrl(xPageActivity: XPageActivity?, url: String?): Fragment {
+ return PageOption.to(XPageWebViewFragment::class.java)
+ .putString(AgentWebFragment.KEY_URL, url)
+ .open(xPageActivity!!)
+ }
+
+ /**
+ * 打开网页
+ *
+ * @param fragment
+ * @param url
+ * @return
+ */
+ fun openUrl(fragment: XPageFragment?, url: String?): Fragment {
+ return PageOption.to(XPageWebViewFragment::class.java)
+ .setNewActivity(true)
+ .putString(AgentWebFragment.KEY_URL, url)
+ .open(fragment!!)
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/dao/RuleDao.kt b/app/src/main/java/com/idormy/sms/forwarder/database/dao/RuleDao.kt
index 6c91739e..1cf74893 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/dao/RuleDao.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/dao/RuleDao.kt
@@ -3,7 +3,7 @@ package com.idormy.sms.forwarder.database.dao
import androidx.paging.PagingSource
import androidx.room.*
import com.idormy.sms.forwarder.database.entity.Rule
-import com.idormy.sms.forwarder.database.entity.RuleAndSender
+//import com.idormy.sms.forwarder.database.entity.RuleAndSender
import io.reactivex.Completable
import io.reactivex.Single
@@ -48,9 +48,9 @@ interface RuleDao {
@Query("SELECT * FROM Rule where type=:type ORDER BY id DESC")
fun pagingSource(type: String): PagingSource
- @Transaction
- @Query("SELECT * FROM Rule where type=:type and status=:status and (sim_slot='ALL' or sim_slot=:simSlot)")
- suspend fun getRuleAndSender(type: String, status: Int, simSlot: String): List
+ //@Transaction
+ //@Query("SELECT * FROM Rule where type=:type and status=:status and (sim_slot='ALL' or sim_slot=:simSlot)")
+ //suspend fun getRuleAndSender(type: String, status: Int, simSlot: String): List
@Transaction
@Query("SELECT * FROM Rule where type=:type and status=:status and (sim_slot='ALL' or sim_slot=:simSlot)")
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/entity/Logs.kt b/app/src/main/java/com/idormy/sms/forwarder/database/entity/Logs.kt
index 99bd964f..e70b9642 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/entity/Logs.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/entity/Logs.kt
@@ -49,16 +49,4 @@ data class Logs(
@ColumnInfo(name = "forward_status", defaultValue = "1") var forwardStatus: Int = 1,
@ColumnInfo(name = "forward_response", defaultValue = "") var forwardResponse: String = "",
@ColumnInfo(name = "time") var time: Date = Date(),
-) : Parcelable {
-
- val statusImageId: Int
- get() {
- if (forwardStatus == 1) {
- return R.drawable.ic_round_warning
- } else if (forwardStatus == 2) {
- return R.drawable.ic_round_check
- }
- return R.drawable.ic_round_cancel
- }
-
-}
\ No newline at end of file
+) : Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/entity/Sender.kt b/app/src/main/java/com/idormy/sms/forwarder/database/entity/Sender.kt
index 2627bdaf..98bd5191 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/entity/Sender.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/entity/Sender.kt
@@ -20,29 +20,6 @@ data class Sender(
@ColumnInfo(name = "status", defaultValue = "1") var status: Int = 1,
@ColumnInfo(name = "time") var time: Date = Date(),
) : Parcelable {
- companion object {
-
- fun getImageId(type: Int): Int = when (type) {
- TYPE_DINGTALK_GROUP_ROBOT -> R.drawable.icon_dingtalk
- TYPE_EMAIL -> R.drawable.icon_email
- TYPE_BARK -> R.drawable.icon_bark
- TYPE_WEBHOOK -> R.drawable.icon_webhook
- TYPE_WEWORK_ROBOT -> R.drawable.icon_wework_robot
- TYPE_WEWORK_AGENT -> R.drawable.icon_wework_agent
- TYPE_SERVERCHAN -> R.drawable.icon_serverchan
- TYPE_TELEGRAM -> R.drawable.icon_telegram
- TYPE_FEISHU -> R.drawable.icon_feishu
- TYPE_PUSHPLUS -> R.drawable.icon_pushplus
- TYPE_GOTIFY -> R.drawable.icon_gotify
- TYPE_SMS -> R.drawable.icon_sms
- TYPE_DINGTALK_INNER_ROBOT -> R.drawable.icon_dingtalk_inner
- TYPE_FEISHU_APP -> R.drawable.icon_feishu_app
- TYPE_URL_SCHEME -> R.drawable.icon_url_scheme
- TYPE_SOCKET -> R.drawable.icon_socket
- else -> R.drawable.icon_sms
- }
-
- }
val imageId: Int
get() = when (type) {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/repository/FrpcRepository.kt b/app/src/main/java/com/idormy/sms/forwarder/database/repository/FrpcRepository.kt
index 58c4be7e..2a97388f 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/repository/FrpcRepository.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/repository/FrpcRepository.kt
@@ -1,36 +1,36 @@
-package com.idormy.sms.forwarder.database.repository
-
-import androidx.annotation.WorkerThread
-import com.idormy.sms.forwarder.database.dao.FrpcDao
-import com.idormy.sms.forwarder.database.entity.Frpc
-
-class FrpcRepository(
- private val frpcDao: FrpcDao,
-) {
-
- var listener: Listener? = null
-
- @WorkerThread
- fun insert(frpc: Frpc) {
- frpcDao.insert(frpc)
- }
-
- @WorkerThread
- fun delete(uid: String) {
- frpcDao.delete(uid)
- }
-
- @WorkerThread
- fun get(uid: String) = frpcDao.get(uid)
-
- @WorkerThread
- fun update(frpc: Frpc) = frpcDao.update(frpc)
-
- //TODO:允许主线程访问,后面再优化
- val all: List = frpcDao.getAll()
-
- fun deleteAll() {
- frpcDao.deleteAll()
- }
-
+package com.idormy.sms.forwarder.database.repository
+
+import androidx.annotation.WorkerThread
+import com.idormy.sms.forwarder.database.dao.FrpcDao
+import com.idormy.sms.forwarder.database.entity.Frpc
+
+class FrpcRepository(
+ private val frpcDao: FrpcDao,
+) {
+
+ //var listener: Listener? = null
+
+ @WorkerThread
+ fun insert(frpc: Frpc) {
+ frpcDao.insert(frpc)
+ }
+
+ @WorkerThread
+ fun delete(uid: String) {
+ frpcDao.delete(uid)
+ }
+
+ @WorkerThread
+ fun get(uid: String) = frpcDao.get(uid)
+
+ @WorkerThread
+ fun update(frpc: Frpc) = frpcDao.update(frpc)
+
+ //TODO:允许主线程访问,后面再优化
+ val all: List = frpcDao.getAll()
+
+ fun deleteAll() {
+ frpcDao.deleteAll()
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/repository/LogsRepository.kt b/app/src/main/java/com/idormy/sms/forwarder/database/repository/LogsRepository.kt
index 235d6ce8..41800d34 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/repository/LogsRepository.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/repository/LogsRepository.kt
@@ -11,10 +11,10 @@ class LogsRepository(private val logsDao: LogsDao) {
logsDao.delete(id)
}
- @WorkerThread
- fun deleteTimeAgo(time: Long) {
- logsDao.deleteTimeAgo(time)
- }
+ //@WorkerThread
+ //fun deleteTimeAgo(time: Long) {
+ // logsDao.deleteTimeAgo(time)
+ //}
@WorkerThread
suspend fun insert(logs: Logs): Long = logsDao.insert(logs)
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/repository/RuleRepository.kt b/app/src/main/java/com/idormy/sms/forwarder/database/repository/RuleRepository.kt
index 9ad0e29d..a0fe270e 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/repository/RuleRepository.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/repository/RuleRepository.kt
@@ -8,7 +8,7 @@ class RuleRepository(
private val ruleDao: RuleDao,
) {
- var listener: Listener? = null
+ private var listener: Listener? = null
@WorkerThread
fun insert(rule: Rule) {
@@ -27,7 +27,7 @@ class RuleRepository(
@WorkerThread
fun getOne(id: Long) = ruleDao.getOne(id)
- suspend fun getRuleAndSender(type: String, status: Int, simSlot: String) = ruleDao.getRuleAndSender(type, status, simSlot)
+ //suspend fun getRuleAndSender(type: String, status: Int, simSlot: String) = ruleDao.getRuleAndSender(type, status, simSlot)
fun getRuleList(type: String, status: Int, simSlot: String) = ruleDao.getRuleList(type, status, simSlot)
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/repository/SenderRepository.kt b/app/src/main/java/com/idormy/sms/forwarder/database/repository/SenderRepository.kt
index ef8301cf..32d766b8 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/repository/SenderRepository.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/repository/SenderRepository.kt
@@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
class SenderRepository(private val senderDao: SenderDao) {
- var listener: Listener? = null
+ private var listener: Listener? = null
@WorkerThread
fun insert(sender: Sender) = senderDao.insert(sender)
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/ClientFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/ClientFragment.kt
index d4bd6656..ef3422d6 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/ClientFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/ClientFragment.kt
@@ -38,7 +38,7 @@ import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.data.ConvertTools
-@Suppress("PrivatePropertyName", "PropertyName")
+@Suppress("PropertyName")
@Page(name = "主动控制·客户端")
class ClientFragment : BaseFragment(), View.OnClickListener, RecyclerViewHolder.OnItemClickListener {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcEditFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcEditFragment.kt
index 8e7ceb50..8ed3543a 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcEditFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcEditFragment.kt
@@ -27,7 +27,7 @@ import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
-@Suppress("PrivatePropertyName", "DEPRECATION")
+@Suppress("DEPRECATION")
@Page(name = "Frp内网穿透·编辑配置")
class FrpcEditFragment : BaseFragment() {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt
index 66736e63..60d93c26 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt
@@ -38,7 +38,6 @@ import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-
@Suppress("DEPRECATION")
@Page(name = "Frp内网穿透")
class FrpcFragment : BaseFragment(), FrpcPagingAdapter.OnItemClickListener {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/LogcatFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/LogcatFragment.kt
index 6fc2f37a..4466e083 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/LogcatFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/LogcatFragment.kt
@@ -1,109 +1,108 @@
-package com.idormy.sms.forwarder.fragment
-
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import com.idormy.sms.forwarder.R
-import com.idormy.sms.forwarder.core.BaseFragment
-import com.idormy.sms.forwarder.databinding.FragmentLogcatBinding
-import com.idormy.sms.forwarder.utils.XToastUtils
-import com.xuexiang.xaop.annotation.SingleClick
-import com.xuexiang.xpage.annotation.Page
-import com.xuexiang.xui.utils.ThemeUtils
-import com.xuexiang.xui.widget.actionbar.TitleBar
-import com.xuexiang.xutil.system.ClipboardUtils
-import io.reactivex.Observable
-import io.reactivex.ObservableEmitter
-import io.reactivex.Observer
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.disposables.Disposable
-import io.reactivex.schedulers.Schedulers
-import java.io.BufferedReader
-import java.io.InputStreamReader
-
-@Suppress("PrivatePropertyName")
-@Page(name = "Logcat")
-class LogcatFragment : BaseFragment() {
-
- override fun viewBindingInflate(
- inflater: LayoutInflater,
- container: ViewGroup,
- ): FragmentLogcatBinding {
- return FragmentLogcatBinding.inflate(inflater, container, false)
- }
-
- override fun initTitle(): TitleBar {
- val titleBar = super.initTitle()!!.setImmersive(false)
- titleBar!!.setTitle(R.string.menu_logcat)
- titleBar.setActionTextColor(ThemeUtils.resolveColor(context, R.attr.colorAccent))
- titleBar.addAction(object : TitleBar.ImageAction(R.drawable.ic_copy) {
- @SingleClick
- override fun performAction(view: View) {
- ClipboardUtils.copyText(binding!!.tvLogcat.text.toString())
- XToastUtils.success(R.string.copySuccess)
- }
- })
- titleBar.addAction(object : TitleBar.ImageAction(R.drawable.ic_delete) {
- @SingleClick
- override fun performAction(view: View) {
- readLog(true)
- binding!!.tvLogcat.text = ""
- }
- })
- return titleBar
- }
-
- override fun initViews() {
- }
-
- override fun initListeners() {
- readLog(false)
- }
-
- private fun readLog(flush: Boolean) {
- val lst: HashSet = LinkedHashSet()
- lst.add("logcat")
- lst.add("-d")
- lst.add("-v")
- lst.add("time")
- lst.add("-s")
- lst.add("GoLog,com.idormy.sms.forwarder.ForegroundService,com.idormy.sms.forwarder.server.ServerService")
- Observable.create { emitter: ObservableEmitter ->
- if (flush) {
- val lst2: HashSet = LinkedHashSet()
- lst2.add("logcat")
- lst2.add("-c")
- val process = Runtime.getRuntime().exec(lst2.toTypedArray())
- process.waitFor()
- }
- val process = Runtime.getRuntime().exec(lst.toTypedArray())
- val `in` = InputStreamReader(process.inputStream)
- val bufferedReader = BufferedReader(`in`)
- var line: String?
- while (bufferedReader.readLine().also { line = it } != null) {
- emitter.onNext(line!!)
- }
- `in`.close()
- bufferedReader.close()
- emitter.onComplete()
- }.subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(object : Observer {
- override fun onSubscribe(d: Disposable) {}
-
- override fun onNext(s: String) {
- binding!!.tvLogcat.append(s)
- binding!!.tvLogcat.append("\r\n")
- binding!!.svLogcat.fullScroll(View.FOCUS_DOWN)
- }
-
- override fun onError(e: Throwable) {
- e.printStackTrace()
- }
-
- override fun onComplete() {}
-
- })
- }
-
+package com.idormy.sms.forwarder.fragment
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.idormy.sms.forwarder.R
+import com.idormy.sms.forwarder.core.BaseFragment
+import com.idormy.sms.forwarder.databinding.FragmentLogcatBinding
+import com.idormy.sms.forwarder.utils.XToastUtils
+import com.xuexiang.xaop.annotation.SingleClick
+import com.xuexiang.xpage.annotation.Page
+import com.xuexiang.xui.utils.ThemeUtils
+import com.xuexiang.xui.widget.actionbar.TitleBar
+import com.xuexiang.xutil.system.ClipboardUtils
+import io.reactivex.Observable
+import io.reactivex.ObservableEmitter
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import java.io.BufferedReader
+import java.io.InputStreamReader
+
+@Page(name = "Logcat")
+class LogcatFragment : BaseFragment() {
+
+ override fun viewBindingInflate(
+ inflater: LayoutInflater,
+ container: ViewGroup,
+ ): FragmentLogcatBinding {
+ return FragmentLogcatBinding.inflate(inflater, container, false)
+ }
+
+ override fun initTitle(): TitleBar {
+ val titleBar = super.initTitle()!!.setImmersive(false)
+ titleBar!!.setTitle(R.string.menu_logcat)
+ titleBar.setActionTextColor(ThemeUtils.resolveColor(context, R.attr.colorAccent))
+ titleBar.addAction(object : TitleBar.ImageAction(R.drawable.ic_copy) {
+ @SingleClick
+ override fun performAction(view: View) {
+ ClipboardUtils.copyText(binding!!.tvLogcat.text.toString())
+ XToastUtils.success(R.string.copySuccess)
+ }
+ })
+ titleBar.addAction(object : TitleBar.ImageAction(R.drawable.ic_delete) {
+ @SingleClick
+ override fun performAction(view: View) {
+ readLog(true)
+ binding!!.tvLogcat.text = ""
+ }
+ })
+ return titleBar
+ }
+
+ override fun initViews() {
+ }
+
+ override fun initListeners() {
+ readLog(false)
+ }
+
+ private fun readLog(flush: Boolean) {
+ val lst: HashSet = LinkedHashSet()
+ lst.add("logcat")
+ lst.add("-d")
+ lst.add("-v")
+ lst.add("time")
+ lst.add("-s")
+ lst.add("GoLog,com.idormy.sms.forwarder.ForegroundService,com.idormy.sms.forwarder.server.ServerService")
+ Observable.create { emitter: ObservableEmitter ->
+ if (flush) {
+ val lst2: HashSet = LinkedHashSet()
+ lst2.add("logcat")
+ lst2.add("-c")
+ val process = Runtime.getRuntime().exec(lst2.toTypedArray())
+ process.waitFor()
+ }
+ val process = Runtime.getRuntime().exec(lst.toTypedArray())
+ val `in` = InputStreamReader(process.inputStream)
+ val bufferedReader = BufferedReader(`in`)
+ var line: String?
+ while (bufferedReader.readLine().also { line = it } != null) {
+ emitter.onNext(line!!)
+ }
+ `in`.close()
+ bufferedReader.close()
+ emitter.onComplete()
+ }.subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(object : Observer {
+ override fun onSubscribe(d: Disposable) {}
+
+ override fun onNext(s: String) {
+ binding!!.tvLogcat.append(s)
+ binding!!.tvLogcat.append("\r\n")
+ binding!!.svLogcat.fullScroll(View.FOCUS_DOWN)
+ }
+
+ override fun onError(e: Throwable) {
+ e.printStackTrace()
+ }
+
+ override fun onComplete() {}
+
+ })
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt
index f28199c4..7ee890e6 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt
@@ -35,8 +35,6 @@ import java.io.File
import java.net.InetAddress
import java.security.KeyPairGenerator
-
-@Suppress("PrivatePropertyName")
@Page(name = "主动控制·服务端")
class ServerFragment : BaseFragment(), View.OnClickListener {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/client/CloneFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/client/CloneFragment.kt
index 5eeb3b4b..ae9a7abc 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/client/CloneFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/client/CloneFragment.kt
@@ -42,7 +42,6 @@ import com.xuexiang.xutil.file.FileUtils
import java.io.File
import java.util.*
-
@Suppress("PropertyName")
@Page(name = "一键换新机")
class CloneFragment : BaseFragment(), View.OnClickListener {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/client/ContactQueryFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/client/ContactQueryFragment.kt
index cccd5273..13400972 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/client/ContactQueryFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/client/ContactQueryFragment.kt
@@ -40,7 +40,6 @@ import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.system.ClipboardUtils
import me.samlss.broccoli.Broccoli
-
@Suppress("PropertyName")
@Page(name = "远程查话簿")
class ContactQueryFragment : BaseFragment() {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/client/SmsQueryFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/client/SmsQueryFragment.kt
index 51d5b8f1..c8ad2173 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/client/SmsQueryFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/client/SmsQueryFragment.kt
@@ -41,7 +41,6 @@ import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.data.DateUtils
import me.samlss.broccoli.Broccoli
-
@Suppress("PropertyName")
@Page(name = "远程查短信")
class SmsQueryFragment : BaseFragment() {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt
index c188826f..55da41a4 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt
@@ -29,7 +29,7 @@ import java.util.*
//短信广播
@OptIn(DelicateCoroutinesApi::class)
-@Suppress("PrivatePropertyName", "DEPRECATION", "DeferredResultUnused", "SENSELESS_COMPARISON")
+@Suppress("PrivatePropertyName", "DeferredResultUnused", "SENSELESS_COMPARISON")
class SmsReceiver : BroadcastReceiver() {
private var TAG = "SmsReceiver"
diff --git a/app/src/main/java/com/idormy/sms/forwarder/server/component/AppMessageConverter.kt b/app/src/main/java/com/idormy/sms/forwarder/server/component/AppMessageConverter.kt
index cd58af6d..5edd759b 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/server/component/AppMessageConverter.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/server/component/AppMessageConverter.kt
@@ -22,7 +22,6 @@ import java.io.InputStream
import java.lang.reflect.Type
import java.nio.charset.Charset
-
@Suppress("PrivatePropertyName")
@Converter
class AppMessageConverter : MessageConverter {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/server/controller/LocationController.kt b/app/src/main/java/com/idormy/sms/forwarder/server/controller/LocationController.kt
index dfbeba0b..824ac025 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/server/controller/LocationController.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/server/controller/LocationController.kt
@@ -10,7 +10,7 @@ import com.yanzhenjie.andserver.annotation.*
import java.util.*
@SuppressLint("SimpleDateFormat")
-@Suppress("PrivatePropertyName", "DEPRECATION")
+@Suppress("PrivatePropertyName")
@RestController
@RequestMapping(path = ["/location"])
class LocationController {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt
index 325f6686..8da15afc 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt
@@ -31,7 +31,7 @@ import kotlinx.coroutines.async
import java.util.*
@OptIn(DelicateCoroutinesApi::class)
-@Suppress("DEPRECATION", "DeferredResultUnused")
+@Suppress("DeferredResultUnused")
class BatteryService : Service() {
override fun onBind(intent: Intent): IBinder? {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt
index e362a2dc..f51dac83 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt
@@ -22,7 +22,7 @@ import com.xuexiang.xutil.app.ServiceUtils
import com.xuexiang.xutil.net.NetworkUtils
import java.util.*
-@Suppress("DEPRECATION", "DeferredResultUnused")
+@Suppress("DEPRECATION")
class NetworkStateService : Service() {
override fun onBind(intent: Intent): IBinder? {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/CertUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/CertUtils.kt
deleted file mode 100644
index 89422181..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/CertUtils.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.idormy.sms.forwarder.utils
-
-import android.annotation.SuppressLint
-import java.security.KeyStore
-import java.security.SecureRandom
-import java.security.cert.X509Certificate
-import java.util.*
-import javax.net.ssl.*
-
-@Suppress("unused")
-@SuppressLint("ALL")
-object CertUtils {
-
- //获取这个SSLSocketFactory
- val sSLSocketFactory: SSLSocketFactory
- get() = try {
- val sslContext = SSLContext.getInstance("SSL")
- sslContext.init(null, trustManager, SecureRandom())
- sslContext.socketFactory
- } catch (e: Exception) {
- throw RuntimeException(e)
- }
-
- //获取TrustManager
- private val trustManager: Array
- get() = arrayOf(
- object : X509TrustManager {
- override fun checkClientTrusted(chain: Array, authType: String) {}
- override fun checkServerTrusted(chain: Array, authType: String) {}
- override fun getAcceptedIssuers(): Array {
- return arrayOf()
- }
- }
- )
-
- //获取HostnameVerifier
- val hostnameVerifier: HostnameVerifier
- get() = HostnameVerifier { _: String?, _: SSLSession? -> true }
- val x509TrustManager: X509TrustManager?
- get() {
- var trustManager: X509TrustManager? = null
- try {
- val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
- trustManagerFactory.init(null as KeyStore?)
- val trustManagers = trustManagerFactory.trustManagers
- check(!(trustManagers.size != 1 || trustManagers[0] !is X509TrustManager)) { "Unexpected default trust managers:" + Arrays.toString(trustManagers) }
- trustManager = trustManagers[0] as X509TrustManager
- } catch (e: Exception) {
- e.printStackTrace()
- }
- return trustManager
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/DataProvider.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/DataProvider.kt
index 1a0ca8f5..61beb63d 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/DataProvider.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/DataProvider.kt
@@ -1,74 +1,73 @@
-package com.idormy.sms.forwarder.utils
-
-import com.idormy.sms.forwarder.entity.CallInfo
-import com.idormy.sms.forwarder.entity.ContactInfo
-import com.idormy.sms.forwarder.entity.SmsInfo
-import com.xuexiang.xaop.annotation.MemoryCache
-
-object DataProvider {
-
- //用于占位的空信息
- @JvmStatic
- @get:MemoryCache
- val emptySmsInfo: List
- get() {
- val list: MutableList = ArrayList()
- for (i in 0..5) {
- list.add(SmsInfo())
- }
- return list
- }
-
- //用于占位的空信息
- @JvmStatic
- @get:MemoryCache
- val emptyCallInfo: List
- get() {
- val list: MutableList = ArrayList()
- for (i in 0..5) {
- list.add(CallInfo())
- }
- return list
- }
-
- //用于占位的空信息
- @JvmStatic
- @get:MemoryCache
- val emptyContactInfo: List
- get() {
- val list: MutableList = ArrayList()
- for (i in 0..5) {
- list.add(ContactInfo())
- }
- return list
- }
-
- //获取时间段
- @JvmStatic
- @get:MemoryCache
- val timePeriodOption: List
- get() {
- return getTimePeriod(24, 10) //修改时请注意会不会造成旧版下标越界
- }
-
- /**
- * 获取时间段
- *
- * @param interval 时间间隔(分钟)
- * @return
- */
- @Suppress("UNCHECKED_CAST")
- fun getTimePeriod(totalHour: Int, interval: Int): List {
- val list: MutableList = ArrayList()
- var point: Int
- var hour: Int
- var min: Int
- for (i in 0..totalHour * 60 / interval) {
- point = i * interval
- hour = point / 60
- min = point - hour * 60
- list.add((if (hour <= 9) "0$hour" else "" + hour) + ":" + if (min <= 9) "0$min" else "" + min)
- }
- return list
- }
+package com.idormy.sms.forwarder.utils
+
+import com.idormy.sms.forwarder.entity.CallInfo
+import com.idormy.sms.forwarder.entity.ContactInfo
+import com.idormy.sms.forwarder.entity.SmsInfo
+import com.xuexiang.xaop.annotation.MemoryCache
+
+object DataProvider {
+
+ //用于占位的空信息
+ @JvmStatic
+ @get:MemoryCache
+ val emptySmsInfo: List
+ get() {
+ val list: MutableList = ArrayList()
+ for (i in 0..5) {
+ list.add(SmsInfo())
+ }
+ return list
+ }
+
+ //用于占位的空信息
+ @JvmStatic
+ @get:MemoryCache
+ val emptyCallInfo: List
+ get() {
+ val list: MutableList = ArrayList()
+ for (i in 0..5) {
+ list.add(CallInfo())
+ }
+ return list
+ }
+
+ //用于占位的空信息
+ @JvmStatic
+ @get:MemoryCache
+ val emptyContactInfo: List
+ get() {
+ val list: MutableList = ArrayList()
+ for (i in 0..5) {
+ list.add(ContactInfo())
+ }
+ return list
+ }
+
+ //获取时间段
+ @JvmStatic
+ @get:MemoryCache
+ val timePeriodOption: List
+ get() {
+ return getTimePeriod(24, 10) //修改时请注意会不会造成旧版下标越界
+ }
+
+ /**
+ * 获取时间段
+ *
+ * @param interval 时间间隔(分钟)
+ * @return
+ */
+ private fun getTimePeriod(totalHour: Int, interval: Int): List {
+ val list: MutableList = ArrayList()
+ var point: Int
+ var hour: Int
+ var min: Int
+ for (i in 0..totalHour * 60 / interval) {
+ point = i * interval
+ hour = point / 60
+ min = point - hour * 60
+ list.add((if (hour <= 9) "0$hour" else "" + hour) + ":" + if (min <= 9) "0$min" else "" + min)
+ }
+ return list
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/HistoryUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/HistoryUtils.kt
index bd2b4d93..33de9ce1 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/HistoryUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/HistoryUtils.kt
@@ -13,7 +13,7 @@ import kotlin.reflect.KProperty
* @author pppscn
* @since 2022年5月9日
*/
-@Suppress("PropertyName", "UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused")
+@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused")
class HistoryUtils(private val name: String, private val default: T) : ReadWriteProperty {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/Logger.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/Logger.kt
deleted file mode 100644
index 745a6577..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/Logger.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2018 Zhenjie Yan.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.idormy.sms.forwarder.utils
-
-import android.util.Log
-
-/**
- * Created by Zhenjie Yan on 2018/9/12.
- */
-@Suppress("unused")
-object Logger {
- private const val TAG = "AndServer"
- private const val DEBUG = true
- fun i(obj: Any?) {
- if (DEBUG) {
- Log.i(TAG, obj?.toString() ?: "null")
- }
- }
-
- fun d(obj: Any?) {
- if (DEBUG) {
- Log.d(TAG, obj?.toString() ?: "null")
- }
- }
-
- fun v(obj: Any?) {
- if (DEBUG) {
- Log.v(TAG, obj?.toString() ?: "null")
- }
- }
-
- fun w(obj: Any?) {
- if (DEBUG) {
- Log.w(TAG, obj?.toString() ?: "null")
- }
- }
-
- fun e(obj: Any?) {
- if (DEBUG) {
- Log.e(TAG, obj?.toString() ?: "null")
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/NetUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/NetUtils.kt
deleted file mode 100644
index cf412385..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/NetUtils.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright © 2018 Zhenjie Yan.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.idormy.sms.forwarder.utils
-
-import java.net.InetAddress
-import java.net.NetworkInterface
-import java.net.SocketException
-import java.util.*
-import java.util.regex.Pattern
-
-/**
- * Created by Zhenjie Yan on 2018/6/9.
- */
-@Suppress("unused")
-object NetUtils {
- /**
- * Ipv4 address check.
- */
- private val IPV4_PATTERN = Pattern.compile(
- "^(" + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" +
- "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
- )
-
- /**
- * Check if valid IPV4 address.
- *
- * @param input the address string to check for validity.
- * @return True if the input parameter is a valid IPv4 address.
- */
- private fun isIPv4Address(input: String?): Boolean {
- return IPV4_PATTERN.matcher(input.toString()).matches()
- }
-
- /**
- * Get local Ip address.
- */
- val localIPAddress: InetAddress?
- get() {
- var enumeration: Enumeration? = null
- try {
- enumeration = NetworkInterface.getNetworkInterfaces()
- } catch (e: SocketException) {
- e.printStackTrace()
- }
- if (enumeration != null) {
- while (enumeration.hasMoreElements()) {
- val nif = enumeration.nextElement()
- val inetAddresses = nif.inetAddresses
- if (inetAddresses != null) {
- while (inetAddresses.hasMoreElements()) {
- val inetAddress = inetAddresses.nextElement()
- if (!inetAddress.isLoopbackAddress && isIPv4Address(inetAddress.hostAddress)) {
- return inetAddress
- }
- }
- }
- }
- }
- return null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/PrefsHelper.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/PrefsHelper.kt
deleted file mode 100644
index e2e41db1..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/PrefsHelper.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-@file:Suppress("DEPRECATION")
-
-package com.idormy.sms.forwarder.utils
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.preference.PreferenceManager
-
-/**
- * Created by aykutasil on 8.12.2016.
- */
-
-@Suppress("unused")
-class PrefsHelper private constructor() {
-
- lateinit var preference: SharedPreferences
-
- val prefEditor: SharedPreferences.Editor
- get() = preference.edit()
-
- constructor(context: Context, prefName: String) : this() {
- preference = context.getSharedPreferences(prefName, Context.MODE_PRIVATE)
- }
-
- constructor(context: Context) : this() {
- preference = getDefaultPreference(context)
- }
-
- companion object {
-
- private val DEFAULT_STRING_VALUE: String? = null
- private const val DEFAULT_INT_VALUE = 0
- private const val DEFAULT_BOOLEAN_VALUE = false
-
- fun getDefaultPreference(context: Context): SharedPreferences {
- return PreferenceManager.getDefaultSharedPreferences(context)
- }
-
- fun writePrefString(context: Context, key: String, value: String?) {
- PrefsHelper(context).prefEditor.putString(key, value).commit()
- }
-
- fun readPrefString(context: Context, key: String): String? {
- return PrefsHelper(context).preference.getString(key, DEFAULT_STRING_VALUE)
- }
-
- fun writePrefInt(context: Context, key: String, value: Int) {
- PrefsHelper(context).prefEditor.putInt(key, value).commit()
- }
-
- fun readPrefInt(context: Context, key: String): Int {
- return PrefsHelper(context).preference.getInt(key, DEFAULT_INT_VALUE)
- }
-
- fun writePrefBool(context: Context, key: String, value: Boolean) {
- PrefsHelper(context).prefEditor.putBoolean(key, value).commit()
- }
-
- fun readPrefBool(context: Context, key: String): Boolean {
- return PrefsHelper(context).preference.getBoolean(key, DEFAULT_BOOLEAN_VALUE)
- }
-
- fun clearPreference(context: Context) {
- PrefsHelper(context).preference.edit().clear().apply()
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt
index d9d4f441..c9e2f4b5 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt
@@ -7,7 +7,7 @@ class SettingUtils private constructor() {
companion object {
//是否是第一次启动
- var isFirstOpen: Boolean by SharedPreference(IS_FIRST_OPEN_KEY, true)
+ //var isFirstOpen: Boolean by SharedPreference(IS_FIRST_OPEN_KEY, true)
//是否同意隐私政策
var isAgreePrivacy: Boolean by SharedPreference(IS_AGREE_PRIVACY_KEY, false)
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sdkinit/UMengInit.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sdkinit/UMengInit.kt
index 52d90dc7..5a98280d 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sdkinit/UMengInit.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sdkinit/UMengInit.kt
@@ -74,9 +74,6 @@ class UMengInit private constructor() {
/**
* 获取渠道信息
- *
- * @param context
- * @return
*/
private fun getChannel(): String { //context: Context?
//return WalleChannelReader.getChannel(context!!, DEFAULT_CHANNEL_ID)
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/BarkUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/BarkUtils.kt
index 06f7d875..1c161e40 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/BarkUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/BarkUtils.kt
@@ -15,7 +15,6 @@ import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import java.util.regex.Pattern
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class BarkUtils {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkGroupRobotUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkGroupRobotUtils.kt
index debcb5ae..82f8c1cd 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkGroupRobotUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkGroupRobotUtils.kt
@@ -20,7 +20,6 @@ import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
//钉钉群自定义机器人
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class DingtalkGroupRobotUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkInnerRobotUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkInnerRobotUtils.kt
index 35fe30e2..9708b032 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkInnerRobotUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/DingtalkInnerRobotUtils.kt
@@ -26,7 +26,6 @@ import java.net.PasswordAuthentication
import java.net.Proxy
//钉钉企业内机器人
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class DingtalkInnerRobotUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/EmailUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/EmailUtils.kt
index 5b06a80c..b999242c 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/EmailUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/EmailUtils.kt
@@ -11,11 +11,10 @@ import com.idormy.sms.forwarder.utils.mail.Mail
import com.idormy.sms.forwarder.utils.mail.MailSender
import com.xuexiang.xui.utils.ResUtils
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class EmailUtils {
companion object {
- private val TAG: String = EmailUtils::class.java.simpleName
+ //private val TAG: String = EmailUtils::class.java.simpleName
fun sendMsg(
setting: EmailSetting,
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuAppUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuAppUtils.kt
index 588c15af..6b8bee17 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuAppUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuAppUtils.kt
@@ -18,7 +18,6 @@ import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils.getString
//飞书企业应用
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class FeishuAppUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuUtils.kt
index b09a82dd..5c8185cd 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/FeishuUtils.kt
@@ -19,7 +19,6 @@ import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class FeishuUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/GotifyUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/GotifyUtils.kt
index 5a1df0f6..406eea79 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/GotifyUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/GotifyUtils.kt
@@ -13,7 +13,6 @@ import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class GotifyUtils {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/PushplusUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/PushplusUtils.kt
index cd51f139..67d3f98e 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/PushplusUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/PushplusUtils.kt
@@ -16,8 +16,6 @@ import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils
-
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class PushplusUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/ServerchanUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/ServerchanUtils.kt
index c2070913..d292e42c 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/ServerchanUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/ServerchanUtils.kt
@@ -14,7 +14,6 @@ import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class ServerchanUtils {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SmsUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SmsUtils.kt
index e5f49164..1223c6c1 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SmsUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SmsUtils.kt
@@ -16,7 +16,6 @@ import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.net.NetworkUtils
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class SmsUtils {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SocketUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SocketUtils.kt
index 26bb5ea0..807bee29 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SocketUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/SocketUtils.kt
@@ -23,7 +23,6 @@ import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class SocketUtils {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/TelegramUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/TelegramUtils.kt
index a06d2b30..45891adb 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/TelegramUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/TelegramUtils.kt
@@ -19,8 +19,6 @@ import okhttp3.Response
import okhttp3.Route
import java.net.*
-
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class TelegramUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/UrlSchemeUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/UrlSchemeUtils.kt
index f45e1af0..baee6f06 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/UrlSchemeUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/UrlSchemeUtils.kt
@@ -15,8 +15,6 @@ import java.net.URLEncoder
import java.text.SimpleDateFormat
import java.util.*
-
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class UrlSchemeUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WebhookUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WebhookUtils.kt
index 73e95520..51db1bba 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WebhookUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WebhookUtils.kt
@@ -22,7 +22,6 @@ import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class WebhookUtils {
companion object {
@@ -114,7 +113,7 @@ class WebhookUtils {
}
Log.d(TAG, "method = GET, Url = $requestUrl")
XHttp.get(requestUrl).keepJson(true)
- } else if (webParams != null && webParams.isNotEmpty() && webParams.startsWith("{")) {
+ } else if (!webParams.isNullOrEmpty() && webParams.startsWith("{")) {
val bodyMsg = webParams.replace("[from]", from)
.replace("[content]", escapeJson(content))
.replace("[msg]", escapeJson(content))
@@ -133,7 +132,7 @@ class WebhookUtils {
else -> XHttp.post(requestUrl).keepJson(true).upJson(bodyMsg)
}
} else {
- if (webParams == null || webParams.isEmpty()) {
+ if (webParams.isNullOrEmpty()) {
webParams = "from=[from]&content=[content]×tamp=[timestamp]"
if (!TextUtils.isEmpty(sign)) webParams += "&sign=[sign]"
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WeworkAgentUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WeworkAgentUtils.kt
index 8219a5ca..ca21e791 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WeworkAgentUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/sender/WeworkAgentUtils.kt
@@ -26,7 +26,6 @@ import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
-@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class WeworkAgentUtils private constructor() {
companion object {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/service/JsonSerializationService.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/service/JsonSerializationService.kt
deleted file mode 100644
index 42fabe2b..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/service/JsonSerializationService.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.idormy.sms.forwarder.utils.service
-
-import android.content.Context
-import com.xuexiang.xrouter.annotation.Router
-import com.xuexiang.xrouter.facade.service.SerializationService
-import com.xuexiang.xutil.net.JsonUtil
-import java.lang.reflect.Type
-
-/**
- * @author XUE
- * @since 2019/3/27 16:39
- */
-@Router(path = "/service/json")
-class JsonSerializationService : SerializationService {
- /**
- * 对象序列化为json
- *
- * @param instance obj
- * @return json string
- */
- override fun object2Json(instance: Any): String {
- return JsonUtil.toJson(instance)
- }
-
- /**
- * json反序列化为对象
- *
- * @param input json string
- * @param clazz object type
- * @return instance of object
- */
- override fun parseObject(input: String, clazz: Type): T {
- return JsonUtil.fromJson(input, clazz)
- }
-
- /**
- * 进程初始化的方法
- *
- * @param context 上下文
- */
- override fun init(context: Context) {}
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/tinker/ShareReflectUtil.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/tinker/ShareReflectUtil.kt
index a1bc3e17..319982fd 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/tinker/ShareReflectUtil.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/tinker/ShareReflectUtil.kt
@@ -1,240 +1,240 @@
-package com.idormy.sms.forwarder.utils.tinker
-
-import android.annotation.SuppressLint
-import android.content.Context
-import java.lang.reflect.Constructor
-import java.lang.reflect.Field
-import java.lang.reflect.Method
-
-@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS", "UNCHECKED_CAST", "SENSELESS_COMPARISON", "unused")
-object ShareReflectUtil {
- /**
- * Locates a given field anywhere in the class inheritance hierarchy.
- *
- * @param instance an object to search the field into.
- * @param name field name
- * @return a field object
- * @throws NoSuchFieldException if the field cannot be located
- */
- @Throws(NoSuchFieldException::class)
- fun findField(instance: Any, name: String): Field {
- var clazz: Class<*>? = instance.javaClass
- while (clazz != null) {
- try {
- val field = clazz.getDeclaredField(name)
- if (!field.isAccessible) {
- field.isAccessible = true
- }
- return field
- } catch (e: NoSuchFieldException) {
- // ignore and search next
- }
- clazz = clazz.superclass
- }
- throw NoSuchFieldException("Field " + name + " not found in " + instance.javaClass)
- }
-
- @Throws(NoSuchFieldException::class)
- fun findField(originClazz: Class<*>, name: String): Field {
- var clazz: Class<*>? = originClazz
- while (clazz != null) {
- try {
- val field = clazz.getDeclaredField(name)
- if (!field.isAccessible) {
- field.isAccessible = true
- }
- return field
- } catch (e: NoSuchFieldException) {
- // ignore and search next
- }
- clazz = clazz.superclass
- }
- throw NoSuchFieldException("Field $name not found in $originClazz")
- }
-
- /**
- * Locates a given method anywhere in the class inheritance hierarchy.
- *
- * @param instance an object to search the method into.
- * @param name method name
- * @param parameterTypes method parameter types
- * @return a method object
- * @throws NoSuchMethodException if the method cannot be located
- */
- @Throws(NoSuchMethodException::class)
- fun findMethod(instance: Any, name: String, vararg parameterTypes: Class<*>?): Method {
- var clazz: Class<*>? = instance.javaClass
- while (clazz != null) {
- try {
- val method = clazz.getDeclaredMethod(name, *parameterTypes)
- if (!method.isAccessible) {
- method.isAccessible = true
- }
- return method
- } catch (e: NoSuchMethodException) {
- // ignore and search next
- }
- clazz = clazz.superclass
- }
- throw NoSuchMethodException(
- "Method "
- + name
- + " with parameters "
- + listOf(*parameterTypes)
- + " not found in " + instance.javaClass
- )
- }
-
- /**
- * Locates a given method anywhere in the class inheritance hierarchy.
- *
- * @param clazz a class to search the method into.
- * @param name method name
- * @param parameterTypes method parameter types
- * @return a method object
- * @throws NoSuchMethodException if the method cannot be located
- */
- @Throws(NoSuchMethodException::class)
- fun findMethod(clazz: Class<*>?, name: String, vararg parameterTypes: Class<*>?): Method {
- var tClazz = clazz
- while (tClazz != null) {
- try {
- val method = tClazz.getDeclaredMethod(name, *parameterTypes)
- if (!method.isAccessible) {
- method.isAccessible = true
- }
- return method
- } catch (e: NoSuchMethodException) {
- // ignore and search next
- }
- tClazz = tClazz.superclass
- }
- throw NoSuchMethodException(
- "Method "
- + name
- + " with parameters "
- + listOf(*parameterTypes)
- + " not found in " + tClazz
- )
- }
-
- /**
- * Locates a given constructor anywhere in the class inheritance hierarchy.
- *
- * @param instance an object to search the constructor into.
- * @param parameterTypes constructor parameter types
- * @return a constructor object
- * @throws NoSuchMethodException if the constructor cannot be located
- */
- @Throws(NoSuchMethodException::class)
- fun findConstructor(instance: Any, vararg parameterTypes: Class<*>?): Constructor<*> {
- var clazz: Class<*>? = instance.javaClass
- while (clazz != null) {
- try {
- val constructor = clazz.getDeclaredConstructor(*parameterTypes)
- if (!constructor.isAccessible) {
- constructor.isAccessible = true
- }
- return constructor
- } catch (e: NoSuchMethodException) {
- // ignore and search next
- }
- clazz = clazz.superclass
- }
- throw NoSuchMethodException(
- "Constructor"
- + " with parameters "
- + listOf(*parameterTypes)
- + " not found in " + instance.javaClass
- )
- }
-
- /**
- * Replace the value of a field containing a non null array, by a new array containing the
- * elements of the original array plus the elements of extraElements.
- *
- * @param instance the instance whose field is to be modified.
- * @param fieldName the field to modify.
- * @param extraElements elements to append at the end of the array.
- */
- @Throws(NoSuchFieldException::class, IllegalArgumentException::class, IllegalAccessException::class)
- fun expandFieldArray(instance: Any, fieldName: String, extraElements: Array) {
- val jlrField = findField(instance, fieldName)
- val original = jlrField[instance] as Array
- val combined = java.lang.reflect.Array.newInstance(original.javaClass.componentType, original.size + extraElements.size) as Array
-
- // NOTE: changed to copy extraElements first, for patch load first
- System.arraycopy(extraElements, 0, combined, 0, extraElements.size)
- System.arraycopy(original, 0, combined, extraElements.size, original.size)
- jlrField[instance] = combined
- }
-
- /**
- * Replace the value of a field containing a non null array, by a new array containing the
- * elements of the original array plus the elements of extraElements.
- *
- * @param instance the instance whose field is to be modified.
- * @param fieldName the field to modify.
- */
- @Throws(NoSuchFieldException::class, IllegalArgumentException::class, IllegalAccessException::class)
- fun reduceFieldArray(instance: Any, fieldName: String, reduceSize: Int) {
- if (reduceSize <= 0) {
- return
- }
- val jlrField = findField(instance, fieldName)
- val original = jlrField[instance] as Array
- val finalLength = original.size - reduceSize
- if (finalLength <= 0) {
- return
- }
- val combined = java.lang.reflect.Array.newInstance(original.javaClass.componentType, finalLength) as Array
- System.arraycopy(original, reduceSize, combined, 0, finalLength)
- jlrField[instance] = combined
- }
-
- @SuppressLint("PrivateApi")
- fun getActivityThread(
- context: Context?,
- activityThread: Class<*>?,
- ): Any? {
- var tActivityThread = activityThread
- return try {
- if (tActivityThread == null) {
- tActivityThread = Class.forName("android.app.ActivityThread")
- }
- val m = tActivityThread!!.getMethod("currentActivityThread")
- m.isAccessible = true
- var currentActivityThread = m.invoke(null)
- if (currentActivityThread == null && context != null) {
- // In older versions of Android (prior to frameworks/base 66a017b63461a22842)
- // the currentActivityThread was built on thread locals, so we'll need to try
- // even harder
- val mLoadedApk = context.javaClass.getField("mLoadedApk")
- mLoadedApk.isAccessible = true
- val apk = mLoadedApk[context]
- val mActivityThreadField = apk.javaClass.getDeclaredField("mActivityThread")
- mActivityThreadField.isAccessible = true
- currentActivityThread = mActivityThreadField[apk]
- }
- currentActivityThread
- } catch (ignore: Throwable) {
- null
- }
- }
-
- /**
- * Handy method for fetching hidden integer constant value in system classes.
- *
- * @param clazz
- * @param fieldName
- * @return
- */
- fun getValueOfStaticIntField(clazz: Class<*>, fieldName: String, defVal: Int): Int {
- return try {
- val field = findField(clazz, fieldName)
- field.getInt(null)
- } catch (thr: Throwable) {
- defVal
- }
- }
+package com.idormy.sms.forwarder.utils.tinker
+
+import android.annotation.SuppressLint
+import android.content.Context
+import java.lang.reflect.Constructor
+import java.lang.reflect.Field
+import java.lang.reflect.Method
+
+@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS", "UNCHECKED_CAST", "unused")
+object ShareReflectUtil {
+ /**
+ * Locates a given field anywhere in the class inheritance hierarchy.
+ *
+ * @param instance an object to search the field into.
+ * @param name field name
+ * @return a field object
+ * @throws NoSuchFieldException if the field cannot be located
+ */
+ @Throws(NoSuchFieldException::class)
+ fun findField(instance: Any, name: String): Field {
+ var clazz: Class<*>? = instance.javaClass
+ while (clazz != null) {
+ try {
+ val field = clazz.getDeclaredField(name)
+ if (!field.isAccessible) {
+ field.isAccessible = true
+ }
+ return field
+ } catch (e: NoSuchFieldException) {
+ // ignore and search next
+ }
+ clazz = clazz.superclass
+ }
+ throw NoSuchFieldException("Field " + name + " not found in " + instance.javaClass)
+ }
+
+ @Throws(NoSuchFieldException::class)
+ fun findField(originClazz: Class<*>, name: String): Field {
+ var clazz: Class<*>? = originClazz
+ while (clazz != null) {
+ try {
+ val field = clazz.getDeclaredField(name)
+ if (!field.isAccessible) {
+ field.isAccessible = true
+ }
+ return field
+ } catch (e: NoSuchFieldException) {
+ // ignore and search next
+ }
+ clazz = clazz.superclass
+ }
+ throw NoSuchFieldException("Field $name not found in $originClazz")
+ }
+
+ /**
+ * Locates a given method anywhere in the class inheritance hierarchy.
+ *
+ * @param instance an object to search the method into.
+ * @param name method name
+ * @param parameterTypes method parameter types
+ * @return a method object
+ * @throws NoSuchMethodException if the method cannot be located
+ */
+ @Throws(NoSuchMethodException::class)
+ fun findMethod(instance: Any, name: String, vararg parameterTypes: Class<*>?): Method {
+ var clazz: Class<*>? = instance.javaClass
+ while (clazz != null) {
+ try {
+ val method = clazz.getDeclaredMethod(name, *parameterTypes)
+ if (!method.isAccessible) {
+ method.isAccessible = true
+ }
+ return method
+ } catch (e: NoSuchMethodException) {
+ // ignore and search next
+ }
+ clazz = clazz.superclass
+ }
+ throw NoSuchMethodException(
+ "Method "
+ + name
+ + " with parameters "
+ + listOf(*parameterTypes)
+ + " not found in " + instance.javaClass
+ )
+ }
+
+ /**
+ * Locates a given method anywhere in the class inheritance hierarchy.
+ *
+ * @param clazz a class to search the method into.
+ * @param name method name
+ * @param parameterTypes method parameter types
+ * @return a method object
+ * @throws NoSuchMethodException if the method cannot be located
+ */
+ @Throws(NoSuchMethodException::class)
+ fun findMethod(clazz: Class<*>?, name: String, vararg parameterTypes: Class<*>?): Method {
+ var tClazz = clazz
+ while (tClazz != null) {
+ try {
+ val method = tClazz.getDeclaredMethod(name, *parameterTypes)
+ if (!method.isAccessible) {
+ method.isAccessible = true
+ }
+ return method
+ } catch (e: NoSuchMethodException) {
+ // ignore and search next
+ }
+ tClazz = tClazz.superclass
+ }
+ throw NoSuchMethodException(
+ "Method "
+ + name
+ + " with parameters "
+ + listOf(*parameterTypes)
+ + " not found in " + tClazz
+ )
+ }
+
+ /**
+ * Locates a given constructor anywhere in the class inheritance hierarchy.
+ *
+ * @param instance an object to search the constructor into.
+ * @param parameterTypes constructor parameter types
+ * @return a constructor object
+ * @throws NoSuchMethodException if the constructor cannot be located
+ */
+ @Throws(NoSuchMethodException::class)
+ fun findConstructor(instance: Any, vararg parameterTypes: Class<*>?): Constructor<*> {
+ var clazz: Class<*>? = instance.javaClass
+ while (clazz != null) {
+ try {
+ val constructor = clazz.getDeclaredConstructor(*parameterTypes)
+ if (!constructor.isAccessible) {
+ constructor.isAccessible = true
+ }
+ return constructor
+ } catch (e: NoSuchMethodException) {
+ // ignore and search next
+ }
+ clazz = clazz.superclass
+ }
+ throw NoSuchMethodException(
+ "Constructor"
+ + " with parameters "
+ + listOf(*parameterTypes)
+ + " not found in " + instance.javaClass
+ )
+ }
+
+ /**
+ * Replace the value of a field containing a non null array, by a new array containing the
+ * elements of the original array plus the elements of extraElements.
+ *
+ * @param instance the instance whose field is to be modified.
+ * @param fieldName the field to modify.
+ * @param extraElements elements to append at the end of the array.
+ */
+ @Throws(NoSuchFieldException::class, IllegalArgumentException::class, IllegalAccessException::class)
+ fun expandFieldArray(instance: Any, fieldName: String, extraElements: Array) {
+ val jlrField = findField(instance, fieldName)
+ val original = jlrField[instance] as Array
+ val combined = java.lang.reflect.Array.newInstance(original.javaClass.componentType, original.size + extraElements.size) as Array
+
+ // NOTE: changed to copy extraElements first, for patch load first
+ System.arraycopy(extraElements, 0, combined, 0, extraElements.size)
+ System.arraycopy(original, 0, combined, extraElements.size, original.size)
+ jlrField[instance] = combined
+ }
+
+ /**
+ * Replace the value of a field containing a non null array, by a new array containing the
+ * elements of the original array plus the elements of extraElements.
+ *
+ * @param instance the instance whose field is to be modified.
+ * @param fieldName the field to modify.
+ */
+ @Throws(NoSuchFieldException::class, IllegalArgumentException::class, IllegalAccessException::class)
+ fun reduceFieldArray(instance: Any, fieldName: String, reduceSize: Int) {
+ if (reduceSize <= 0) {
+ return
+ }
+ val jlrField = findField(instance, fieldName)
+ val original = jlrField[instance] as Array
+ val finalLength = original.size - reduceSize
+ if (finalLength <= 0) {
+ return
+ }
+ val combined = java.lang.reflect.Array.newInstance(original.javaClass.componentType, finalLength) as Array
+ System.arraycopy(original, reduceSize, combined, 0, finalLength)
+ jlrField[instance] = combined
+ }
+
+ @SuppressLint("PrivateApi")
+ fun getActivityThread(
+ context: Context?,
+ activityThread: Class<*>?,
+ ): Any? {
+ var tActivityThread = activityThread
+ return try {
+ if (tActivityThread == null) {
+ tActivityThread = Class.forName("android.app.ActivityThread")
+ }
+ val m = tActivityThread!!.getMethod("currentActivityThread")
+ m.isAccessible = true
+ var currentActivityThread = m.invoke(null)
+ if (currentActivityThread == null && context != null) {
+ // In older versions of Android (prior to frameworks/base 66a017b63461a22842)
+ // the currentActivityThread was built on thread locals, so we'll need to try
+ // even harder
+ val mLoadedApk = context.javaClass.getField("mLoadedApk")
+ mLoadedApk.isAccessible = true
+ val apk = mLoadedApk[context]
+ val mActivityThreadField = apk.javaClass.getDeclaredField("mActivityThread")
+ mActivityThreadField.isAccessible = true
+ currentActivityThread = mActivityThreadField[apk]
+ }
+ currentActivityThread
+ } catch (ignore: Throwable) {
+ null
+ }
+ }
+
+ /**
+ * Handy method for fetching hidden integer constant value in system classes.
+ *
+ * @param clazz
+ * @param fieldName
+ * @return
+ */
+ fun getValueOfStaticIntField(clazz: Class<*>, fieldName: String, defVal: Int): Int {
+ return try {
+ val field = findField(clazz, fieldName)
+ field.getInt(null)
+ } catch (thr: Throwable) {
+ defVal
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/widget/GuideTipsDialog.kt b/app/src/main/java/com/idormy/sms/forwarder/widget/GuideTipsDialog.kt
index e5bff1fa..5c234800 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/widget/GuideTipsDialog.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/widget/GuideTipsDialog.kt
@@ -167,7 +167,7 @@ class GuideTipsDialog(context: Context?, tips: List) :
).tips, object : NoTipCallBack>() {
@Throws(Throwable::class)
override fun onSuccess(response: List?) {
- if (response != null && response.isNotEmpty()) {
+ if (!response.isNullOrEmpty()) {
GuideTipsDialog(context, response).show()
}
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/workers/LoadAppListWorker.kt b/app/src/main/java/com/idormy/sms/forwarder/workers/LoadAppListWorker.kt
index 9be13a4d..6ad9dab1 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/workers/LoadAppListWorker.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/workers/LoadAppListWorker.kt
@@ -39,7 +39,7 @@ class LoadAppListWorker(
LiveEventBus.get(EVENT_LOAD_APP_LIST, String::class.java).post("finish")
App.LoadingAppList = false
- Log.d("LoadAppListWorker", "LoadAppListWorker finish, App.LoadingAppList=${App.LoadingAppList}")
+ Log.d("LoadAppListWorker", "LoadAppListWorker finish")
return@withContext Result.success()
}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 1f6bb290..00000000
--- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 0d025f9b..00000000
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
deleted file mode 100644
index 2b027f9f..00000000
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_login_close.xml b/app/src/main/res/drawable/ic_login_close.xml
deleted file mode 100644
index 71703bf6..00000000
--- a/app/src/main/res/drawable/ic_login_close.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/ic_password.xml b/app/src/main/res/drawable/ic_password.xml
deleted file mode 100644
index 5b4ce70d..00000000
--- a/app/src/main/res/drawable/ic_password.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_phone.xml b/app/src/main/res/drawable/ic_phone.xml
deleted file mode 100644
index 62654143..00000000
--- a/app/src/main/res/drawable/ic_phone.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/app/src/test/java/com/idormy/sms/forwarder/ExampleUnitTest.kt b/app/src/test/java/com/idormy/sms/forwarder/ExampleUnitTest.kt
deleted file mode 100644
index 43adf5b9..00000000
--- a/app/src/test/java/com/idormy/sms/forwarder/ExampleUnitTest.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.idormy.sms.forwarder
-
-import com.idormy.sms.forwarder.core.http.entity.TipInfo
-import com.xuexiang.xhttp2.model.ApiResult
-import com.xuexiang.xutil.net.JsonUtil
-import org.junit.Assert
-import org.junit.Test
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see [Testing documentation](http://d.android.com/tools/testing)
- */
-class ExampleUnitTest {
- @Test
- fun addition_isCorrect() {
- Assert.assertEquals(4, (2 + 2).toLong())
- val info = TipInfo()
- info.title = "微信公众号"
- info.content = "获取更多资讯,欢迎关注我的微信公众号:【我的Android开源之旅】"
- val list: MutableList = ArrayList()
- for (i in 0..4) {
- list.add(info)
- }
- val result = ApiResult>()
- result.data = list
- println(JsonUtil.toJson(result))
- }
-}
\ No newline at end of file