AssimilateTranslate/app/src/main/java/com/assimilate/alltrans/viewui/MainActivity.kt
2024-08-07 18:35:45 +08:00

437 lines
15 KiB
Kotlin

package com.assimilate.alltrans.viewui
import android.app.ActivityManager
import android.content.ActivityNotFoundException
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.media.projection.MediaProjectionManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.speech.RecognizerIntent
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.R
import com.assimilate.alltrans.allservice.SusService
import com.assimilate.alltrans.common.AppStore
import com.assimilate.alltrans.common.FirebaseAnalyticsHelper
import com.assimilate.alltrans.common.LolAdWrapper
import com.assimilate.alltrans.common.Widget
import com.assimilate.alltrans.databinding.ActivityMainBinding
import com.assimilate.alltrans.model.LanguagesConstants
import com.assimilate.alltrans.model.PreferenceLanguageUtils
class MainActivity : AppCompatActivity() {
private var isBackPressedOnce = false
private var serverIsStart = false
private val backPressHandler = Handler(Looper.getMainLooper())
private var launcher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK && result.data != null) {
val speech =
result.data!!.getStringArrayListExtra("android.speech.extra.RESULTS")?.get(0)
if (speech != null) {
binding.etText.setText(speech)
} else {
FirebaseAnalyticsHelper.textVoiceResultEvent(
MyApp.Config.FAIL_REASON,
"speech_is_null"
)
}
}
}
private lateinit var binding: ActivityMainBinding
private lateinit var mediaProjectionManager: MediaProjectionManager
private val REQUEST_CODE_OVERLAY = 1011
private val REQUEST_CODE_MEDIA_PROJECTION = 1012
private val mpResultCode = "mpResultCode"
private val mpData = "mpData"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(26, systemBars.top + 26, 26, systemBars.bottom)
insets
}
initSet()
initClick()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_OVERLAY) {
// 检查悬浮窗权限是否已授予
if (Settings.canDrawOverlays(this)) {
checkAndRequestMediaProjectionPermission()
} else {
Widget.makeToast(this, "To allow floating windows for quick translation.")
}
} else if (requestCode == REQUEST_CODE_MEDIA_PROJECTION) {
// 处理mediaProjectionManager权限请求结果
if (resultCode == RESULT_OK) {
serverIsStart = true
binding.ivQuickStart.setImageResource(R.drawable.main_setting_quick)
// 权限授予,启动截图
val serviceIntent = Intent(this, SusService::class.java).apply {
putExtra(mpResultCode, resultCode)
putExtra(mpData, data)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent)
} else {
startService(serviceIntent)
}
FirebaseAnalyticsHelper.hoverButtonAgreeEvent()
} else {
Widget.makeToast(
this,
"Please allow access to screen information to identify the content that needs translation."
)
FirebaseAnalyticsHelper.hoverButtonCancelEvent()
}
}
}
private fun initView() {
LolAdWrapper.shared.loadAdShowNativeAd(
this,
"your_native_ad_placement",
binding.homeNative,
R.layout.ad_layout_admob_banner,
R.layout.ad_layout_max_banner
)
binding.chSourceLanguage.text = PreferenceLanguageUtils.getString("language_source")
binding.chTargetLanguage.text = PreferenceLanguageUtils.getString("language_target")
}
private fun initSet() {
loadNative()
val isRunning = isServiceRunning(this, SusService::class.java)
if (isRunning) {
binding.ivQuickStart.setImageResource(R.drawable.main_setting_quick)
} else {
binding.ivQuickStart.setImageResource(R.drawable.main_setting_quick_def)
Widget.startScaleAnimation(binding.ivQuickStart)
}
backPressedCall()
// 初始化截屏
mediaProjectionManager =
getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
FirebaseAnalyticsHelper.homePvEvent(MyApp.Config.CLICK_FROM, "create")
}
private fun initClick() {
binding.tvMainDic.setOnClickListener {
// startActivity(Intent(this,DicActivity::class.java))
}
binding.tvMainPhotoTrans.setOnClickListener {
startActivity(
Intent(this, PhotoImageActivity::class.java).putExtra("key_start_ph", "camera")
)
}
binding.tvMainVoice.setOnClickListener {
voiceToText()
toTextTransResult()
FirebaseAnalyticsHelper.textVoiceClickEvent()
}
binding.tvMainPaste.setOnClickListener {
pasteFromClipboard()
FirebaseAnalyticsHelper.textTransPasteEvent()
}
binding.tvMainTrans.setOnClickListener {
toTextTransResult()
FirebaseAnalyticsHelper.textTransClickEvent()
}
binding.ivMainSetting.setOnClickListener {
startActivity(
Intent(this, SettingsActivity::class.java)
)
}
binding.chSourceLanguage.setOnClickListener {
startActivity(
Intent(this, LanguageChangeActivity::class.java)
)
}
binding.chTargetLanguage.setOnClickListener {
val intentT = Intent(this, LanguageChangeActivity::class.java)
intentT.putExtra("choose_t", true)
startActivity(intentT)
}
binding.ivMainHistory.setOnClickListener {
intent = Intent(this, HistoryActivity::class.java)
intent.putExtra("remove", "remove_collection")
startActivity(
intent
)
FirebaseAnalyticsHelper.historyClickEvent()
}
binding.llQuickSet.setOnClickListener {
// startActivity(
// Intent(this, QuickSetActivity::class.java)
// )
}
binding.ivQuickStart.setOnClickListener {
if (!serverIsStart) {
// 检查并请求悬浮窗权限
if (!Settings.canDrawOverlays(this)) {
val intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:$packageName")
)
startActivityForResult(intent, REQUEST_CODE_OVERLAY)
} else {
FirebaseAnalyticsHelper.hoverLimitAgreeEvent()
checkAndRequestMediaProjectionPermission()
}
} else {
stopService(Intent(this, SusService::class.java))
serverIsStart = false
binding.ivQuickStart.setImageResource(R.drawable.main_setting_quick_def)
}
FirebaseAnalyticsHelper.hoverButtonClickEvent()
}
binding.ivMainExChange.setOnClickListener {
// 读取当前的源语言和目标语言
val currentSourceLanguage = PreferenceLanguageUtils.getString("language_source")
val currentTargetLanguage = PreferenceLanguageUtils.getString("language_target")
// 交换源语言和目标语言
PreferenceLanguageUtils.putString("language_source", currentTargetLanguage)
PreferenceLanguageUtils.putString("language_target", currentSourceLanguage)
// 更新界面显示
binding.chSourceLanguage.text = currentTargetLanguage
binding.chTargetLanguage.text = currentSourceLanguage
}
binding.etText.setOnClickListener {
FirebaseAnalyticsHelper.textInputEvent()
}
// 监听EditText的文本变化
binding.etText.addTextChangedListener(object : TextWatcher {
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?) {
// 统计字符数并显示在 TextView 中
val charCount = s?.length ?: 0
// 截断逻辑
if (charCount > 1800) {
val truncatedText = s?.subSequence(0, 1800)
binding.etText.setText(truncatedText)
binding.etText.setSelection(1800) // 设置光标位置到文本末尾
}
// 根据EditText的内容显示或隐藏粘贴按钮
if (s.isNullOrEmpty()) {
binding.tvMainTrans.visibility = View.GONE
} else {
binding.tvMainTrans.visibility = View.VISIBLE
}
// 更新字符计数显示
val displayCharCount = if (charCount > 1800) 1800 else charCount
binding.tvMainLimitText.text = getString(R.string.main_limit_num, displayCharCount)
}
})
}
private fun checkAndRequestMediaProjectionPermission() {
// 启动截图
startActivityForResult(
mediaProjectionManager.createScreenCaptureIntent(),
REQUEST_CODE_MEDIA_PROJECTION
)
}
private fun toTextTransResult() {
if (binding.etText.text.isEmpty()) {
return
}
val intent = Intent(this, TextResultActivity::class.java)
intent.putExtra("source_text", binding.etText.text.toString())
startActivity(intent)
binding.etText.text = null
}
// 语音转文本
private fun voiceToText() {
val speechIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
speechIntent.putExtra(
RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
4000
) // 设置5秒的静默时间
speechIntent.putExtra(
RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
4000
) // 设置5秒的可能完全静默时间
// speechIntent.putExtra(
// "android.speech.extra.LANGUAGE_MODEL",
// MyApp.getSourceLanguage()
// )
val languageCode = LanguagesConstants.getInstance()
.getLanguageCodeByLanguage(PreferenceLanguageUtils.getString("language_source"), this)
speechIntent.putExtra(
"android.speech.extra.LANGUAGE",
languageCode
)
// speechIntent.putExtra(
// "android.speech.extra.LANGUAGE_PREFERENCE",
//
// )
try {
launcher.launch(speechIntent)
} catch (ea: ActivityNotFoundException) {
FirebaseAnalyticsHelper.textVoiceResultEvent(
MyApp.Config.FAIL_REASON,
"device_not_support"
)
Widget.makeToast(this, getString(R.string.main_voice_to_text))
}
}
private fun isServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val services = activityManager.getRunningServices(Integer.MAX_VALUE)
for (service in services) {
if (serviceClass.name == service.service.className) {
return true
}
}
return false
}
// 粘贴文本
private fun pasteFromClipboard() {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
if (clipboard.hasPrimaryClip()) {
val clipData = clipboard.primaryClip
if (clipData != null && clipData.itemCount > 0) {
val item = clipData.getItemAt(0)
val pasteData = item.coerceToText(this).toString()
if (pasteData.isNotEmpty()) {
binding.etText.setText(pasteData)
binding.etText.requestFocus() // 获取焦点
toTextTransResult()
} else {
Toast.makeText(
this,
resources.getString(R.string.main_paste_empty),
Toast.LENGTH_SHORT
).show()
}
} else {
Log.e("PasteFromClipboard", "No items in clipboard.")
}
} else {
Log.e("PasteFromClipboard", "Clipboard has no primary clip.")
}
}
override fun onResume() {
super.onResume()
initView()
}
override fun onRestart() {
super.onRestart()
FirebaseAnalyticsHelper.homePvEvent(MyApp.Config.CLICK_FROM, "cap")
}
override fun onDestroy() {
super.onDestroy()
launcher.unregister()
}
//定义手势返回
private fun backPressedCall() {
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (isBackPressedOnce) {
finishAffinity()
} else {
isBackPressedOnce = true
Toast.makeText(
applicationContext,
"Press the back again to exit.",
Toast.LENGTH_SHORT
).show()
backPressHandler.postDelayed({ isBackPressedOnce = false }, 2000)
}
}
}
onBackPressedDispatcher.addCallback(this, callback)
}
private fun loadNative() {
LolAdWrapper.shared.loadAdShowNativeAd(
this,
MyApp.Config.home_native_auto,
binding.homeNative,
R.layout.ad_layout_admob_banner,
R.layout.ad_layout_max_banner
)
}
}