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 ) } }