mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 17:37:40 +08:00
新增:发送通道 URL Scheme(支持跨应用数据传递)#250
This commit is contained in:
parent
65e861ba62
commit
992fc2eb8c
@ -37,6 +37,7 @@ data class Sender(
|
|||||||
TYPE_SMS -> R.drawable.icon_sms
|
TYPE_SMS -> R.drawable.icon_sms
|
||||||
TYPE_DINGTALK_INNER_ROBOT -> R.drawable.icon_dingtalk_inner
|
TYPE_DINGTALK_INNER_ROBOT -> R.drawable.icon_dingtalk_inner
|
||||||
TYPE_FEISHU_APP -> R.drawable.icon_feishu_app
|
TYPE_FEISHU_APP -> R.drawable.icon_feishu_app
|
||||||
|
TYPE_URL_SCHEME -> R.drawable.icon_url_scheme
|
||||||
else -> R.drawable.icon_sms
|
else -> R.drawable.icon_sms
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ data class Sender(
|
|||||||
TYPE_SMS -> R.drawable.icon_sms
|
TYPE_SMS -> R.drawable.icon_sms
|
||||||
TYPE_DINGTALK_INNER_ROBOT -> R.drawable.icon_dingtalk_inner
|
TYPE_DINGTALK_INNER_ROBOT -> R.drawable.icon_dingtalk_inner
|
||||||
TYPE_FEISHU_APP -> R.drawable.icon_feishu_app
|
TYPE_FEISHU_APP -> R.drawable.icon_feishu_app
|
||||||
|
TYPE_URL_SCHEME -> R.drawable.icon_url_scheme
|
||||||
else -> R.drawable.icon_sms
|
else -> R.drawable.icon_sms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.idormy.sms.forwarder.entity.setting
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class UrlSchemeSetting(
|
||||||
|
var urlScheme: String,
|
||||||
|
) : Serializable
|
@ -109,6 +109,7 @@ class SendersFragment : BaseFragment<FragmentSendersBinding?>(), SenderPagingAda
|
|||||||
TYPE_GOTIFY -> GotifyFragment::class.java
|
TYPE_GOTIFY -> GotifyFragment::class.java
|
||||||
TYPE_DINGTALK_INNER_ROBOT -> DingtalkInnerRobotFragment::class.java
|
TYPE_DINGTALK_INNER_ROBOT -> DingtalkInnerRobotFragment::class.java
|
||||||
TYPE_FEISHU_APP -> FeishuAppFragment::class.java
|
TYPE_FEISHU_APP -> FeishuAppFragment::class.java
|
||||||
|
TYPE_URL_SCHEME -> UrlSchemeFragment::class.java
|
||||||
else -> DingtalkGroupRobotFragment::class.java
|
else -> DingtalkGroupRobotFragment::class.java
|
||||||
}
|
}
|
||||||
).setNewActivity(true)
|
).setNewActivity(true)
|
||||||
@ -134,6 +135,7 @@ class SendersFragment : BaseFragment<FragmentSendersBinding?>(), SenderPagingAda
|
|||||||
TYPE_GOTIFY -> GotifyFragment::class.java
|
TYPE_GOTIFY -> GotifyFragment::class.java
|
||||||
TYPE_DINGTALK_INNER_ROBOT -> DingtalkInnerRobotFragment::class.java
|
TYPE_DINGTALK_INNER_ROBOT -> DingtalkInnerRobotFragment::class.java
|
||||||
TYPE_FEISHU_APP -> FeishuAppFragment::class.java
|
TYPE_FEISHU_APP -> FeishuAppFragment::class.java
|
||||||
|
TYPE_URL_SCHEME -> UrlSchemeFragment::class.java
|
||||||
else -> DingtalkGroupRobotFragment::class.java
|
else -> DingtalkGroupRobotFragment::class.java
|
||||||
}
|
}
|
||||||
).setNewActivity(true)
|
).setNewActivity(true)
|
||||||
|
@ -0,0 +1,227 @@
|
|||||||
|
package com.idormy.sms.forwarder.fragment.senders
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Looper
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.idormy.sms.forwarder.R
|
||||||
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
|
import com.idormy.sms.forwarder.database.AppDatabase
|
||||||
|
import com.idormy.sms.forwarder.database.entity.Sender
|
||||||
|
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
||||||
|
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
|
||||||
|
import com.idormy.sms.forwarder.databinding.FragmentSendersUrlSchemeBinding
|
||||||
|
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||||
|
import com.idormy.sms.forwarder.entity.setting.UrlSchemeSetting
|
||||||
|
import com.idormy.sms.forwarder.utils.*
|
||||||
|
import com.idormy.sms.forwarder.utils.sender.UrlSchemeUtils
|
||||||
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
|
import com.xuexiang.xaop.annotation.SingleClick
|
||||||
|
import com.xuexiang.xpage.annotation.Page
|
||||||
|
import com.xuexiang.xrouter.annotation.AutoWired
|
||||||
|
import com.xuexiang.xrouter.launcher.XRouter
|
||||||
|
import com.xuexiang.xui.utils.CountDownButtonHelper
|
||||||
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||||
|
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
|
||||||
|
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
||||||
|
import io.reactivex.SingleObserver
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Page(name = "URL Scheme")
|
||||||
|
@Suppress("PrivatePropertyName")
|
||||||
|
class UrlSchemeFragment : BaseFragment<FragmentSendersUrlSchemeBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
|
private val TAG: String = UrlSchemeFragment::class.java.simpleName
|
||||||
|
var titleBar: TitleBar? = null
|
||||||
|
private val viewModel by viewModels<SenderViewModel> { BaseViewModelFactory(context) }
|
||||||
|
private var mCountDownHelper: CountDownButtonHelper? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@AutoWired(name = KEY_SENDER_ID)
|
||||||
|
var senderId: Long = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@AutoWired(name = KEY_SENDER_TYPE)
|
||||||
|
var senderType: Int = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@AutoWired(name = KEY_SENDER_CLONE)
|
||||||
|
var isClone: Boolean = false
|
||||||
|
|
||||||
|
override fun initArgs() {
|
||||||
|
XRouter.getInstance().inject(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun viewBindingInflate(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup,
|
||||||
|
): FragmentSendersUrlSchemeBinding {
|
||||||
|
return FragmentSendersUrlSchemeBinding.inflate(inflater, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initTitle(): TitleBar? {
|
||||||
|
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.url_scheme)
|
||||||
|
return titleBar
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化控件
|
||||||
|
*/
|
||||||
|
override fun initViews() {
|
||||||
|
//测试按钮增加倒计时,避免重复点击
|
||||||
|
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, SettingUtils.requestTimeout)
|
||||||
|
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
|
||||||
|
override fun onCountDown(time: Int) {
|
||||||
|
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinished() {
|
||||||
|
binding!!.btnTest.text = getString(R.string.test)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//新增
|
||||||
|
if (senderId <= 0) {
|
||||||
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
|
binding!!.btnDel.setText(R.string.discard)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//编辑
|
||||||
|
binding!!.btnDel.setText(R.string.del)
|
||||||
|
AppDatabase.getInstance(requireContext())
|
||||||
|
.senderDao()
|
||||||
|
.get(senderId)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(object : SingleObserver<Sender> {
|
||||||
|
override fun onSubscribe(d: Disposable) {}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSuccess(sender: Sender) {
|
||||||
|
if (isClone) {
|
||||||
|
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
|
||||||
|
binding!!.btnDel.setText(R.string.discard)
|
||||||
|
} else {
|
||||||
|
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
|
||||||
|
}
|
||||||
|
binding!!.etName.setText(sender.name)
|
||||||
|
binding!!.sbEnable.isChecked = sender.status == 1
|
||||||
|
val settingVo = Gson().fromJson(sender.jsonSetting, UrlSchemeSetting::class.java)
|
||||||
|
Log.d(TAG, settingVo.toString())
|
||||||
|
if (settingVo != null) {
|
||||||
|
binding!!.etUrlScheme.setText(settingVo.urlScheme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initListeners() {
|
||||||
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
|
LiveEventBus.get(KEY_SENDER_TEST, String::class.java).observe(this) { mCountDownHelper?.finish() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@SingleClick
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
try {
|
||||||
|
when (v.id) {
|
||||||
|
R.id.btn_test -> {
|
||||||
|
mCountDownHelper?.start()
|
||||||
|
Thread {
|
||||||
|
try {
|
||||||
|
val settingVo = checkSetting()
|
||||||
|
Log.d(TAG, settingVo.toString())
|
||||||
|
val msgInfo = MsgInfo("sms", getString(R.string.test_phone_num), getString(R.string.test_sender_sms), Date(), getString(R.string.test_sim_info))
|
||||||
|
UrlSchemeUtils.sendMsg(settingVo, msgInfo)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
if (Looper.myLooper() == null) Looper.prepare()
|
||||||
|
XToastUtils.error(e.message.toString())
|
||||||
|
Looper.loop()
|
||||||
|
}
|
||||||
|
LiveEventBus.get(KEY_SENDER_TEST, String::class.java).post("finish")
|
||||||
|
}.start()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
R.id.btn_del -> {
|
||||||
|
if (senderId <= 0 || isClone) {
|
||||||
|
popToBack()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialDialog.Builder(requireContext())
|
||||||
|
.title(R.string.delete_sender_title)
|
||||||
|
.content(R.string.delete_sender_tips)
|
||||||
|
.positiveText(R.string.lab_yes)
|
||||||
|
.negativeText(R.string.lab_no)
|
||||||
|
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
|
viewModel.delete(senderId)
|
||||||
|
XToastUtils.success(R.string.delete_sender_toast)
|
||||||
|
popToBack()
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
R.id.btn_save -> {
|
||||||
|
val name = binding!!.etName.text.toString().trim()
|
||||||
|
if (TextUtils.isEmpty(name)) {
|
||||||
|
throw Exception(getString(R.string.invalid_name))
|
||||||
|
}
|
||||||
|
|
||||||
|
val status = if (binding!!.sbEnable.isChecked) 1 else 0
|
||||||
|
val settingVo = checkSetting()
|
||||||
|
if (isClone) senderId = 0
|
||||||
|
val senderNew = Sender(senderId, senderType, name, Gson().toJson(settingVo), status)
|
||||||
|
Log.d(TAG, senderNew.toString())
|
||||||
|
|
||||||
|
viewModel.insertOrUpdate(senderNew)
|
||||||
|
XToastUtils.success(R.string.tipSaveSuccess)
|
||||||
|
popToBack()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
XToastUtils.error(e.message.toString())
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkSetting(): UrlSchemeSetting {
|
||||||
|
val urlScheme = binding!!.etUrlScheme.text.toString().trim()
|
||||||
|
if (!CommonUtils.checkUrlScheme(urlScheme, false)) {
|
||||||
|
throw Exception(getString(R.string.invalid_url_scheme))
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO:判断Sheme是否有效
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(urlScheme))
|
||||||
|
val packageManager: PackageManager = requireContext().packageManager
|
||||||
|
val activities: List<ResolveInfo> = packageManager.queryIntentActivities(intent, 0)
|
||||||
|
if (activities.isEmpty()) {
|
||||||
|
throw Exception(getString(R.string.invalid_url_scheme))
|
||||||
|
}
|
||||||
|
|
||||||
|
return UrlSchemeSetting(urlScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
if (mCountDownHelper != null) mCountDownHelper!!.recycle()
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -249,6 +249,20 @@ class CommonUtils private constructor() {
|
|||||||
return mat.matches()
|
return mat.matches()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//是否合法的URL Scheme
|
||||||
|
fun checkUrlScheme(urls: String?): Boolean {
|
||||||
|
return checkUrlScheme(urls, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
//是否合法的URL Scheme
|
||||||
|
fun checkUrlScheme(urls: String?, emptyResult: Boolean): Boolean {
|
||||||
|
if (TextUtils.isEmpty(urls)) return emptyResult
|
||||||
|
val regex = "^[a-zA-Z0-9]+://[-a-zA-Z0-9+&@#/%?=~_|!:,.;\\[\\]]*[-a-zA-Z0-9+&@#/%=~_|\\[\\]]"
|
||||||
|
val pat = Pattern.compile(regex)
|
||||||
|
val mat = pat.matcher(urls?.trim() ?: "")
|
||||||
|
return mat.matches()
|
||||||
|
}
|
||||||
|
|
||||||
//是否启用通知监听服务
|
//是否启用通知监听服务
|
||||||
fun isNotificationListenerServiceEnabled(context: Context): Boolean {
|
fun isNotificationListenerServiceEnabled(context: Context): Boolean {
|
||||||
val packageNames = NotificationManagerCompat.getEnabledListenerPackages(context)
|
val packageNames = NotificationManagerCompat.getEnabledListenerPackages(context)
|
||||||
|
@ -166,6 +166,7 @@ const val TYPE_PUSHPLUS = 10
|
|||||||
const val TYPE_GOTIFY = 11
|
const val TYPE_GOTIFY = 11
|
||||||
const val TYPE_DINGTALK_INNER_ROBOT = 12
|
const val TYPE_DINGTALK_INNER_ROBOT = 12
|
||||||
const val TYPE_FEISHU_APP = 13
|
const val TYPE_FEISHU_APP = 13
|
||||||
|
const val TYPE_URL_SCHEME = 14
|
||||||
var SENDER_FRAGMENT_LIST = listOf(
|
var SENDER_FRAGMENT_LIST = listOf(
|
||||||
PageInfo(
|
PageInfo(
|
||||||
getString(R.string.dingtalk_robot),
|
getString(R.string.dingtalk_robot),
|
||||||
@ -265,6 +266,13 @@ var SENDER_FRAGMENT_LIST = listOf(
|
|||||||
CoreAnim.slide,
|
CoreAnim.slide,
|
||||||
R.drawable.icon_feishu_app
|
R.drawable.icon_feishu_app
|
||||||
),
|
),
|
||||||
|
PageInfo(
|
||||||
|
getString(R.string.url_scheme),
|
||||||
|
"com.idormy.sms.forwarder.fragment.senders.UrlSchemeFragment",
|
||||||
|
"{\"\":\"\"}",
|
||||||
|
CoreAnim.slide,
|
||||||
|
R.drawable.icon_url_scheme
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
//前台服务
|
//前台服务
|
||||||
|
@ -126,6 +126,10 @@ object SendUtils {
|
|||||||
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuAppSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuAppSetting::class.java)
|
||||||
FeishuAppUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
FeishuAppUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
||||||
}
|
}
|
||||||
|
TYPE_URL_SCHEME -> {
|
||||||
|
val settingVo = Gson().fromJson(sender.jsonSetting, UrlSchemeSetting::class.java)
|
||||||
|
UrlSchemeUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
updateLogs(logId, 0, "未知发送通道")
|
updateLogs(logId, 0, "未知发送通道")
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.idormy.sms.forwarder.utils.sender
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
|
import com.idormy.sms.forwarder.database.entity.Rule
|
||||||
|
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||||
|
import com.idormy.sms.forwarder.entity.setting.UrlSchemeSetting
|
||||||
|
import com.idormy.sms.forwarder.utils.SendUtils
|
||||||
|
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||||
|
import com.xuexiang.xutil.XUtil
|
||||||
|
import com.xuexiang.xutil.app.AppUtils
|
||||||
|
import java.net.URLEncoder
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
|
||||||
|
class UrlSchemeUtils private constructor() {
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val TAG: String = UrlSchemeUtils::class.java.simpleName
|
||||||
|
|
||||||
|
fun sendMsg(
|
||||||
|
setting: UrlSchemeSetting,
|
||||||
|
msgInfo: MsgInfo,
|
||||||
|
rule: Rule?,
|
||||||
|
logId: Long?,
|
||||||
|
) {
|
||||||
|
val from: String = msgInfo.from
|
||||||
|
val content: String = if (rule != null) {
|
||||||
|
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
|
||||||
|
} else {
|
||||||
|
msgInfo.getContentForSend(SettingUtils.smsTemplate)
|
||||||
|
}
|
||||||
|
val timestamp = System.currentTimeMillis()
|
||||||
|
val orgContent: String = msgInfo.content
|
||||||
|
val deviceMark: String = SettingUtils.extraDeviceMark
|
||||||
|
val appVersion: String = AppUtils.getAppVersionName()
|
||||||
|
val simInfo: String = msgInfo.simInfo
|
||||||
|
@SuppressLint("SimpleDateFormat") val receiveTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date()) //smsVo.getDate()
|
||||||
|
|
||||||
|
var urlScheme = setting.urlScheme
|
||||||
|
Log.i(TAG, "urlScheme:$urlScheme")
|
||||||
|
|
||||||
|
urlScheme = urlScheme.replace("[from]", URLEncoder.encode(from, "UTF-8"))
|
||||||
|
.replace("[content]", URLEncoder.encode(content, "UTF-8"))
|
||||||
|
.replace("[msg]", URLEncoder.encode(content, "UTF-8"))
|
||||||
|
.replace("[org_content]", URLEncoder.encode(orgContent, "UTF-8"))
|
||||||
|
.replace("[device_mark]", URLEncoder.encode(deviceMark, "UTF-8"))
|
||||||
|
.replace("[app_version]", URLEncoder.encode(appVersion, "UTF-8"))
|
||||||
|
.replace("[title]", URLEncoder.encode(simInfo, "UTF-8"))
|
||||||
|
.replace("[card_slot]", URLEncoder.encode(simInfo, "UTF-8"))
|
||||||
|
.replace("[receive_time]", URLEncoder.encode(receiveTime, "UTF-8"))
|
||||||
|
.replace("[timestamp]", timestamp.toString())
|
||||||
|
.replace("\n", "%0A")
|
||||||
|
Log.i(TAG, "urlScheme:$urlScheme")
|
||||||
|
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(urlScheme))
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
try {
|
||||||
|
XUtil.getContext().startActivity(intent)
|
||||||
|
SendUtils.updateLogs(logId, 2, "调用成功")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Log.e(TAG, e.message.toString())
|
||||||
|
SendUtils.updateLogs(logId, 0, e.message.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendMsg(setting: UrlSchemeSetting, msgInfo: MsgInfo) {
|
||||||
|
sendMsg(setting, msgInfo, null, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
app/src/main/res/drawable/icon_url_scheme.webp
Normal file
BIN
app/src/main/res/drawable/icon_url_scheme.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
122
app/src/main/res/layout/fragment_senders_url_scheme.xml
Normal file
122
app/src/main/res/layout/fragment_senders_url_scheme.xml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/xui_config_color_background"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:overScrollMode="never">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/senderBarStyleWithSwitch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/sender_name_status"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||||
|
android:id="@+id/et_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:singleLine="true"
|
||||||
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||||
|
android:id="@+id/sb_enable"
|
||||||
|
style="@style/SwitchButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/senderBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/url_scheme"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/url_scheme_tips"
|
||||||
|
android:textSize="10sp"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||||
|
android:id="@+id/et_url_scheme"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||||
|
android:id="@+id/btn_del"
|
||||||
|
style="@style/SuperButton.Gray.Icon"
|
||||||
|
android:drawableStart="@drawable/icon_delete"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:text="@string/del"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:ignore="RtlSymmetry" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||||
|
android:id="@+id/btn_save"
|
||||||
|
style="@style/SuperButton.Blue.Icon"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:drawableStart="@drawable/icon_save"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:text="@string/save"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:ignore="RtlSymmetry" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||||
|
android:id="@+id/btn_test"
|
||||||
|
style="@style/SuperButton.Green.Icon"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:drawableStart="@drawable/icon_test"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:text="@string/test"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:ignore="RtlSymmetry" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -277,6 +277,7 @@
|
|||||||
<string name="invalid_openid">Multiple openids are separated by ,</string>
|
<string name="invalid_openid">Multiple openids are separated by ,</string>
|
||||||
<string name="invalid_webserver">WebServer is empty or not a valid URL</string>
|
<string name="invalid_webserver">WebServer is empty or not a valid URL</string>
|
||||||
<string name="invalid_webhook">WebHook is empty or not a valid URL</string>
|
<string name="invalid_webhook">WebHook is empty or not a valid URL</string>
|
||||||
|
<string name="invalid_url_scheme">URL Scheme is empty or invalid</string>
|
||||||
<string name="invalid_at_mobiles">toUser/toParty/toTag cannot be empty or select @all</string>
|
<string name="invalid_at_mobiles">toUser/toParty/toTag cannot be empty or select @all</string>
|
||||||
<string name="invalid_wework_agent">CoreID, AgentID, and Secret cannot be empty</string>
|
<string name="invalid_wework_agent">CoreID, AgentID, and Secret cannot be empty</string>
|
||||||
<string name="invalid_dingtalk_inner_robot">AgentId, AppKey, AppSecret, and UserIds cannot be empty</string>
|
<string name="invalid_dingtalk_inner_robot">AgentId, AppKey, AppSecret, and UserIds cannot be empty</string>
|
||||||
@ -334,12 +335,12 @@
|
|||||||
<!--SettingActivity-->
|
<!--SettingActivity-->
|
||||||
<string name="notify_content">Notify Content</string>
|
<string name="notify_content">Notify Content</string>
|
||||||
<string name="device_name">Device Name</string>
|
<string name="device_name">Device Name</string>
|
||||||
<string name="sim_sub_id">SIM1 SubId</string>
|
<string name="sim_sub_id">SIM SubId</string>
|
||||||
<string name="sim1_remark" tools:ignore="Typos">SIM1 SubId/Label</string>
|
<string name="sim1_remark" tools:ignore="Typos">SIM1 SubId/Label</string>
|
||||||
<string name="sim2_remark" tools:ignore="Typos">SIM2 SubId/Label</string>
|
<string name="sim2_remark" tools:ignore="Typos">SIM2 SubId/Label</string>
|
||||||
<string name="carrier_mobile" tools:ignore="Typos">Label of SIM,\neg. AT&T_88888888</string>
|
<string name="carrier_mobile" tools:ignore="Typos">Label of SIM,\neg. AT&T_88888888</string>
|
||||||
<string name="tip_number_only_error_message">Number must be greater than 0!</string>
|
<string name="tip_number_only_error_message">Number must be greater than 0!</string>
|
||||||
<string name="regexp_number_only">^[1-9]?\\d+$</string>
|
<string name="regexp_number_only" tools:ignore="Typos">^[1-9]?\\d+$</string>
|
||||||
<string name="low_power_alarm_threshold">Low Power Alarm</string>
|
<string name="low_power_alarm_threshold">Low Power Alarm</string>
|
||||||
<string name="low_power_alarm_threshold_tips">Value range: 0–99.\nLeft blank or 0 is disabled</string>
|
<string name="low_power_alarm_threshold_tips">Value range: 0–99.\nLeft blank or 0 is disabled</string>
|
||||||
<string name="retry_interval">Retry Interval</string>
|
<string name="retry_interval">Retry Interval</string>
|
||||||
@ -695,6 +696,9 @@
|
|||||||
<string name="wework_webHook">WebHook</string>
|
<string name="wework_webHook">WebHook</string>
|
||||||
<string name="wework_webHook_tips">Example: https://qyapi.weixin.qq.com/cgixx?key=xxx</string>
|
<string name="wework_webHook_tips">Example: https://qyapi.weixin.qq.com/cgixx?key=xxx</string>
|
||||||
|
|
||||||
|
<string name="url_scheme">URL Scheme</string>
|
||||||
|
<string name="url_scheme_tips">Example:myapp://api/add?&type=0&msg=[msg]</string>
|
||||||
|
|
||||||
<string name="webhook_server">Webhook Server</string>
|
<string name="webhook_server">Webhook Server</string>
|
||||||
<string name="webhook_server_tips">For example: https://a.b.com/msg?token=xyz</string>
|
<string name="webhook_server_tips">For example: https://a.b.com/msg?token=xyz</string>
|
||||||
<string name="webhook_params">Params</string>
|
<string name="webhook_params">Params</string>
|
||||||
|
@ -278,6 +278,7 @@
|
|||||||
<string name="invalid_openid">多个 openid 用 , 隔开</string>
|
<string name="invalid_openid">多个 openid 用 , 隔开</string>
|
||||||
<string name="invalid_webserver">WebServer为空 或 不是有效URL</string>
|
<string name="invalid_webserver">WebServer为空 或 不是有效URL</string>
|
||||||
<string name="invalid_webhook">WebHook为空 或 不是有效URL</string>
|
<string name="invalid_webhook">WebHook为空 或 不是有效URL</string>
|
||||||
|
<string name="invalid_url_scheme">URL Scheme 为空 或 无效</string>
|
||||||
<string name="invalid_at_mobiles">指定成员/指定部门/指定标签 不能为空 或者 选择@all</string>
|
<string name="invalid_at_mobiles">指定成员/指定部门/指定标签 不能为空 或者 选择@all</string>
|
||||||
<string name="invalid_wework_agent">企业ID、AgentID、Secret都不能为空</string>
|
<string name="invalid_wework_agent">企业ID、AgentID、Secret都不能为空</string>
|
||||||
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能为空</string>
|
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能为空</string>
|
||||||
@ -340,7 +341,7 @@
|
|||||||
<string name="sim2_remark" tools:ignore="Typos">SIM2主键/备注</string>
|
<string name="sim2_remark" tools:ignore="Typos">SIM2主键/备注</string>
|
||||||
<string name="carrier_mobile">序号/运营商_手机号</string>
|
<string name="carrier_mobile">序号/运营商_手机号</string>
|
||||||
<string name="tip_number_only_error_message">数字必须大于0!</string>
|
<string name="tip_number_only_error_message">数字必须大于0!</string>
|
||||||
<string name="regexp_number_only">^[1-9]?\\d+$</string>
|
<string name="regexp_number_only" tools:ignore="Typos">^[1-9]?\\d+$</string>
|
||||||
<string name="low_power_alarm_threshold">安全电量范围(%)</string>
|
<string name="low_power_alarm_threshold">安全电量范围(%)</string>
|
||||||
<string name="low_power_alarm_threshold_tips">超出安全范围将发出预警</string>
|
<string name="low_power_alarm_threshold_tips">超出安全范围将发出预警</string>
|
||||||
<string name="retry_interval">请求重试机制</string>
|
<string name="retry_interval">请求重试机制</string>
|
||||||
@ -696,6 +697,9 @@
|
|||||||
<string name="wework_webHook">WebHook地址</string>
|
<string name="wework_webHook">WebHook地址</string>
|
||||||
<string name="wework_webHook_tips">示例:https://qyapi.weixin.qq.com/cgixx?key=xxx</string>
|
<string name="wework_webHook_tips">示例:https://qyapi.weixin.qq.com/cgixx?key=xxx</string>
|
||||||
|
|
||||||
|
<string name="url_scheme">URL Scheme</string>
|
||||||
|
<string name="url_scheme_tips">示例:myapp://api/add?&type=0&msg=[msg]</string>
|
||||||
|
|
||||||
<string name="webhook_server">Webhook Server</string>
|
<string name="webhook_server">Webhook Server</string>
|
||||||
<string name="webhook_server_tips">例如:https://a.b.com/msg?token=xyz</string>
|
<string name="webhook_server_tips">例如:https://a.b.com/msg?token=xyz</string>
|
||||||
<string name="webhook_params">Params</string>
|
<string name="webhook_params">Params</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user