mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
整理:Code Review
This commit is contained in:
parent
6571775a0f
commit
9c6f404190
7
app/proguard-rules.pro
vendored
7
app/proguard-rules.pro
vendored
@ -291,3 +291,10 @@
|
|||||||
-keep interface * implements com.xuexiang.xrouter.facade.template.IProvider
|
-keep interface * implements com.xuexiang.xrouter.facade.template.IProvider
|
||||||
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
|
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
|
||||||
-keep class * implements com.xuexiang.xrouter.facade.template.IProvider
|
-keep class * implements com.xuexiang.xrouter.facade.template.IProvider
|
||||||
|
|
||||||
|
-dontwarn com.alipay.sdk.**
|
||||||
|
-dontwarn com.android.org.conscrypt.**
|
||||||
|
-dontwarn java.awt.image.**
|
||||||
|
-dontwarn javax.lang.model.**
|
||||||
|
-dontwarn javax.naming.**
|
||||||
|
-dontwarn javax.naming.directory.**
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
tools:ignore="QueryAllPackagesPermission" />
|
tools:ignore="QueryAllPackagesPermission" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
@ -55,9 +56,6 @@
|
|||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.READ_LOGS"
|
android:name="android.permission.READ_LOGS"
|
||||||
tools:ignore="ProtectedPermissions" />
|
tools:ignore="ProtectedPermissions" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
|
@ -1,269 +1,269 @@
|
|||||||
package com.idormy.sms.forwarder.adapter.base.delegate
|
package com.idormy.sms.forwarder.adapter.base.delegate
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.LayoutRes
|
import androidx.annotation.LayoutRes
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.alibaba.android.vlayout.DelegateAdapter
|
import com.alibaba.android.vlayout.DelegateAdapter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础DelegateAdapter
|
* 基础DelegateAdapter
|
||||||
*
|
*
|
||||||
* @author xuexiang
|
* @author xuexiang
|
||||||
* @since 2020/3/20 12:17 AM
|
* @since 2020/3/20 12:17 AM
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused", "WRONG_TYPE_PARAMETER_NULLABILITY_FOR_JAVA_OVERRIDE")
|
||||||
abstract class XDelegateAdapter<T, V : RecyclerView.ViewHolder?> : DelegateAdapter.Adapter<V> {
|
abstract class XDelegateAdapter<T, V : RecyclerView.ViewHolder?> : DelegateAdapter.Adapter<V> {
|
||||||
/**
|
/**
|
||||||
* 数据源
|
* 数据源
|
||||||
*/
|
*/
|
||||||
private val mData: MutableList<T> = ArrayList()
|
private val mData: MutableList<T> = ArrayList()
|
||||||
/**
|
/**
|
||||||
* @return 当前列表的选中项
|
* @return 当前列表的选中项
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* 当前点击的条目
|
* 当前点击的条目
|
||||||
*/
|
*/
|
||||||
private var selectPosition = -1
|
private var selectPosition = -1
|
||||||
|
|
||||||
constructor()
|
constructor()
|
||||||
constructor(list: Collection<T>?) {
|
constructor(list: Collection<T>?) {
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
mData.addAll(list)
|
mData.addAll(list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(data: Array<T>?) {
|
constructor(data: Array<T>?) {
|
||||||
if (data != null && data.isNotEmpty()) {
|
if (data != null && data.isNotEmpty()) {
|
||||||
mData.addAll(listOf(*data))
|
mData.addAll(listOf(*data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建自定义的ViewHolder
|
* 构建自定义的ViewHolder
|
||||||
*
|
*
|
||||||
* @param parent
|
* @param parent
|
||||||
* @param viewType
|
* @param viewType
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected abstract fun getViewHolder(parent: ViewGroup, viewType: Int): V
|
protected abstract fun getViewHolder(parent: ViewGroup, viewType: Int): V
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定数据
|
* 绑定数据
|
||||||
*
|
*
|
||||||
* @param holder
|
* @param holder
|
||||||
* @param position 索引
|
* @param position 索引
|
||||||
* @param item 列表项
|
* @param item 列表项
|
||||||
*/
|
*/
|
||||||
protected abstract fun bindData(holder: V, position: Int, item: T)
|
protected abstract fun bindData(holder: V, position: Int, item: T)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载布局获取控件
|
* 加载布局获取控件
|
||||||
*
|
*
|
||||||
* @param parent 父布局
|
* @param parent 父布局
|
||||||
* @param layoutId 布局ID
|
* @param layoutId 布局ID
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected fun inflateView(parent: ViewGroup, @LayoutRes layoutId: Int): View {
|
protected fun inflateView(parent: ViewGroup, @LayoutRes layoutId: Int): View {
|
||||||
return LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
|
return LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): V {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): V {
|
||||||
return getViewHolder(parent, viewType)
|
return getViewHolder(parent, viewType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: V, position: Int) {
|
override fun onBindViewHolder(holder: V, position: Int) {
|
||||||
bindData(holder, position, mData[position])
|
bindData(holder, position, mData[position])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取列表项
|
* 获取列表项
|
||||||
*
|
*
|
||||||
* @param position
|
* @param position
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private fun getItem(position: Int): T? {
|
private fun getItem(position: Int): T? {
|
||||||
return if (checkPosition(position)) mData[position] else null
|
return if (checkPosition(position)) mData[position] else null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPosition(position: Int): Boolean {
|
private fun checkPosition(position: Int): Boolean {
|
||||||
return position >= 0 && position <= mData.size - 1
|
return position >= 0 && position <= mData.size - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
val isEmpty: Boolean
|
val isEmpty: Boolean
|
||||||
get() = itemCount == 0
|
get() = itemCount == 0
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return mData.size
|
return mData.size
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 数据源
|
* @return 数据源
|
||||||
*/
|
*/
|
||||||
val data: List<T>
|
val data: List<T>
|
||||||
get() = mData
|
get() = mData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给指定位置添加一项
|
* 给指定位置添加一项
|
||||||
*
|
*
|
||||||
* @param pos
|
* @param pos
|
||||||
* @param item
|
* @param item
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun add(pos: Int, item: T): XDelegateAdapter<*, *> {
|
fun add(pos: Int, item: T): XDelegateAdapter<*, *> {
|
||||||
mData.add(pos, item)
|
mData.add(pos, item)
|
||||||
notifyItemInserted(pos)
|
notifyItemInserted(pos)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在列表末端增加一项
|
* 在列表末端增加一项
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun add(item: T): XDelegateAdapter<*, *> {
|
fun add(item: T): XDelegateAdapter<*, *> {
|
||||||
mData.add(item)
|
mData.add(item)
|
||||||
notifyItemInserted(mData.size - 1)
|
notifyItemInserted(mData.size - 1)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除列表中指定索引的数据
|
* 删除列表中指定索引的数据
|
||||||
*
|
*
|
||||||
* @param pos
|
* @param pos
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun delete(pos: Int): XDelegateAdapter<*, *> {
|
fun delete(pos: Int): XDelegateAdapter<*, *> {
|
||||||
mData.removeAt(pos)
|
mData.removeAt(pos)
|
||||||
notifyItemRemoved(pos)
|
notifyItemRemoved(pos)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新列表中指定位置的数据
|
* 刷新列表中指定位置的数据
|
||||||
*
|
*
|
||||||
* @param pos
|
* @param pos
|
||||||
* @param item
|
* @param item
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun refresh(pos: Int, item: T): XDelegateAdapter<*, *> {
|
fun refresh(pos: Int, item: T): XDelegateAdapter<*, *> {
|
||||||
mData[pos] = item
|
mData[pos] = item
|
||||||
notifyItemChanged(pos)
|
notifyItemChanged(pos)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新列表数据
|
* 刷新列表数据
|
||||||
*
|
*
|
||||||
* @param collection
|
* @param collection
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
open fun refresh(collection: Collection<T>?): XDelegateAdapter<*, *> {
|
open fun refresh(collection: Collection<T>?): XDelegateAdapter<*, *> {
|
||||||
if (collection != null) {
|
if (collection != null) {
|
||||||
mData.clear()
|
mData.clear()
|
||||||
mData.addAll(collection)
|
mData.addAll(collection)
|
||||||
selectPosition = -1
|
selectPosition = -1
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新列表数据
|
* 刷新列表数据
|
||||||
*
|
*
|
||||||
* @param array
|
* @param array
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun refresh(array: Array<T>?): XDelegateAdapter<*, *> {
|
fun refresh(array: Array<T>?): XDelegateAdapter<*, *> {
|
||||||
if (array != null && array.isNotEmpty()) {
|
if (array != null && array.isNotEmpty()) {
|
||||||
mData.clear()
|
mData.clear()
|
||||||
mData.addAll(listOf(*array))
|
mData.addAll(listOf(*array))
|
||||||
selectPosition = -1
|
selectPosition = -1
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载更多
|
* 加载更多
|
||||||
*
|
*
|
||||||
* @param collection
|
* @param collection
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun loadMore(collection: Collection<T>?): XDelegateAdapter<*, *> {
|
fun loadMore(collection: Collection<T>?): XDelegateAdapter<*, *> {
|
||||||
if (collection != null) {
|
if (collection != null) {
|
||||||
mData.addAll(collection)
|
mData.addAll(collection)
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载更多
|
* 加载更多
|
||||||
*
|
*
|
||||||
* @param array
|
* @param array
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun loadMore(array: Array<T>?): XDelegateAdapter<*, *> {
|
fun loadMore(array: Array<T>?): XDelegateAdapter<*, *> {
|
||||||
if (array != null && array.isNotEmpty()) {
|
if (array != null && array.isNotEmpty()) {
|
||||||
mData.addAll(listOf(*array))
|
mData.addAll(listOf(*array))
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加一个
|
* 添加一个
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun load(item: T?): XDelegateAdapter<*, *> {
|
fun load(item: T?): XDelegateAdapter<*, *> {
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
mData.add(item)
|
mData.add(item)
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置当前列表的选中项
|
* 设置当前列表的选中项
|
||||||
*
|
*
|
||||||
* @param selectPosition
|
* @param selectPosition
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun setSelectPosition(selectPosition: Int): XDelegateAdapter<*, *> {
|
fun setSelectPosition(selectPosition: Int): XDelegateAdapter<*, *> {
|
||||||
this.selectPosition = selectPosition
|
this.selectPosition = selectPosition
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前列表选中项
|
* 获取当前列表选中项
|
||||||
*
|
*
|
||||||
* @return 当前列表选中项
|
* @return 当前列表选中项
|
||||||
*/
|
*/
|
||||||
val selectItem: T?
|
val selectItem: T?
|
||||||
get() = getItem(selectPosition)
|
get() = getItem(selectPosition)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除数据
|
* 清除数据
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun clear() {
|
fun clear() {
|
||||||
if (!isEmpty) {
|
if (!isEmpty) {
|
||||||
mData.clear()
|
mData.clear()
|
||||||
selectPosition = -1
|
selectPosition = -1
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,157 +1,157 @@
|
|||||||
package com.idormy.sms.forwarder.core
|
package com.idormy.sms.forwarder.core
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.xuexiang.xpage.base.XPageActivity
|
import com.xuexiang.xpage.base.XPageActivity
|
||||||
import com.xuexiang.xpage.base.XPageFragment
|
import com.xuexiang.xpage.base.XPageFragment
|
||||||
import com.xuexiang.xpage.core.CoreSwitchBean
|
import com.xuexiang.xpage.core.CoreSwitchBean
|
||||||
import com.xuexiang.xrouter.facade.service.SerializationService
|
import com.xuexiang.xrouter.facade.service.SerializationService
|
||||||
import com.xuexiang.xrouter.launcher.XRouter
|
import com.xuexiang.xrouter.launcher.XRouter
|
||||||
import com.xuexiang.xui.utils.ResUtils
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
import com.xuexiang.xui.widget.slideback.SlideBack
|
import com.xuexiang.xui.widget.slideback.SlideBack
|
||||||
import io.github.inflationx.viewpump.ViewPumpContextWrapper
|
import io.github.inflationx.viewpump.ViewPumpContextWrapper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础容器Activity
|
* 基础容器Activity
|
||||||
*
|
*
|
||||||
* @author XUE
|
* @author XUE
|
||||||
* @since 2019/3/22 11:21
|
* @since 2019/3/22 11:21
|
||||||
*/
|
*/
|
||||||
@Suppress("MemberVisibilityCanBePrivate", "UNCHECKED_CAST")
|
@Suppress("MemberVisibilityCanBePrivate", "UNCHECKED_CAST", "DEPRECATION")
|
||||||
open class BaseActivity<Binding : ViewBinding?> : XPageActivity() {
|
open class BaseActivity<Binding : ViewBinding?> : XPageActivity() {
|
||||||
/**
|
/**
|
||||||
* 获取Binding
|
* 获取Binding
|
||||||
*
|
*
|
||||||
* @return Binding
|
* @return Binding
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* ViewBinding
|
* ViewBinding
|
||||||
*/
|
*/
|
||||||
var binding: Binding? = null
|
var binding: Binding? = null
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
override fun attachBaseContext(newBase: Context) {
|
override fun attachBaseContext(newBase: Context) {
|
||||||
//注入字体
|
//注入字体
|
||||||
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase))
|
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCustomRootView(): View? {
|
override fun getCustomRootView(): View? {
|
||||||
binding = viewBindingInflate(layoutInflater)
|
binding = viewBindingInflate(layoutInflater)
|
||||||
return if (binding != null) binding!!.root else null
|
return if (binding != null) binding!!.root else null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
initStatusBarStyle()
|
initStatusBarStyle()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
registerSlideBack()
|
registerSlideBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建ViewBinding
|
* 构建ViewBinding
|
||||||
*
|
*
|
||||||
* @param inflater inflater
|
* @param inflater inflater
|
||||||
* @return ViewBinding
|
* @return ViewBinding
|
||||||
*/
|
*/
|
||||||
protected open fun viewBindingInflate(inflater: LayoutInflater?): Binding? {
|
protected open fun viewBindingInflate(inflater: LayoutInflater?): Binding? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化状态栏的样式
|
* 初始化状态栏的样式
|
||||||
*/
|
*/
|
||||||
protected open fun initStatusBarStyle() {}
|
protected open fun initStatusBarStyle() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开fragment
|
* 打开fragment
|
||||||
*
|
*
|
||||||
* @param clazz 页面类
|
* @param clazz 页面类
|
||||||
* @param addToBackStack 是否添加到栈中
|
* @param addToBackStack 是否添加到栈中
|
||||||
* @return 打开的fragment对象
|
* @return 打开的fragment对象
|
||||||
*/
|
*/
|
||||||
fun <T : XPageFragment?> openPage(clazz: Class<T>?, addToBackStack: Boolean): T {
|
fun <T : XPageFragment?> openPage(clazz: Class<T>?, addToBackStack: Boolean): T {
|
||||||
val page = CoreSwitchBean(clazz)
|
val page = CoreSwitchBean(clazz)
|
||||||
.setAddToBackStack(addToBackStack)
|
.setAddToBackStack(addToBackStack)
|
||||||
return openPage(page) as T
|
return openPage(page) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开fragment
|
* 打开fragment
|
||||||
*
|
*
|
||||||
* @return 打开的fragment对象
|
* @return 打开的fragment对象
|
||||||
*/
|
*/
|
||||||
fun <T : XPageFragment?> openNewPage(clazz: Class<T>?): T {
|
fun <T : XPageFragment?> openNewPage(clazz: Class<T>?): T {
|
||||||
val page = CoreSwitchBean(clazz)
|
val page = CoreSwitchBean(clazz)
|
||||||
.setNewActivity(true)
|
.setNewActivity(true)
|
||||||
return openPage(page) as T
|
return openPage(page) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换fragment
|
* 切换fragment
|
||||||
*
|
*
|
||||||
* @param clazz 页面类
|
* @param clazz 页面类
|
||||||
* @return 打开的fragment对象
|
* @return 打开的fragment对象
|
||||||
*/
|
*/
|
||||||
fun <T : XPageFragment?> switchPage(clazz: Class<T>?): T {
|
fun <T : XPageFragment?> switchPage(clazz: Class<T>?): T {
|
||||||
return openPage(clazz, false)
|
return openPage(clazz, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化对象
|
* 序列化对象
|
||||||
*
|
*
|
||||||
* @param object
|
* @param object
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun serializeObject(`object`: Any?): String {
|
fun serializeObject(`object`: Any?): String {
|
||||||
return XRouter.getInstance().navigation(SerializationService::class.java)
|
return XRouter.getInstance().navigation(SerializationService::class.java)
|
||||||
.object2Json(`object`)
|
.object2Json(`object`)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRelease() {
|
override fun onRelease() {
|
||||||
unregisterSlideBack()
|
unregisterSlideBack()
|
||||||
super.onRelease()
|
super.onRelease()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册侧滑回调
|
* 注册侧滑回调
|
||||||
*/
|
*/
|
||||||
protected fun registerSlideBack() {
|
protected fun registerSlideBack() {
|
||||||
if (isSupportSlideBack) {
|
if (isSupportSlideBack) {
|
||||||
SlideBack.with(this)
|
SlideBack.with(this)
|
||||||
.haveScroll(true)
|
.haveScroll(true)
|
||||||
.edgeMode(if (ResUtils.isRtl()) SlideBack.EDGE_RIGHT else SlideBack.EDGE_LEFT)
|
.edgeMode(if (ResUtils.isRtl()) SlideBack.EDGE_RIGHT else SlideBack.EDGE_LEFT)
|
||||||
.callBack { popPage() }
|
.callBack { popPage() }
|
||||||
.register()
|
.register()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注销侧滑回调
|
* 注销侧滑回调
|
||||||
*/
|
*/
|
||||||
protected fun unregisterSlideBack() {
|
protected fun unregisterSlideBack() {
|
||||||
if (isSupportSlideBack) {
|
if (isSupportSlideBack) {
|
||||||
SlideBack.unregister(this)
|
SlideBack.unregister(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 是否支持侧滑返回
|
* @return 是否支持侧滑返回
|
||||||
*/
|
*/
|
||||||
protected open val isSupportSlideBack: Boolean
|
protected open val isSupportSlideBack: Boolean
|
||||||
get() {
|
get() {
|
||||||
val page: CoreSwitchBean? = intent.getParcelableExtra(CoreSwitchBean.KEY_SWITCH_BEAN)
|
val page: CoreSwitchBean? = intent.getParcelableExtra(CoreSwitchBean.KEY_SWITCH_BEAN)
|
||||||
return page == null || page.bundle == null || page.bundle.getBoolean(
|
return page == null || page.bundle == null || page.bundle.getBoolean(
|
||||||
KEY_SUPPORT_SLIDE_BACK,
|
KEY_SUPPORT_SLIDE_BACK,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* 是否支持侧滑返回
|
* 是否支持侧滑返回
|
||||||
*/
|
*/
|
||||||
const val KEY_SUPPORT_SLIDE_BACK = "key_support_slide_back"
|
const val KEY_SUPPORT_SLIDE_BACK = "key_support_slide_back"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,87 +1,87 @@
|
|||||||
package com.idormy.sms.forwarder.core
|
package com.idormy.sms.forwarder.core
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import com.umeng.analytics.MobclickAgent
|
import com.umeng.analytics.MobclickAgent
|
||||||
import com.xuexiang.xaop.annotation.SingleClick
|
import com.xuexiang.xaop.annotation.SingleClick
|
||||||
import com.xuexiang.xpage.base.XPageContainerListFragment
|
import com.xuexiang.xpage.base.XPageContainerListFragment
|
||||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||||
import com.xuexiang.xui.widget.actionbar.TitleUtils
|
import com.xuexiang.xui.widget.actionbar.TitleUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改列表样式为主副标题显示
|
* 修改列表样式为主副标题显示
|
||||||
*
|
*
|
||||||
* @author xuexiang
|
* @author xuexiang
|
||||||
* @since 2018/11/22 上午11:26
|
* @since 2018/11/22 上午11:26
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused", "UNUSED_PARAMETER")
|
||||||
abstract class BaseContainerFragment : XPageContainerListFragment() {
|
abstract class BaseContainerFragment : XPageContainerListFragment() {
|
||||||
override fun initPage() {
|
override fun initPage() {
|
||||||
initTitle()
|
initTitle()
|
||||||
initViews()
|
initViews()
|
||||||
initListeners()
|
initListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun initTitle(): TitleBar {
|
protected fun initTitle(): TitleBar {
|
||||||
return TitleUtils.addTitleBarDynamic(
|
return TitleUtils.addTitleBarDynamic(
|
||||||
rootView as ViewGroup,
|
rootView as ViewGroup,
|
||||||
pageTitle
|
pageTitle
|
||||||
) { popToBack() }
|
) { popToBack() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initData() {
|
override fun initData() {
|
||||||
mSimpleData = initSimpleData(mSimpleData)
|
mSimpleData = initSimpleData(mSimpleData)
|
||||||
val data: MutableList<Map<String?, String?>?> = ArrayList()
|
val data: MutableList<Map<String?, String?>?> = ArrayList()
|
||||||
for (content in mSimpleData) {
|
for (content in mSimpleData) {
|
||||||
val item: MutableMap<String?, String?> = HashMap()
|
val item: MutableMap<String?, String?> = HashMap()
|
||||||
val index = content.indexOf("\n")
|
val index = content.indexOf("\n")
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
item[SimpleListAdapter.KEY_TITLE] = content.subSequence(0, index).toString()
|
item[SimpleListAdapter.KEY_TITLE] = content.subSequence(0, index).toString()
|
||||||
item[SimpleListAdapter.KEY_SUB_TITLE] =
|
item[SimpleListAdapter.KEY_SUB_TITLE] =
|
||||||
content.subSequence(index + 1, content.length).toString()
|
content.subSequence(index + 1, content.length).toString()
|
||||||
} else {
|
} else {
|
||||||
item[SimpleListAdapter.KEY_TITLE] = content
|
item[SimpleListAdapter.KEY_TITLE] = content
|
||||||
item[SimpleListAdapter.KEY_SUB_TITLE] = ""
|
item[SimpleListAdapter.KEY_SUB_TITLE] = ""
|
||||||
}
|
}
|
||||||
data.add(item)
|
data.add(item)
|
||||||
}
|
}
|
||||||
listView.adapter = SimpleListAdapter(context, data)
|
listView.adapter = SimpleListAdapter(context, data)
|
||||||
initSimply()
|
initSimply()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(adapterView: AdapterView<*>?, view: View, position: Int, id: Long) {
|
override fun onItemClick(adapterView: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||||
onItemClick(view, position)
|
onItemClick(view, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SingleClick
|
@SingleClick
|
||||||
private fun onItemClick(view: View, position: Int) {
|
private fun onItemClick(view: View, position: Int) {
|
||||||
onItemClick(position)
|
onItemClick(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
listView.onItemClickListener = null
|
listView.onItemClickListener = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
//屏幕旋转时刷新一下title
|
//屏幕旋转时刷新一下title
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
val root = rootView as ViewGroup
|
val root = rootView as ViewGroup
|
||||||
if (root.getChildAt(0) is TitleBar) {
|
if (root.getChildAt(0) is TitleBar) {
|
||||||
root.removeViewAt(0)
|
root.removeViewAt(0)
|
||||||
initTitle()
|
initTitle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
MobclickAgent.onPageStart(pageName)
|
MobclickAgent.onPageStart(pageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
MobclickAgent.onPageEnd(pageName)
|
MobclickAgent.onPageEnd(pageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,52 +1,52 @@
|
|||||||
package com.idormy.sms.forwarder.core.webview
|
package com.idormy.sms.forwarder.core.webview
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修复 Android 5.0 & 5.1 打开 WebView 闪退问题:
|
* 修复 Android 5.0 & 5.1 打开 WebView 闪退问题:
|
||||||
* 参阅 https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview
|
* 参阅 https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused", "DEPRECATION")
|
||||||
class LollipopFixedWebView : WebView {
|
class LollipopFixedWebView : WebView {
|
||||||
constructor(context: Context) : super(getFixedContext(context))
|
constructor(context: Context) : super(getFixedContext(context))
|
||||||
constructor(context: Context, attrs: AttributeSet?) : super(getFixedContext(context), attrs)
|
constructor(context: Context, attrs: AttributeSet?) : super(getFixedContext(context), attrs)
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
||||||
getFixedContext(context), attrs, defStyleAttr
|
getFixedContext(context), attrs, defStyleAttr
|
||||||
)
|
)
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
constructor(
|
constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet?,
|
attrs: AttributeSet?,
|
||||||
defStyleAttr: Int,
|
defStyleAttr: Int,
|
||||||
defStyleRes: Int,
|
defStyleRes: Int,
|
||||||
) : super(
|
) : super(
|
||||||
getFixedContext(context), attrs, defStyleAttr, defStyleRes
|
getFixedContext(context), attrs, defStyleAttr, defStyleRes
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet?,
|
attrs: AttributeSet?,
|
||||||
defStyleAttr: Int,
|
defStyleAttr: Int,
|
||||||
privateBrowsing: Boolean,
|
privateBrowsing: Boolean,
|
||||||
) : super(
|
) : super(
|
||||||
getFixedContext(context), attrs, defStyleAttr, privateBrowsing
|
getFixedContext(context), attrs, defStyleAttr, privateBrowsing
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getFixedContext(context: Context): Context {
|
fun getFixedContext(context: Context): Context {
|
||||||
return if (isLollipopWebViewBug) {
|
return if (isLollipopWebViewBug) {
|
||||||
// Avoid crashing on Android 5 and 6 (API level 21 to 23)
|
// Avoid crashing on Android 5 and 6 (API level 21 to 23)
|
||||||
context.createConfigurationContext(Configuration())
|
context.createConfigurationContext(Configuration())
|
||||||
} else context
|
} else context
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isLollipopWebViewBug: Boolean
|
private val isLollipopWebViewBug: Boolean
|
||||||
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,132 +1,133 @@
|
|||||||
package com.idormy.sms.forwarder.core.webview
|
package com.idormy.sms.forwarder.core.webview
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.webkit.WebResourceRequest
|
import android.webkit.WebResourceRequest
|
||||||
import android.webkit.WebResourceResponse
|
import android.webkit.WebResourceResponse
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.webview.WebViewInterceptDialog.Companion.show
|
import com.idormy.sms.forwarder.core.webview.WebViewInterceptDialog.Companion.show
|
||||||
import com.just.agentweb.core.client.MiddlewareWebClientBase
|
import com.just.agentweb.core.client.MiddlewareWebClientBase
|
||||||
import com.xuexiang.xui.utils.ResUtils
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【网络请求、加载】
|
* 【网络请求、加载】
|
||||||
* WebClient(WebViewClient 这个类主要帮助WebView处理各种通知、url加载,请求时间的)中间件
|
* WebClient(WebViewClient 这个类主要帮助WebView处理各种通知、url加载,请求时间的)中间件
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 方法的执行顺序,例如下面用了7个中间件一个 WebViewClient
|
* 方法的执行顺序,例如下面用了7个中间件一个 WebViewClient
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 1
|
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 1
|
||||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 2
|
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 2
|
||||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 3
|
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 3
|
||||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 4
|
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 4
|
||||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 5
|
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 5
|
||||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 6
|
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 6
|
||||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 7
|
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 7
|
||||||
* DefaultWebClient // 8
|
* DefaultWebClient // 8
|
||||||
* .setWebViewClient(mWebViewClient) // 9
|
* .setWebViewClient(mWebViewClient) // 9
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 典型的洋葱模型
|
* 典型的洋葱模型
|
||||||
* 对象内部的方法执行顺序: 1->2->3->4->5->6->7->8->9->8->7->6->5->4->3->2->1
|
* 对象内部的方法执行顺序: 1->2->3->4->5->6->7->8->9->8->7->6->5->4->3->2->1
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 中断中间件的执行, 删除super.methodName(...) 这行即可
|
* 中断中间件的执行, 删除super.methodName(...) 这行即可
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 这里主要是做去广告的工作
|
* 这里主要是做去广告的工作
|
||||||
*/
|
*/
|
||||||
open class MiddlewareWebViewClient : MiddlewareWebClientBase() {
|
@Suppress("UNUSED_PARAMETER", "DEPRECATION", "OVERRIDE_DEPRECATION")
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
open class MiddlewareWebViewClient : MiddlewareWebClientBase() {
|
||||||
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
Log.i(
|
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
||||||
"Info",
|
Log.i(
|
||||||
"MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + request.url.toString() + " c:" + count++
|
"Info",
|
||||||
)
|
"MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + request.url.toString() + " c:" + count++
|
||||||
return if (shouldOverrideUrlLoadingByApp(view, request.url.toString())) {
|
)
|
||||||
true
|
return if (shouldOverrideUrlLoadingByApp(view, request.url.toString())) {
|
||||||
} else super.shouldOverrideUrlLoading(view, request)
|
true
|
||||||
}
|
} else super.shouldOverrideUrlLoading(view, request)
|
||||||
|
}
|
||||||
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
|
||||||
Log.i(
|
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
||||||
"Info",
|
Log.i(
|
||||||
"MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + url + " c:" + count++
|
"Info",
|
||||||
)
|
"MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + url + " c:" + count++
|
||||||
return if (shouldOverrideUrlLoadingByApp(view, url)) {
|
)
|
||||||
true
|
return if (shouldOverrideUrlLoadingByApp(view, url)) {
|
||||||
} else super.shouldOverrideUrlLoading(view, url)
|
true
|
||||||
}
|
} else super.shouldOverrideUrlLoading(view, url)
|
||||||
|
}
|
||||||
override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {
|
|
||||||
val tUrl = url.lowercase(Locale.ROOT)
|
override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {
|
||||||
return if (!hasAdUrl(tUrl)) {
|
val tUrl = url.lowercase(Locale.ROOT)
|
||||||
//正常加载
|
return if (!hasAdUrl(tUrl)) {
|
||||||
super.shouldInterceptRequest(view, tUrl)
|
//正常加载
|
||||||
} else {
|
super.shouldInterceptRequest(view, tUrl)
|
||||||
//含有广告资源屏蔽请求
|
} else {
|
||||||
WebResourceResponse(null, null, null)
|
//含有广告资源屏蔽请求
|
||||||
}
|
WebResourceResponse(null, null, null)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
override fun shouldInterceptRequest(
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
view: WebView,
|
override fun shouldInterceptRequest(
|
||||||
request: WebResourceRequest,
|
view: WebView,
|
||||||
): WebResourceResponse? {
|
request: WebResourceRequest,
|
||||||
val url = request.url.toString().lowercase(Locale.ROOT)
|
): WebResourceResponse? {
|
||||||
return if (!hasAdUrl(url)) {
|
val url = request.url.toString().lowercase(Locale.ROOT)
|
||||||
//正常加载
|
return if (!hasAdUrl(url)) {
|
||||||
super.shouldInterceptRequest(view, request)
|
//正常加载
|
||||||
} else {
|
super.shouldInterceptRequest(view, request)
|
||||||
//含有广告资源屏蔽请求
|
} else {
|
||||||
WebResourceResponse(null, null, null)
|
//含有广告资源屏蔽请求
|
||||||
}
|
WebResourceResponse(null, null, null)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 根据url的scheme处理跳转第三方app的业务,true代表拦截,false代表不拦截
|
/**
|
||||||
*/
|
* 根据url的scheme处理跳转第三方app的业务,true代表拦截,false代表不拦截
|
||||||
private fun shouldOverrideUrlLoadingByApp(webView: WebView, url: String): Boolean {
|
*/
|
||||||
if (url.startsWith("http") || url.startsWith("https") || url.startsWith("ftp")) {
|
private fun shouldOverrideUrlLoadingByApp(webView: WebView, url: String): Boolean {
|
||||||
//不拦截http, https, ftp的请求
|
if (url.startsWith("http") || url.startsWith("https") || url.startsWith("ftp")) {
|
||||||
val uri = Uri.parse(url)
|
//不拦截http, https, ftp的请求
|
||||||
if (uri != null && !(WebViewInterceptDialog.APP_LINK_HOST == uri.host && url.contains("xpage"))) {
|
val uri = Uri.parse(url)
|
||||||
return false
|
if (uri != null && !(WebViewInterceptDialog.APP_LINK_HOST == uri.host && url.contains("xpage"))) {
|
||||||
}
|
return false
|
||||||
}
|
}
|
||||||
show(url)
|
}
|
||||||
return true
|
show(url)
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
companion object {
|
|
||||||
private var count = 1
|
companion object {
|
||||||
|
private var count = 1
|
||||||
/**
|
|
||||||
* 判断是否存在广告的链接
|
/**
|
||||||
*
|
* 判断是否存在广告的链接
|
||||||
* @param url
|
*
|
||||||
* @return
|
* @param url
|
||||||
*/
|
* @return
|
||||||
private fun hasAdUrl(url: String): Boolean {
|
*/
|
||||||
val adUrls = ResUtils.getStringArray(R.array.adBlockUrl)
|
private fun hasAdUrl(url: String): Boolean {
|
||||||
for (adUrl in adUrls) {
|
val adUrls = ResUtils.getStringArray(R.array.adBlockUrl)
|
||||||
if (url.contains(adUrl)) {
|
for (adUrl in adUrls) {
|
||||||
return true
|
if (url.contains(adUrl)) {
|
||||||
}
|
return true
|
||||||
}
|
}
|
||||||
return false
|
}
|
||||||
}
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,88 +1,88 @@
|
|||||||
package com.idormy.sms.forwarder.entity
|
package com.idormy.sms.forwarder.entity
|
||||||
|
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable.Creator
|
import android.os.Parcelable.Creator
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.xuexiang.xui.utils.ResUtils
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
import com.xuexiang.xui.widget.imageview.preview.enitity.IPreviewInfo
|
import com.xuexiang.xui.widget.imageview.preview.enitity.IPreviewInfo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片预览实体类
|
* 图片预览实体类
|
||||||
*
|
*
|
||||||
* @author xuexiang
|
* @author xuexiang
|
||||||
* @since 2018/12/7 下午5:34
|
* @since 2018/12/7 下午5:34
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused", "DEPRECATION")
|
||||||
data class ImageInfo(
|
data class ImageInfo(
|
||||||
//图片地址
|
//图片地址
|
||||||
var mUrl: String,
|
var mUrl: String,
|
||||||
//记录坐标
|
//记录坐标
|
||||||
var mBounds: Rect? = null,
|
var mBounds: Rect? = null,
|
||||||
var mVideoUrl: String? = null,
|
var mVideoUrl: String? = null,
|
||||||
var description: String? = ResUtils.getString(R.string.description),
|
var description: String? = ResUtils.getString(R.string.description),
|
||||||
) : IPreviewInfo {
|
) : IPreviewInfo {
|
||||||
|
|
||||||
constructor(url: String) : this(mUrl = url)
|
constructor(url: String) : this(mUrl = url)
|
||||||
|
|
||||||
constructor(url: String, bounds: Rect?) : this(mUrl = url, mBounds = bounds)
|
constructor(url: String, bounds: Rect?) : this(mUrl = url, mBounds = bounds)
|
||||||
|
|
||||||
constructor(videoUrl: String?, url: String) : this(mUrl = url, mVideoUrl = videoUrl)
|
constructor(videoUrl: String?, url: String) : this(mUrl = url, mVideoUrl = videoUrl)
|
||||||
|
|
||||||
override fun getUrl(): String { //将你的图片地址字段返回
|
override fun getUrl(): String { //将你的图片地址字段返回
|
||||||
return mUrl
|
return mUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUrl(url: String) {
|
fun setUrl(url: String) {
|
||||||
mUrl = url
|
mUrl = url
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBounds(): Rect? { //将你的图片显示坐标字段返回
|
override fun getBounds(): Rect? { //将你的图片显示坐标字段返回
|
||||||
return mBounds
|
return mBounds
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getVideoUrl(): String? {
|
override fun getVideoUrl(): String? {
|
||||||
return mVideoUrl
|
return mVideoUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setBounds(bounds: Rect) {
|
fun setBounds(bounds: Rect) {
|
||||||
mBounds = bounds
|
mBounds = bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setVideoUrl(videoUrl: String) {
|
fun setVideoUrl(videoUrl: String) {
|
||||||
mVideoUrl = videoUrl
|
mVideoUrl = videoUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun describeContents(): Int {
|
override fun describeContents(): Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||||
dest.writeString(mUrl)
|
dest.writeString(mUrl)
|
||||||
dest.writeParcelable(mBounds, flags)
|
dest.writeParcelable(mBounds, flags)
|
||||||
dest.writeString(description)
|
dest.writeString(description)
|
||||||
dest.writeString(mVideoUrl)
|
dest.writeString(mVideoUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(`in`: Parcel) : this(
|
constructor(`in`: Parcel) : this(
|
||||||
mUrl = `in`.readString()!!,
|
mUrl = `in`.readString()!!,
|
||||||
mBounds = `in`.readParcelable(Rect::class.java.classLoader),
|
mBounds = `in`.readParcelable(Rect::class.java.classLoader),
|
||||||
description = `in`.readString(),
|
description = `in`.readString(),
|
||||||
mVideoUrl = `in`.readString()
|
mVideoUrl = `in`.readString()
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object CREATOR : Creator<ImageInfo> {
|
companion object CREATOR : Creator<ImageInfo> {
|
||||||
|
|
||||||
fun newInstance(url: String, bounds: Rect): List<ImageInfo> {
|
fun newInstance(url: String, bounds: Rect): List<ImageInfo> {
|
||||||
return listOf(ImageInfo(url, bounds))
|
return listOf(ImageInfo(url, bounds))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createFromParcel(parcel: Parcel): ImageInfo {
|
override fun createFromParcel(parcel: Parcel): ImageInfo {
|
||||||
return ImageInfo(parcel)
|
return ImageInfo(parcel)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun newArray(size: Int): Array<ImageInfo?> {
|
override fun newArray(size: Int): Array<ImageInfo?> {
|
||||||
return arrayOfNulls(size)
|
return arrayOfNulls(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package com.idormy.sms.forwarder.entity.setting
|
|||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
|
@Suppress("SENSELESS_COMPARISON")
|
||||||
data class FeishuAppSetting(
|
data class FeishuAppSetting(
|
||||||
var appId: String = "",
|
var appId: String = "",
|
||||||
val appSecret: String = "",
|
val appSecret: String = "",
|
||||||
|
@ -1,146 +1,146 @@
|
|||||||
package com.idormy.sms.forwarder.fragment
|
package com.idormy.sms.forwarder.fragment
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.database.entity.Frpc
|
import com.idormy.sms.forwarder.database.entity.Frpc
|
||||||
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
||||||
import com.idormy.sms.forwarder.database.viewmodel.FrpcViewModel
|
import com.idormy.sms.forwarder.database.viewmodel.FrpcViewModel
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentFrpcEditBinding
|
import com.idormy.sms.forwarder.databinding.FragmentFrpcEditBinding
|
||||||
import com.idormy.sms.forwarder.utils.EVENT_FRPC_UPDATE_CONFIG
|
import com.idormy.sms.forwarder.utils.EVENT_FRPC_UPDATE_CONFIG
|
||||||
import com.idormy.sms.forwarder.utils.INTENT_FRPC_EDIT_FILE
|
import com.idormy.sms.forwarder.utils.INTENT_FRPC_EDIT_FILE
|
||||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
import com.idormy.sms.forwarder.utils.XToastUtils
|
||||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
import com.xuexiang.xaop.annotation.SingleClick
|
import com.xuexiang.xaop.annotation.SingleClick
|
||||||
import com.xuexiang.xpage.annotation.Page
|
import com.xuexiang.xpage.annotation.Page
|
||||||
import com.xuexiang.xui.utils.ResUtils
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
import com.xuexiang.xui.utils.ThemeUtils
|
import com.xuexiang.xui.utils.ThemeUtils
|
||||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||||
import com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
import com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||||
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
|
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
|
||||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
||||||
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
@Page(name = "Frp内网穿透·编辑配置")
|
@Page(name = "Frp内网穿透·编辑配置")
|
||||||
class FrpcEditFragment : BaseFragment<FragmentFrpcEditBinding?>() {
|
class FrpcEditFragment : BaseFragment<FragmentFrpcEditBinding?>() {
|
||||||
|
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
var frpc: Frpc? = null
|
var frpc: Frpc? = null
|
||||||
private val viewModel by viewModels<FrpcViewModel> { BaseViewModelFactory(context) }
|
private val viewModel by viewModels<FrpcViewModel> { BaseViewModelFactory(context) }
|
||||||
|
|
||||||
override fun initViews() {
|
override fun initViews() {
|
||||||
val pairCompleteMap: MutableMap<Char, Char> = HashMap()
|
val pairCompleteMap: MutableMap<Char, Char> = HashMap()
|
||||||
pairCompleteMap['{'] = '}'
|
pairCompleteMap['{'] = '}'
|
||||||
pairCompleteMap['['] = ']'
|
pairCompleteMap['['] = ']'
|
||||||
pairCompleteMap['('] = ')'
|
pairCompleteMap['('] = ')'
|
||||||
pairCompleteMap['<'] = '>'
|
pairCompleteMap['<'] = '>'
|
||||||
pairCompleteMap['"'] = '"'
|
pairCompleteMap['"'] = '"'
|
||||||
|
|
||||||
binding!!.editText.enablePairComplete(true)
|
binding!!.editText.enablePairComplete(true)
|
||||||
binding!!.editText.enablePairCompleteCenterCursor(true)
|
binding!!.editText.enablePairCompleteCenterCursor(true)
|
||||||
binding!!.editText.setPairCompleteMap(pairCompleteMap)
|
binding!!.editText.setPairCompleteMap(pairCompleteMap)
|
||||||
|
|
||||||
binding!!.editText.setEnableLineNumber(true)
|
binding!!.editText.setEnableLineNumber(true)
|
||||||
binding!!.editText.setLineNumberTextColor(Color.LTGRAY)
|
binding!!.editText.setLineNumberTextColor(Color.LTGRAY)
|
||||||
binding!!.editText.setLineNumberTextSize(24f)
|
binding!!.editText.setLineNumberTextSize(24f)
|
||||||
binding!!.editText.textSize = 14f
|
binding!!.editText.textSize = 14f
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun viewBindingInflate(inflater: LayoutInflater, container: ViewGroup): FragmentFrpcEditBinding {
|
override fun viewBindingInflate(inflater: LayoutInflater, container: ViewGroup): FragmentFrpcEditBinding {
|
||||||
return FragmentFrpcEditBinding.inflate(inflater, container, false)
|
return FragmentFrpcEditBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
titleBar = super.initTitle()!!.setImmersive(false)
|
titleBar = super.initTitle()!!.setImmersive(false)
|
||||||
titleBar!!.setTitle(R.string.menu_frpc)
|
titleBar!!.setTitle(R.string.menu_frpc)
|
||||||
titleBar!!.setActionTextColor(ThemeUtils.resolveColor(context, R.attr.colorAccent))
|
titleBar!!.setActionTextColor(ThemeUtils.resolveColor(context, R.attr.colorAccent))
|
||||||
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_save) {
|
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_save) {
|
||||||
@SuppressLint("ResourceAsColor")
|
@SuppressLint("ResourceAsColor")
|
||||||
@SingleClick
|
@SingleClick
|
||||||
override fun performAction(view: View) {
|
override fun performAction(view: View) {
|
||||||
if (frpc == null) return
|
if (frpc == null) return
|
||||||
|
|
||||||
val dialogFrpc = View.inflate(requireContext(), R.layout.dialog_frpc_save, null)
|
val dialogFrpc = View.inflate(requireContext(), R.layout.dialog_frpc_save, null)
|
||||||
val tvName = dialogFrpc.findViewById<MaterialEditText>(R.id.tv_name)
|
val tvName = dialogFrpc.findViewById<MaterialEditText>(R.id.tv_name)
|
||||||
val sbAutorun = dialogFrpc.findViewById<SwitchButton>(R.id.sb_autorun)
|
val sbAutorun = dialogFrpc.findViewById<SwitchButton>(R.id.sb_autorun)
|
||||||
|
|
||||||
tvName.setText(frpc!!.name)
|
tvName.setText(frpc!!.name)
|
||||||
sbAutorun.setCheckedImmediately(frpc!!.autorun == 1)
|
sbAutorun.setCheckedImmediately(frpc!!.autorun == 1)
|
||||||
|
|
||||||
frpc!!.config = binding!!.editText.text.toString()
|
frpc!!.config = binding!!.editText.text.toString()
|
||||||
|
|
||||||
if (TextUtils.isEmpty(frpc!!.config)) {
|
if (TextUtils.isEmpty(frpc!!.config)) {
|
||||||
XToastUtils.error(R.string.tips_input_config_content)
|
XToastUtils.error(R.string.tips_input_config_content)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialDialog.Builder(context!!)
|
MaterialDialog.Builder(context!!)
|
||||||
.iconRes(R.drawable.ic_menu_frpc)
|
.iconRes(R.drawable.ic_menu_frpc)
|
||||||
.title(R.string.title_save_config)
|
.title(R.string.title_save_config)
|
||||||
.customView(dialogFrpc, true)
|
.customView(dialogFrpc, true)
|
||||||
.cancelable(false)
|
.cancelable(false)
|
||||||
.autoDismiss(false)
|
.autoDismiss(false)
|
||||||
.neutralText(R.string.action_quit)
|
.neutralText(R.string.action_quit)
|
||||||
.neutralColor(ResUtils.getColors(R.color.red))
|
.neutralColor(ResUtils.getColors(R.color.red))
|
||||||
.onNeutral { dialog: MaterialDialog?, _: DialogAction? ->
|
.onNeutral { dialog: MaterialDialog?, _: DialogAction? ->
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
activity?.onBackPressed()
|
activity?.onBackPressed()
|
||||||
}
|
}
|
||||||
.negativeText(R.string.action_back)
|
.negativeText(R.string.action_back)
|
||||||
.negativeColor(ResUtils.getColors(R.color.colorBlueGrey))
|
.negativeColor(ResUtils.getColors(R.color.colorBlueGrey))
|
||||||
.onNegative { dialog: MaterialDialog?, _: DialogAction? ->
|
.onNegative { dialog: MaterialDialog?, _: DialogAction? ->
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
}
|
}
|
||||||
.positiveText(R.string.action_save)
|
.positiveText(R.string.action_save)
|
||||||
.onPositive { dialog: MaterialDialog?, _: DialogAction? ->
|
.onPositive { dialog: MaterialDialog?, _: DialogAction? ->
|
||||||
try {
|
try {
|
||||||
frpc!!.autorun = if (sbAutorun.isChecked) 1 else 0
|
frpc!!.autorun = if (sbAutorun.isChecked) 1 else 0
|
||||||
frpc!!.name = tvName.text.toString()
|
frpc!!.name = tvName.text.toString()
|
||||||
if (TextUtils.isEmpty(frpc!!.name)) {
|
if (TextUtils.isEmpty(frpc!!.name)) {
|
||||||
XToastUtils.error(R.string.tips_input_config_name)
|
XToastUtils.error(R.string.tips_input_config_name)
|
||||||
return@onPositive
|
return@onPositive
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TextUtils.isEmpty(frpc!!.uid)) {
|
if (TextUtils.isEmpty(frpc!!.uid)) {
|
||||||
viewModel.insert(frpc!!)
|
viewModel.insert(frpc!!)
|
||||||
} else {
|
} else {
|
||||||
viewModel.update(frpc!!)
|
viewModel.update(frpc!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
LiveEventBus.get<Frpc>(EVENT_FRPC_UPDATE_CONFIG).post(frpc)
|
LiveEventBus.get<Frpc>(EVENT_FRPC_UPDATE_CONFIG).post(frpc)
|
||||||
XToastUtils.success(R.string.tipSaveSuccess)
|
XToastUtils.success(R.string.tipSaveSuccess)
|
||||||
|
|
||||||
activity?.onBackPressed()
|
activity?.onBackPressed()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
XToastUtils.error(e.message.toString())
|
XToastUtils.error(e.message.toString())
|
||||||
}
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_restore) {
|
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_restore) {
|
||||||
@SingleClick
|
@SingleClick
|
||||||
override fun performAction(view: View) {
|
override fun performAction(view: View) {
|
||||||
binding!!.editText.setText(frpc?.config!!)
|
binding!!.editText.setText(frpc?.config!!)
|
||||||
XToastUtils.success(R.string.tipRestoreSuccess)
|
XToastUtils.success(R.string.tipRestoreSuccess)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return titleBar
|
return titleBar
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
LiveEventBus.get(INTENT_FRPC_EDIT_FILE, Frpc::class.java).observeSticky(this) { value: Frpc ->
|
LiveEventBus.get(INTENT_FRPC_EDIT_FILE, Frpc::class.java).observeSticky(this) { value: Frpc ->
|
||||||
frpc = value
|
frpc = value
|
||||||
binding!!.editText.setText(value.config)
|
binding!!.editText.setText(value.config)
|
||||||
titleBar!!.setTitle(if (TextUtils.isEmpty(value.name)) getString(R.string.noName) else value.name)
|
titleBar!!.setTitle(if (TextUtils.isEmpty(value.name)) getString(R.string.noName) else value.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -39,7 +39,7 @@ import io.reactivex.schedulers.Schedulers
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Page(name = "URL Scheme")
|
@Page(name = "URL Scheme")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
class UrlSchemeFragment : BaseFragment<FragmentSendersUrlSchemeBinding?>(), View.OnClickListener {
|
class UrlSchemeFragment : BaseFragment<FragmentSendersUrlSchemeBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = UrlSchemeFragment::class.java.simpleName
|
private val TAG: String = UrlSchemeFragment::class.java.simpleName
|
||||||
|
@ -1,105 +1,106 @@
|
|||||||
package com.idormy.sms.forwarder.utils
|
package com.idormy.sms.forwarder.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
class CacheUtils private constructor() {
|
@Suppress("DEPRECATION")
|
||||||
companion object {
|
class CacheUtils private constructor() {
|
||||||
/**
|
companion object {
|
||||||
* 获取缓存大小
|
/**
|
||||||
*
|
* 获取缓存大小
|
||||||
* @param context 上下文
|
*
|
||||||
* @return 缓存大小
|
* @param context 上下文
|
||||||
*/
|
* @return 缓存大小
|
||||||
fun getTotalCacheSize(context: Context): String {
|
*/
|
||||||
return try {
|
fun getTotalCacheSize(context: Context): String {
|
||||||
var cacheSize = getFolderSize(context.cacheDir)
|
return try {
|
||||||
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
|
var cacheSize = getFolderSize(context.cacheDir)
|
||||||
cacheSize += getFolderSize(context.externalCacheDir)
|
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
|
||||||
}
|
cacheSize += getFolderSize(context.externalCacheDir)
|
||||||
getFormatSize(cacheSize.toDouble())
|
}
|
||||||
} catch (e: Exception) {
|
getFormatSize(cacheSize.toDouble())
|
||||||
e.printStackTrace()
|
} catch (e: Exception) {
|
||||||
"0KB"
|
e.printStackTrace()
|
||||||
}
|
"0KB"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/***
|
|
||||||
* 清理所有缓存
|
/***
|
||||||
* @param context 上下文
|
* 清理所有缓存
|
||||||
*/
|
* @param context 上下文
|
||||||
fun clearAllCache(context: Context) {
|
*/
|
||||||
deleteDir(context.cacheDir)
|
fun clearAllCache(context: Context) {
|
||||||
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
|
deleteDir(context.cacheDir)
|
||||||
deleteDir(context.externalCacheDir)
|
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
|
||||||
}
|
deleteDir(context.externalCacheDir)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun deleteDir(dir: File?): Boolean {
|
|
||||||
if (dir != null && dir.isDirectory) {
|
private fun deleteDir(dir: File?): Boolean {
|
||||||
val children = dir.list()!!
|
if (dir != null && dir.isDirectory) {
|
||||||
for (child in children) {
|
val children = dir.list()!!
|
||||||
val success = deleteDir(File(dir, child))
|
for (child in children) {
|
||||||
if (!success) {
|
val success = deleteDir(File(dir, child))
|
||||||
return false
|
if (!success) {
|
||||||
}
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(dir != null)
|
}
|
||||||
return dir!!.delete()
|
assert(dir != null)
|
||||||
}
|
return dir!!.delete()
|
||||||
|
}
|
||||||
// 获取文件
|
|
||||||
//Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
|
// 获取文件
|
||||||
//Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
|
//Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
|
||||||
private fun getFolderSize(file: File?): Long {
|
//Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
|
||||||
var size: Long = 0
|
private fun getFolderSize(file: File?): Long {
|
||||||
try {
|
var size: Long = 0
|
||||||
val fileList = file!!.listFiles()!!
|
try {
|
||||||
for (value in fileList) {
|
val fileList = file!!.listFiles()!!
|
||||||
// 如果下面还有文件
|
for (value in fileList) {
|
||||||
size = if (value.isDirectory) {
|
// 如果下面还有文件
|
||||||
size + getFolderSize(value)
|
size = if (value.isDirectory) {
|
||||||
} else {
|
size + getFolderSize(value)
|
||||||
size + value.length()
|
} else {
|
||||||
}
|
size + value.length()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
}
|
||||||
e.printStackTrace()
|
} catch (e: Exception) {
|
||||||
}
|
e.printStackTrace()
|
||||||
return size
|
}
|
||||||
}
|
return size
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 格式化单位
|
/**
|
||||||
*
|
* 格式化单位
|
||||||
* @param size 文件大小
|
*
|
||||||
* @return 结果
|
* @param size 文件大小
|
||||||
*/
|
* @return 结果
|
||||||
private fun getFormatSize(size: Double): String {
|
*/
|
||||||
val kiloByte = size / 1024
|
private fun getFormatSize(size: Double): String {
|
||||||
if (kiloByte < 1) {
|
val kiloByte = size / 1024
|
||||||
return "0KB"
|
if (kiloByte < 1) {
|
||||||
}
|
return "0KB"
|
||||||
val megaByte = kiloByte / 1024
|
}
|
||||||
if (megaByte < 1) {
|
val megaByte = kiloByte / 1024
|
||||||
val result1 = BigDecimal(kiloByte.toString())
|
if (megaByte < 1) {
|
||||||
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB"
|
val result1 = BigDecimal(kiloByte.toString())
|
||||||
}
|
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB"
|
||||||
val gigaByte = megaByte / 1024
|
}
|
||||||
if (gigaByte < 1) {
|
val gigaByte = megaByte / 1024
|
||||||
val result2 = BigDecimal(megaByte.toString())
|
if (gigaByte < 1) {
|
||||||
return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB"
|
val result2 = BigDecimal(megaByte.toString())
|
||||||
}
|
return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB"
|
||||||
val teraBytes = gigaByte / 1024
|
}
|
||||||
if (teraBytes < 1) {
|
val teraBytes = gigaByte / 1024
|
||||||
val result3 = BigDecimal(gigaByte.toString())
|
if (teraBytes < 1) {
|
||||||
return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB"
|
val result3 = BigDecimal(gigaByte.toString())
|
||||||
}
|
return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB"
|
||||||
val result4 = BigDecimal(teraBytes)
|
}
|
||||||
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"
|
val result4 = BigDecimal(teraBytes)
|
||||||
}
|
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,51 +1,52 @@
|
|||||||
package com.idormy.sms.forwarder.utils
|
package com.idormy.sms.forwarder.utils
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ResolveInfo
|
import android.content.pm.ResolveInfo
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
|
|
||||||
class KeepAliveUtils private constructor() {
|
@Suppress("DEPRECATION")
|
||||||
|
class KeepAliveUtils private constructor() {
|
||||||
companion object {
|
|
||||||
fun isIgnoreBatteryOptimization(activity: Activity): Boolean {
|
companion object {
|
||||||
//安卓6.0以下没有忽略电池优化
|
fun isIgnoreBatteryOptimization(activity: Activity): Boolean {
|
||||||
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
//安卓6.0以下没有忽略电池优化
|
||||||
true
|
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||||
} else try {
|
true
|
||||||
val powerManager: PowerManager = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
|
} else try {
|
||||||
powerManager.isIgnoringBatteryOptimizations(activity.packageName)
|
val powerManager: PowerManager = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||||
} catch (e: Exception) {
|
powerManager.isIgnoringBatteryOptimizations(activity.packageName)
|
||||||
XToastUtils.error(R.string.unsupport)
|
} catch (e: Exception) {
|
||||||
false
|
XToastUtils.error(R.string.unsupport)
|
||||||
}
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
|
||||||
fun ignoreBatteryOptimization(activity: Activity) {
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
try {
|
fun ignoreBatteryOptimization(activity: Activity) {
|
||||||
if (isIgnoreBatteryOptimization(activity)) {
|
try {
|
||||||
return
|
if (isIgnoreBatteryOptimization(activity)) {
|
||||||
}
|
return
|
||||||
@SuppressLint("BatteryLife") val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
|
}
|
||||||
intent.data = Uri.parse("package:" + activity.packageName)
|
@SuppressLint("BatteryLife") val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
|
||||||
val resolveInfo: ResolveInfo? = activity.packageManager.resolveActivity(intent, 0)
|
intent.data = Uri.parse("package:" + activity.packageName)
|
||||||
if (resolveInfo != null) {
|
val resolveInfo: ResolveInfo? = activity.packageManager.resolveActivity(intent, 0)
|
||||||
activity.startActivity(intent)
|
if (resolveInfo != null) {
|
||||||
} else {
|
activity.startActivity(intent)
|
||||||
XToastUtils.error(R.string.unsupport)
|
} else {
|
||||||
}
|
XToastUtils.error(R.string.unsupport)
|
||||||
} catch (e: Exception) {
|
}
|
||||||
XToastUtils.error(R.string.unsupport)
|
} catch (e: Exception) {
|
||||||
}
|
XToastUtils.error(R.string.unsupport)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ import com.xuexiang.xutil.resource.ResUtils
|
|||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Suppress("PropertyName")
|
@Suppress("PropertyName", "DEPRECATION")
|
||||||
class PhoneUtils private constructor() {
|
class PhoneUtils private constructor() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -7,6 +7,7 @@ import java.io.*
|
|||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
@Suppress("unused", "UNCHECKED_CAST")
|
||||||
class SharedPreference<T>(private val name: String, private val default: T) : ReadWriteProperty<Any?, T> {
|
class SharedPreference<T>(private val name: String, private val default: T) : ReadWriteProperty<Any?, T> {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -1,47 +1,49 @@
|
|||||||
package com.idormy.sms.forwarder.utils.mail
|
package com.idormy.sms.forwarder.utils.mail
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.mail.Transport
|
import javax.mail.Transport
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 邮件发送器
|
* 邮件发送器
|
||||||
*/
|
*/
|
||||||
object MailSender {
|
object MailSender {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取单例
|
* 获取单例
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getInstance() = this
|
fun getInstance() = this
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送邮件
|
* 发送邮件
|
||||||
*/
|
*/
|
||||||
fun sendMail(mail: Mail, onMailSendListener: OnMailSendListener? = null) {
|
fun sendMail(mail: Mail, onMailSendListener: OnMailSendListener? = null) {
|
||||||
val send = GlobalScope.async(Dispatchers.IO) {
|
@Suppress("OPT_IN_USAGE")
|
||||||
Transport.send(MailUtil.createMailMessage(mail))
|
val send = GlobalScope.async(Dispatchers.IO) {
|
||||||
}
|
Transport.send(MailUtil.createMailMessage(mail))
|
||||||
|
}
|
||||||
GlobalScope.launch(Dispatchers.Main) {
|
|
||||||
runCatching {
|
@Suppress("OPT_IN_USAGE")
|
||||||
send.await()
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
onMailSendListener?.onSuccess()
|
runCatching {
|
||||||
}.onFailure {
|
send.await()
|
||||||
Log.e("MailSender", it.message.toString())
|
onMailSendListener?.onSuccess()
|
||||||
onMailSendListener?.onError(it)
|
}.onFailure {
|
||||||
}
|
Log.e("MailSender", it.message.toString())
|
||||||
}
|
onMailSendListener?.onError(it)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* 发送回调
|
|
||||||
*/
|
/**
|
||||||
interface OnMailSendListener {
|
* 发送回调
|
||||||
fun onSuccess()
|
*/
|
||||||
fun onError(e: Throwable)
|
interface OnMailSendListener {
|
||||||
}
|
fun onSuccess()
|
||||||
|
fun onError(e: Throwable)
|
||||||
|
}
|
||||||
}
|
}
|
@ -41,7 +41,7 @@ class UMengInit private constructor() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
UMConfigure.setLogEnabled(false)
|
UMConfigure.setLogEnabled(false)
|
||||||
UMConfigure.preInit(application, BuildConfig.APP_ID_UMENG, getChannel(application))
|
UMConfigure.preInit(application, BuildConfig.APP_ID_UMENG, getChannel()) //getChannel(application)
|
||||||
// 用户同意了隐私协议
|
// 用户同意了隐私协议
|
||||||
if (isAgreePrivacy) {
|
if (isAgreePrivacy) {
|
||||||
realInit(application)
|
realInit(application)
|
||||||
@ -62,7 +62,7 @@ class UMengInit private constructor() {
|
|||||||
UMConfigure.init(
|
UMConfigure.init(
|
||||||
application,
|
application,
|
||||||
BuildConfig.APP_ID_UMENG,
|
BuildConfig.APP_ID_UMENG,
|
||||||
getChannel(application),
|
getChannel(), //getChannel(application)
|
||||||
UMConfigure.DEVICE_TYPE_PHONE,
|
UMConfigure.DEVICE_TYPE_PHONE,
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
@ -78,7 +78,7 @@ class UMengInit private constructor() {
|
|||||||
* @param context
|
* @param context
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private fun getChannel(context: Context?): String {
|
private fun getChannel(): String { //context: Context?
|
||||||
//return WalleChannelReader.getChannel(context!!, DEFAULT_CHANNEL_ID)
|
//return WalleChannelReader.getChannel(context!!, DEFAULT_CHANNEL_ID)
|
||||||
return DEFAULT_CHANNEL_ID
|
return DEFAULT_CHANNEL_ID
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ buildscript {
|
|||||||
apply from: './versions.gradle'
|
apply from: './versions.gradle'
|
||||||
addRepos(repositories) //增加代码仓库
|
addRepos(repositories) //增加代码仓库
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "com.android.tools.build:gradle:$versions.android_gradle_plugin"
|
classpath deps.android_gradle_plugin
|
||||||
classpath deps.android_maven_gradle_plugin
|
classpath deps.android_maven_gradle_plugin
|
||||||
//图片压缩
|
//图片压缩
|
||||||
classpath 'com.chenenyu:img-optimizer:1.2.0'
|
classpath 'com.chenenyu:img-optimizer:1.2.0'
|
||||||
@ -58,9 +58,9 @@ allprojects {
|
|||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
|
|
||||||
FileTree tree = fileTree(dir: rootProject.getRootDir())
|
FileTree rootTree = fileTree(dir: rootDir)
|
||||||
tree.each { File file ->
|
rootTree.each { File file ->
|
||||||
if (file.toString().contains("ajcore") && file.toString().endsWith(".txt")) {
|
if ((file.toString().contains("ajcore") || file.toString().contains("mapping") || file.toString().contains("seeds") || file.toString().contains("unused")) && file.toString().endsWith(".txt")) {
|
||||||
delete file
|
delete file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user