diff --git a/app/src/main/java/com/idormy/sms/forwarder/App.kt b/app/src/main/java/com/idormy/sms/forwarder/App.kt index 43532b0d4e..9c88589666 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/App.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/App.kt @@ -112,12 +112,12 @@ class App : Application(), CactusCallback, Configuration.Provider by Core { } //启动前台服务 - Intent(this, ForegroundService::class.java).also { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(it) - } else { - startService(it) - } + val serviceIntent = Intent(this, ForegroundService::class.java) + serviceIntent.action = "START" + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(serviceIntent) + } else { + startService(serviceIntent) } //网络状态监听 diff --git a/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt b/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt index 7e3e0d9a1e..c5cf921792 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/activity/MainActivity.kt @@ -104,12 +104,12 @@ class MainActivity : BaseActivity(), //启动前台服务 if (!ForegroundService.isRunning) { - Intent(this, ForegroundService::class.java).also { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(it) - } else { - startService(it) - } + val serviceIntent = Intent(this, ForegroundService::class.java) + serviceIntent.action = "START" + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(serviceIntent) + } else { + startService(serviceIntent) } } }) @@ -204,6 +204,7 @@ class MainActivity : BaseActivity(), .show() } } + R.id.nav_app_list -> openNewPage(AppListFragment::class.java) //R.id.nav_logcat -> openNewPage(LogcatFragment::class.java) R.id.nav_help -> AgentWebActivity.goWeb(this, getString(R.string.url_help)) @@ -232,12 +233,15 @@ class MainActivity : BaseActivity(), getString(R.string.menu_rules) -> binding!!.includeMain.toolbar.inflateMenu( R.menu.menu_rules ) + getString(R.string.menu_senders) -> binding!!.includeMain.toolbar.inflateMenu( R.menu.menu_senders ) + getString(R.string.menu_settings) -> binding!!.includeMain.toolbar.inflateMenu( R.menu.menu_settings ) + else -> binding!!.includeMain.toolbar.inflateMenu(R.menu.menu_logs) } item.isChecked = true @@ -255,13 +259,6 @@ class MainActivity : BaseActivity(), LiveEventBus.get(EVENT_UPDATE_RULE_TYPE, String::class.java).observe(this) { type: String -> ruleType = type } - - //更新通知栏文案 - LiveEventBus.get(EVENT_UPDATE_NOTIFY, String::class.java).observe(this) { notify: String -> - cactusUpdateNotification { - setContent(notify) - } - } } /** @@ -287,6 +284,7 @@ class MainActivity : BaseActivity(), R.id.action_notifications -> { showTipsForce(this) } + R.id.action_clear_logs -> { MaterialDialog.Builder(this) .content(R.string.delete_type_log_tips) @@ -311,6 +309,7 @@ class MainActivity : BaseActivity(), } .show() } + R.id.action_add_sender -> { val dialog = BottomSheetDialog(this) val view: View = @@ -328,6 +327,7 @@ class MainActivity : BaseActivity(), dialog.show() WidgetUtils.transparentBottomSheetDialogBackground(dialog) } + R.id.action_add_rule -> { PageOption.to(RulesEditFragment::class.java) .putString(KEY_RULE_TYPE, ruleType) diff --git a/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt b/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt index 5d858e726e..5917aabf1a 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/core/Core.kt @@ -19,28 +19,6 @@ object Core : Configuration.Provider { val logs: LogsRepository by lazy { (app as App).logsRepository } val rule: RuleRepository by lazy { (app as App).ruleRepository } val sender: SenderRepository by lazy { (app as App).senderRepository } - /* - val telephonyManager: TelephonyManager by lazy { app.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager } - val smsManager: SmsManager by lazy { app.getSystemService(SmsManager::class.java) } - val subscriptionManager: SubscriptionManager by lazy { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - SubscriptionManager.from(app) - } else { - app.getSystemService(SubscriptionManager::class.java) - } - } - val user by lazy { app.getSystemService()!! }*/ - - - /*val directBootAware: Boolean get() = directBootSupported && dataStore.canToggleLocked - val directBootSupported by lazy { - Build.VERSION.SDK_INT >= 24 && try { - app.getSystemService()?.storageEncryptionStatus == - DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER - } catch (_: RuntimeException) { - false - } - }*/ fun init(app: Application) { this.app = app @@ -54,6 +32,4 @@ object Core : Configuration.Provider { setTaskExecutor { (app as App).applicationScope.launch { it.run() } } }.build() } - - fun startService() = ContextCompat.startForegroundService(app, Intent(app, ForegroundService::class.java)) } diff --git a/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt b/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt index f6bb63be75..c39b364b15 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt @@ -6,6 +6,7 @@ import android.util.Log import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.utils.CALL_TYPE_MAP +import com.idormy.sms.forwarder.utils.HttpServerUtils import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils.Companion.enableSmsTemplate import com.idormy.sms.forwarder.utils.SettingUtils.Companion.extraDeviceMark @@ -58,7 +59,7 @@ data class MsgInfo( .replace(getString(R.string.tag_app_version), versionName) .replace(getString(R.string.tag_call_type), CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call)) .trim() - return replaceAppName(regexReplace(titleForSend, regexReplace), from) + return replaceLocationTag(replaceAppName(regexReplace(titleForSend, regexReplace), from)) } val smsVoForSend: String @@ -106,7 +107,7 @@ data class MsgInfo( .replace(getString(R.string.tag_app_version), versionName) .replace(getString(R.string.tag_call_type), CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call)) .trim() - return replaceAppName(regexReplace(smsVoForSend, regexReplace), from) + return replaceLocationTag(replaceAppName(regexReplace(smsVoForSend, regexReplace), from)) } //正则替换内容 @@ -154,6 +155,15 @@ data class MsgInfo( return content.replace(getString(R.string.tag_app_name), appName) } + //替换 {{定位信息}} 标签 + private fun replaceLocationTag(content: String): String { + if (TextUtils.isEmpty(content)) return content + if (content.indexOf(getString(R.string.tag_location)) == -1) return content + + val location = HttpServerUtils.apiLocationCache.toString() + return content.replace(getString(R.string.tag_location), location) + } + override fun toString(): String { return "MsgInfo{" + "mobile='" + from + '\'' + diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt index 485eeb2157..1a422b6a9d 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/FrpcFragment.kt @@ -138,12 +138,12 @@ class FrpcFragment : BaseFragment(), FrpcPagingAdapter.On R.id.iv_play -> { if (!ForegroundService.isRunning) { - Intent(requireContext(), ForegroundService::class.java).also { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - requireContext().startForegroundService(it) - } else { - requireContext().startService(it) - } + val serviceIntent = Intent(requireContext(), ForegroundService::class.java) + serviceIntent.action = "START" + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + requireContext().startForegroundService(serviceIntent) + } else { + requireContext().startService(serviceIntent) } } diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt index e90b03b6d3..e92cc0cfdb 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt @@ -471,7 +471,7 @@ class ServerFragment : BaseFragment(), View.OnClickListe }) } - //联系人权限 + //定位权限 private fun checkLocationPermission() { XXPermissions.with(this).permission(Permission.ACCESS_COARSE_LOCATION).permission(Permission.ACCESS_FINE_LOCATION).permission(Permission.ACCESS_BACKGROUND_LOCATION).request(object : OnPermissionCallback { override fun onGranted(permissions: List, all: Boolean) { diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt index dae7cc98bc..e77629a8c4 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt @@ -18,6 +18,7 @@ import android.view.View import android.view.ViewGroup import android.widget.* import androidx.annotation.RequiresApi +import androidx.core.content.ContextCompat import androidx.lifecycle.Observer import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager @@ -32,6 +33,7 @@ import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.databinding.FragmentSettingsBinding import com.idormy.sms.forwarder.entity.SimInfo import com.idormy.sms.forwarder.receiver.BootReceiver +import com.idormy.sms.forwarder.service.ForegroundService import com.idormy.sms.forwarder.utils.* import com.idormy.sms.forwarder.workers.LoadAppListWorker import com.jeremyliao.liveeventbus.LiveEventBus @@ -172,6 +174,9 @@ class SettingsFragment : BaseFragment(), View.OnClickL //纯客户端模式 switchDirectlyToClient(binding!!.sbDirectlyToClient) + + //启用 {{定位信息}} 标签 + switchEnableLocationTag(binding!!.sbEnableLocationTag) } override fun onResume() { @@ -918,21 +923,25 @@ class SettingsFragment : BaseFragment(), View.OnClickL override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {} override fun afterTextChanged(s: Editable) { - SettingUtils.notifyContent = etNotifyContent.text.toString().trim() - LiveEventBus.get(EVENT_UPDATE_NOTIFY, String::class.java).post(SettingUtils.notifyContent) + val notifyContent = etNotifyContent.text.toString().trim() + SettingUtils.notifyContent = notifyContent + val updateIntent = Intent(context, ForegroundService::class.java) + updateIntent.action = "UPDATE_NOTIFICATION" + updateIntent.putExtra("UPDATED_CONTENT", notifyContent) + context?.let { ContextCompat.startForegroundService(it, updateIntent) } } }) } //设置转发时启用自定义模版 @SuppressLint("UseSwitchCompatOrMaterialCode", "SetTextI18n") - fun switchSmsTemplate(sb_sms_template: SwitchButton) { + fun switchSmsTemplate(sbSmsTemplate: SwitchButton) { val isOn: Boolean = SettingUtils.enableSmsTemplate - sb_sms_template.isChecked = isOn + sbSmsTemplate.isChecked = isOn val layoutSmsTemplate: LinearLayout = binding!!.layoutSmsTemplate layoutSmsTemplate.visibility = if (isOn) View.VISIBLE else View.GONE val etSmsTemplate: EditText = binding!!.etSmsTemplate - sb_sms_template.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> + sbSmsTemplate.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> layoutSmsTemplate.visibility = if (isChecked) View.VISIBLE else View.GONE SettingUtils.enableSmsTemplate = isChecked if (!isChecked) { @@ -983,6 +992,40 @@ class SettingsFragment : BaseFragment(), View.OnClickL } } + //启用 {{定位信息}} 标签 + private fun switchEnableLocationTag(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocationTag: SwitchButton) { + switchEnableLocationTag.isChecked = SettingUtils.enableLocationTag + switchEnableLocationTag.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> + SettingUtils.enableLocationTag = isChecked + if (isChecked) { + XXPermissions.with(this).permission(Permission.ACCESS_COARSE_LOCATION).permission(Permission.ACCESS_FINE_LOCATION).permission(Permission.ACCESS_BACKGROUND_LOCATION).request(object : OnPermissionCallback { + override fun onGranted(permissions: List, all: Boolean) { + //重启前台服务 + val serviceIntent = Intent(requireContext(), ForegroundService::class.java) + serviceIntent.action = "START" + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + requireContext().startForegroundService(serviceIntent) + } else { + requireContext().startService(serviceIntent) + } + } + + override fun onDenied(permissions: List, never: Boolean) { + if (never) { + XToastUtils.error(R.string.toast_denied_never) + // 如果是被永久拒绝就跳转到应用权限系统设置页面 + XXPermissions.startPermissionActivity(requireContext(), permissions) + } else { + XToastUtils.error(R.string.toast_denied) + } + SettingUtils.enableLocationTag = false + switchEnableLocationTag.isChecked = false + } + }) + } + } + } + //获取当前手机品牌 private fun getAutoStartTips(): String { return when (Build.BRAND.lowercase(Locale.ROOT)) { diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt index e4598de30a..1710f9d50c 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt @@ -1,9 +1,13 @@ package com.idormy.sms.forwarder.service +import android.annotation.SuppressLint import android.app.* import android.content.Intent import android.graphics.BitmapFactory import android.graphics.Color +import android.location.Criteria +import android.location.Geocoder +import android.location.Location import android.os.Build import android.os.IBinder import android.text.TextUtils @@ -16,9 +20,14 @@ import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.activity.MainActivity import com.idormy.sms.forwarder.database.AppDatabase +import com.idormy.sms.forwarder.entity.LocationInfo import com.idormy.sms.forwarder.utils.* import com.idormy.sms.forwarder.workers.LoadAppListWorker import com.jeremyliao.liveeventbus.LiveEventBus +import com.king.location.LocationClient +import com.king.location.LocationErrorCode +import com.king.location.OnExceptionListener +import com.king.location.OnLocationListener import com.xuexiang.xutil.XUtil import com.xuexiang.xutil.file.FileUtils import frpclib.Frpclib @@ -31,45 +40,48 @@ import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async +import java.text.SimpleDateFormat +import java.util.Date +@SuppressLint("SimpleDateFormat") @Suppress("PrivatePropertyName", "DeferredResultUnused", "OPT_IN_USAGE", "DEPRECATION") class ForegroundService : Service() { + private val TAG: String = "ForegroundService" + private var notificationManager: NotificationManager? = null + private val compositeDisposable = CompositeDisposable() private val frpcObserver = Observer { uid: String -> if (Frpclib.isRunning(uid)) { return@Observer } - AppDatabase.getInstance(App.context) - .frpcDao() - .get(uid) - .flatMap { (uid1, _, config) -> - val error = Frpclib.runContent(uid1, config) - Single.just(error) + AppDatabase.getInstance(App.context).frpcDao().get(uid).flatMap { (uid1, _, config) -> + val error = Frpclib.runContent(uid1, config) + Single.just(error) + }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver { + override fun onSubscribe(d: Disposable) { + compositeDisposable.add(d) } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : SingleObserver { - override fun onSubscribe(d: Disposable) { - compositeDisposable.add(d) - } - override fun onError(e: Throwable) { - e.printStackTrace() - LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid) - } + override fun onError(e: Throwable) { + e.printStackTrace() + LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid) + } - override fun onSuccess(msg: String) { - if (!TextUtils.isEmpty(msg)) { - Log.e(TAG, msg) - LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid) - } else { - LiveEventBus.get(EVENT_FRPC_RUNNING_SUCCESS, String::class.java).post(uid) - } + override fun onSuccess(msg: String) { + if (!TextUtils.isEmpty(msg)) { + Log.e(TAG, msg) + LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid) + } else { + LiveEventBus.get(EVENT_FRPC_RUNNING_SUCCESS, String::class.java).post(uid) } - }) + } + }) } - private var notificationManager: NotificationManager? = null + + private val locationClient by lazy { LocationClient(App.context) } + private val geocoder by lazy { Geocoder(App.context) } + private val simpleDateFormat by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss") } companion object { var isRunning = false @@ -78,13 +90,52 @@ class ForegroundService : Service() { override fun onCreate() { super.onCreate() - try { - //纯客户端模式 - if (SettingUtils.enablePureClientMode) return + //纯客户端模式 + if (SettingUtils.enablePureClientMode) return + + createNotificationChannel() + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager - startForeground(FRONT_NOTIFY_ID, createForegroundNotification()) + //纯客户端模式 + if (SettingUtils.enablePureClientMode) return START_STICKY + + if (intent != null) { + when (intent.action) { + "START" -> { + startForegroundService() + } + "STOP" -> { + stopForegroundService() + } + + "UPDATE_NOTIFICATION" -> { + val updatedContent = intent.getStringExtra("UPDATED_CONTENT") + updateNotification(updatedContent ?: "") + } + } + } + return START_STICKY + } + + override fun onDestroy() { + //非纯客户端模式 + if (!SettingUtils.enablePureClientMode) stopForegroundService() + + super.onDestroy() + } + + override fun onBind(intent: Intent): IBinder? { + return null + } + + private fun startForegroundService() { + val notification = createNotification(SettingUtils.notifyContent) + startForeground(NOTIFICATION_ID, notification) + + try { //开关通知监听服务 if (SettingUtils.enableAppNotify && CommonUtils.isNotificationListenerServiceEnabled(this)) { CommonUtils.toggleNotificationListenerService(this) @@ -96,6 +147,7 @@ class ForegroundService : Service() { WorkManager.getInstance(XUtil.getContext()).enqueue(request) } + //启动 Frpc if (FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so")) { //监听Frpc启动指令 LiveEventBus.get(INTENT_FRPC_APPLY_FILE, String::class.java).observeStickyForever(frpcObserver) @@ -117,6 +169,65 @@ class ForegroundService : Service() { } } + //远程找手机 + if (SettingUtils.enableLocationTag || HttpServerUtils.enableApiLocation) { + //可根据具体需求设置定位配置参数(这里只列出一些主要的参数) + val locationOption = locationClient.getLocationOption().setAccuracy(Criteria.ACCURACY_FINE)//设置位置精度:高精度 + .setPowerRequirement(Criteria.POWER_LOW) //设置电量消耗:低电耗 + .setMinTime(10000)//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒 + .setMinDistance(0)//设置位置更新最小距离(单位:米);默认距离:0米 + .setOnceLocation(false)//设置是否只定位一次,默认为 false,当设置为 true 时,则只定位一次后,会自动停止定位 + .setLastKnownLocation(false)//设置是否获取最后一次缓存的已知位置,默认为 true + //设置定位配置参数 + locationClient.setLocationOption(locationOption) + locationClient.startLocation() + + //设置定位监听 + locationClient.setOnLocationListener(object : OnLocationListener() { + override fun onLocationChanged(location: Location) { + //位置信息 + Log.d(TAG, "onLocationChanged(location = ${location})") + + val locationInfo = LocationInfo( + location.longitude, location.latitude, "", simpleDateFormat.format(Date(location.time)), location.provider.toString() + ) + + //根据坐标经纬度获取位置地址信息(WGS-84坐标系) + val list = geocoder.getFromLocation(location.latitude, location.longitude, 1) + if (list?.isNotEmpty() == true) { + locationInfo.address = list[0].getAddressLine(0) + } + + Log.d(TAG, "locationInfo = $locationInfo") + HttpServerUtils.apiLocationCache = locationInfo + } + + override fun onProviderEnabled(provider: String) { + super.onProviderEnabled(provider) + Log.d(TAG, "onProviderEnabled(provider = ${provider})") + } + + override fun onProviderDisabled(provider: String) { + super.onProviderDisabled(provider) + Log.d(TAG, "onProviderDisabled(provider = ${provider})") + } + + }) + + //设置异常监听 + locationClient.setOnExceptionListener(object : OnExceptionListener { + override fun onException(@LocationErrorCode errorCode: Int, e: Exception) { + //定位出现异常 + Log.w(TAG, "onException(errorCode = ${errorCode}, e = ${e})") + } + }) + + if (locationClient.isStarted()) {//如果已经开始定位,则先停止定位 + locationClient.stopLocation() + } + locationClient.startLocation() + } + isRunning = true } catch (e: Exception) { e.printStackTrace() @@ -125,34 +236,25 @@ class ForegroundService : Service() { } - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - isRunning = true - return START_STICKY - } - - override fun onDestroy() { - //纯客户端模式 - if (SettingUtils.enablePureClientMode) { - super.onDestroy() - return - } - + private fun stopForegroundService() { try { + //如果已经开始定位,则先停止定位 + if (HttpServerUtils.enableApiLocation && locationClient.isStarted()) { + locationClient.stopLocation() + } + stopForeground(true) + stopSelf() compositeDisposable.dispose() isRunning = false } catch (e: Exception) { e.printStackTrace() + isRunning = true } - super.onDestroy() } - override fun onBind(intent: Intent): IBinder? { - return null - } - - private fun createForegroundNotification(): Notification { - + private fun createNotificationChannel() { + notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val importance = NotificationManager.IMPORTANCE_HIGH val notificationChannel = NotificationChannel(FRONT_CHANNEL_ID, FRONT_CHANNEL_NAME, importance) @@ -165,20 +267,19 @@ class ForegroundService : Service() { notificationManager!!.createNotificationChannel(notificationChannel) } } - val builder = NotificationCompat.Builder(this, FRONT_CHANNEL_ID) - builder.setSmallIcon(R.drawable.ic_forwarder) - builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_menu_frpc)) - // TODO: 部分机型标题会重复待排除 - // if (DeviceUtils.getDeviceBrand().contains("Xiaomi")) { - builder.setContentTitle(getString(R.string.app_name)) - //} - builder.setContentText(SettingUtils.notifyContent) - builder.setWhen(System.currentTimeMillis()) - val activityIntent = Intent(this, MainActivity::class.java) + } + + private fun createNotification(content: String): Notification { + val notificationIntent = Intent(this, MainActivity::class.java) val flags = if (Build.VERSION.SDK_INT >= 30) PendingIntent.FLAG_IMMUTABLE else PendingIntent.FLAG_UPDATE_CURRENT - val pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, flags) - builder.setContentIntent(pendingIntent) - return builder.build() + val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, flags) + + return NotificationCompat.Builder(this, FRONT_CHANNEL_ID).setContentTitle(getString(R.string.app_name)).setContentText(content).setSmallIcon(R.drawable.ic_forwarder).setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_menu_frpc)).setContentIntent(pendingIntent).setWhen(System.currentTimeMillis()).build() + } + + private fun updateNotification(updatedContent: String) { + val notification = createNotification(updatedContent) + notificationManager?.notify(NOTIFICATION_ID, notification) } } \ No newline at end of file diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/HttpService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/HttpService.kt index 8a99caff67..cd8347a111 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/service/HttpService.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/service/HttpService.kt @@ -1,40 +1,24 @@ package com.idormy.sms.forwarder.service -import android.annotation.SuppressLint import android.app.Service import android.content.Intent -import android.location.Criteria -import android.location.Geocoder -import android.location.Location import android.os.IBinder import android.util.Log -import com.idormy.sms.forwarder.App -import com.idormy.sms.forwarder.entity.LocationInfo import com.idormy.sms.forwarder.utils.HTTP_SERVER_PORT import com.idormy.sms.forwarder.utils.HTTP_SERVER_TIME_OUT -import com.idormy.sms.forwarder.utils.HttpServerUtils import com.idormy.sms.forwarder.utils.SettingUtils -import com.king.location.LocationClient -import com.king.location.LocationErrorCode -import com.king.location.OnExceptionListener -import com.king.location.OnLocationListener import com.yanzhenjie.andserver.AndServer import com.yanzhenjie.andserver.Server -import java.text.SimpleDateFormat import java.util.* import java.util.concurrent.TimeUnit -@SuppressLint("SimpleDateFormat") -@Suppress("PrivatePropertyName", "DEPRECATION") +@Suppress("PrivatePropertyName") class HttpService : Service(), Server.ServerListener { private val TAG: String = "HttpService" private val server by lazy { AndServer.webServer(this).port(HTTP_SERVER_PORT).listener(this).timeout(HTTP_SERVER_TIME_OUT, TimeUnit.SECONDS).build() } - private val locationClient by lazy { LocationClient(App.context) } - private val geocoder by lazy { Geocoder(App.context) } - private val simpleDateFormat by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss") } override fun onBind(p0: Intent?): IBinder? { return null @@ -48,69 +32,6 @@ class HttpService : Service(), Server.ServerListener { Log.i(TAG, "onCreate: ") server.startup() - - //远程找手机 - if (HttpServerUtils.enableApiLocation) { - //可根据具体需求设置定位配置参数(这里只列出一些主要的参数) - val locationOption = locationClient.getLocationOption().setAccuracy(Criteria.ACCURACY_FINE)//设置位置精度:高精度 - .setPowerRequirement(Criteria.POWER_LOW) //设置电量消耗:低电耗 - .setMinTime(10000)//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒 - .setMinDistance(0)//设置位置更新最小距离(单位:米);默认距离:0米 - .setOnceLocation(false)//设置是否只定位一次,默认为 false,当设置为 true 时,则只定位一次后,会自动停止定位 - .setLastKnownLocation(false)//设置是否获取最后一次缓存的已知位置,默认为 true - //设置定位配置参数 - locationClient.setLocationOption(locationOption) - locationClient.startLocation() - - //设置定位监听 - locationClient.setOnLocationListener(object : OnLocationListener() { - override fun onLocationChanged(location: Location) { - //位置信息 - Log.d(TAG, "onLocationChanged(location = ${location})") - - val locationInfo = LocationInfo( - location.longitude, - location.latitude, - "", - simpleDateFormat.format(Date(location.time)), - location.provider.toString() - ) - - //根据坐标经纬度获取位置地址信息(WGS-84坐标系) - val list = geocoder.getFromLocation(location.latitude, location.longitude, 1) - if (list?.isNotEmpty() == true) { - locationInfo.address = list[0].getAddressLine(0) - } - - Log.d(TAG, "locationInfo = $locationInfo") - HttpServerUtils.apiLocationCache = locationInfo - } - - override fun onProviderEnabled(provider: String) { - super.onProviderEnabled(provider) - Log.d(TAG, "onProviderEnabled(provider = ${provider})") - } - - override fun onProviderDisabled(provider: String) { - super.onProviderDisabled(provider) - Log.d(TAG, "onProviderDisabled(provider = ${provider})") - } - - }) - - //设置异常监听 - locationClient.setOnExceptionListener(object : OnExceptionListener { - override fun onException(@LocationErrorCode errorCode: Int, e: Exception) { - //定位出现异常 - Log.w(TAG, "onException(errorCode = ${errorCode}, e = ${e})") - } - }) - - if (locationClient.isStarted()) {//如果已经开始定位,则先停止定位 - locationClient.stopLocation() - } - locationClient.startLocation() - } } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -126,10 +47,6 @@ class HttpService : Service(), Server.ServerListener { Log.i(TAG, "onDestroy: ") server.shutdown() - - if (HttpServerUtils.enableApiLocation && locationClient.isStarted()) {//如果已经开始定位,则先停止定位 - locationClient.stopLocation() - } } override fun onException(e: Exception?) { diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt index 1b987b9e96..31fdae5f0d 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt @@ -86,6 +86,7 @@ const val SP_SMS_TEMPLATE = "sms_template" const val SP_ENABLE_HELP_TIP = "enable_help_tip" const val SP_PURE_CLIENT_MODE = "enable_pure_client_mode" +const val SP_LOCATION_TAG = "enable_location_tag" const val SP_ENABLE_CACTUS = "enable_cactus" const val CACTUS_TIMER = "cactus_timer" @@ -324,6 +325,7 @@ var SENDER_FRAGMENT_LIST = listOf( //前台服务 const val FRONT_NOTIFY_ID = 0x1010 +const val NOTIFICATION_ID = 101 const val FRONT_CHANNEL_ID = "com.idormy.sms.forwarder" const val FRONT_CHANNEL_NAME = "SmsForwarder Foreground Service" @@ -349,7 +351,6 @@ const val KEY_URL = "key_url" //主页监听时间 const val EVENT_UPDATE_LOGS_TYPE = "key_logs_type" const val EVENT_UPDATE_RULE_TYPE = "key_status" -const val EVENT_UPDATE_NOTIFY = "key_notify" const val KEY_SENDER_ID = "key_sender_id" const val KEY_SENDER_TYPE = "key_sender_type" diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt index c87f226d0b..fda771a55d 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt @@ -157,6 +157,9 @@ class SettingUtils private constructor() { //是否纯客户端模式 var enablePureClientMode: Boolean by SharedPreference(SP_PURE_CLIENT_MODE, false) + //是否启用定位标签 + var enableLocationTag: Boolean by SharedPreference(SP_LOCATION_TAG, false) + } init { diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 2474d27fa3..763a10bf8d 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -344,6 +344,40 @@ tools:ignore="SmallSp" /> + + + + + + + + + + + + + {{TITLE}} {{SCHEME}} {{CALL_TYPE}} + {{LOCATION}} SMS CALL APP @@ -1057,4 +1058,7 @@ Number Country Subscription ID + + Enable {{LOCATION}} Tag + Insert location info into forwarded msg. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cd53dd578d..59706f2fc9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -608,6 +608,7 @@ {{通知标题}} {{通知Scheme}} {{通话类型}} + {{定位信息}} 短信 来电 应用 @@ -1058,4 +1059,7 @@ 手机号码 国家代码 订阅标识 + + 启用 {{定位信息}} 标签 + 在转发信息中插入手机的当前定位信息