diff --git a/README.md b/README.md
index f5bd3c9..f7eb010 100644
--- a/README.md
+++ b/README.md
@@ -2,5 +2,8 @@
在线
语言识别
+文本识别
语音翻译
拍照翻译
+悬浮窗翻译
+辞典
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2fdca60..2b762e9 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -15,8 +15,9 @@ android {
applicationId = "com.assimilate.alltrans"
minSdk = 23
targetSdk = 34
- versionCode = 3
- versionName = "1.0.3"
+ // 该打 6
+ versionCode = 5
+ versionName = "1.0.5"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@@ -76,14 +77,10 @@ dependencies {
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:33.1.1"))
-
- // Add the dependencies for the Crashlytics and Analytics libraries
- // When using the BoM, you don't specify versions in Firebase library dependencies
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-config")
-
// To recognize Latin script
implementation("com.google.mlkit:text-recognition:16.0.0")
// To recognize Chinese script
diff --git a/app/myadalltrans.json b/app/myadalltrans.json
index e98940f..e2d0c8f 100644
--- a/app/myadalltrans.json
+++ b/app/myadalltrans.json
@@ -261,7 +261,6 @@
}
},
"config": [
-
[
"admob_inst",
{
@@ -324,6 +323,51 @@
}
]
},
+ "alltrans_directory_int_auto": {
+ "data": [
+ {
+ "after_click": {
+ "admob_inst": "keep",
+ "max_inst": "keep"
+ },
+ "block": {
+ "admob_inst": {
+ "delay": 0,
+ "rate": 0
+ },
+ "max_inst": {
+ "delay": 0,
+ "rate": 0
+ }
+ },
+ "close": {
+ "admob_inst": {
+ "delay": 0,
+ "rate": 0
+ },
+ "max_inst": {
+ "delay": 0,
+ "rate": 0
+ }
+ },
+ "config": [
+ [
+ "admob_inst",
+ {
+ "ca-app-pub-9280511366580942/1975489976": 100
+ }
+ ]
+ ],
+ "limit": {
+ "admob_inst": 100,
+ "max_inst": 100
+ },
+ "cycle": 0,
+ "timeout": 15000,
+ "showIntervalEnable": false
+ }
+ ]
+ },
"alltrans_home_native_auto": {
"data": [
{
@@ -372,6 +416,54 @@
}
]
},
+ "alltrans_text_trans_native_auto": {
+ "data": [
+ {
+ "config": [
+ [
+ "admob_native",
+ {
+ "ca-app-pub-9280511366580942/6930403378": 100
+ }
+ ]
+ ],
+ "block": {
+ "admob_native": {
+ "delay": 0,
+ "rate": 0
+ },
+ "max_native": {
+ "delay": 0,
+ "rate": 0
+ }
+ },
+ "click": {
+ "admob_native": [
+ 100,
+ 100,
+ 100,
+ 100,
+ 100
+ ],
+ "max_native": [
+ 100,
+ 100,
+ 100,
+ 100,
+ 100
+ ]
+ },
+ "after_click": {
+ "admob_native": "next",
+ "max_native": "next"
+ },
+ "limit": {
+ "admob_native": 100,
+ "max_native": 100
+ }
+ }
+ ]
+ },
"alltrans_backup_int_auto": {
"data": [
{
@@ -417,4 +509,4 @@
}
]
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 47f7121..3c7ed4e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,6 +14,7 @@
+
-
+
-
+
+ tools:replace="android:resource" />
? = null) {
+// if (BuildConfig.DEBUG) {
+// // 在调试模式下不上传事件
+// return
+// }
val bundle = Bundle().apply {
params?.forEach { (key, value) ->
when (value) {
@@ -44,12 +48,12 @@ object FirebaseAnalyticsHelper {
logCusEvent(MyApp.Config.textTransSwitch, params)
}
- fun languageChooseEvent(from: String,value: String) {
+ fun languageChooseEvent(from: String, value: String) {
val params = mapOf(from to value)
logCusEvent(MyApp.Config.languageChoose, params)
}
- fun languageFromEvent(clickFrom: String,value: String) {
+ fun languageFromEvent(clickFrom: String, value: String) {
val params = mapOf(clickFrom to value)
logCusEvent(MyApp.Config.languageFrom, params)
}
@@ -58,7 +62,7 @@ object FirebaseAnalyticsHelper {
logCusEvent(MyApp.Config.textTransClick, null)
}
- fun textTransResultEvent(result: String,value: String) {
+ fun textTransResultEvent(result: String, value: String) {
val params = mapOf(result to value)
logCusEvent(MyApp.Config.textTransResult, params)
}
@@ -77,7 +81,7 @@ object FirebaseAnalyticsHelper {
}
- fun textVoiceResultEvent(failReason: String,value: String) {
+ fun textVoiceResultEvent(failReason: String, value: String) {
val params = mapOf(failReason to value)
logCusEvent(MyApp.Config.textVoiceResult, params)
}
@@ -133,7 +137,7 @@ object FirebaseAnalyticsHelper {
logCusEvent(MyApp.Config.hoverScreenDistrict, null)
}
- fun imageClickEvent(clickFrom: String,value: String) {
+ fun imageClickEvent(clickFrom: String, value: String) {
val params = mapOf(clickFrom to value)
logCusEvent(MyApp.Config.imageClick, params)
}
@@ -155,30 +159,42 @@ object FirebaseAnalyticsHelper {
logCusEvent(MyApp.Config.historyDelete, null)
}
- fun hoverGlobalResultEvent(failReason: String,value: String) {
+ fun directoryClickEvent() {
+ logCusEvent(MyApp.Config.directoryClick, null)
+ }
+
+ fun directoryTransClickEvent() {
+ logCusEvent(MyApp.Config.directoryTransClick, null)
+ }
+
+ fun directoryTransResultEvent(failReason: String, value: String) {
+ val params = mapOf(failReason to value)
+ logCusEvent(MyApp.Config.directoryTransResult, params)
+ }
+
+ fun hoverGlobalResultEvent(failReason: String, value: String) {
val params = mapOf(failReason to value)
logCusEvent(MyApp.Config.hoverGlobalResult, params)
}
-
- fun hoverDistrictResultEvent(failReason: String,value: String) {
+ fun hoverDistrictResultEvent(failReason: String, value: String) {
val params = mapOf(failReason to value)
logCusEvent(MyApp.Config.hoverDistrictResult, params)
}
- fun imageCameraResultEvent(failReason: String,value: String) {
+ fun imageCameraResultEvent(failReason: String, value: String) {
val params = mapOf(failReason to value)
logCusEvent(MyApp.Config.imageCameraResult, params)
}
-
- fun imagePhotoResultEvent(failReason: String,value: String) {
+ fun imagePhotoResultEvent(failReason: String, value: String) {
val params = mapOf(failReason to value)
logCusEvent(MyApp.Config.imagePhotoResult, params)
}
-//
+// oeran domo
+
// fun logEvent(eventName: String, myParam: Map? = null) {
//
// val jsonObject = JSONObject()
diff --git a/app/src/main/java/com/assimilate/alltrans/common/LolAdWrapper.kt b/app/src/main/java/com/assimilate/alltrans/common/LolAdWrapper.kt
index 58341aa..a55d095 100644
--- a/app/src/main/java/com/assimilate/alltrans/common/LolAdWrapper.kt
+++ b/app/src/main/java/com/assimilate/alltrans/common/LolAdWrapper.kt
@@ -3,20 +3,16 @@ package com.assimilate.alltrans.common
import android.app.Activity
import android.widget.FrameLayout
import com.assimilate.alltrans.MyApp
-import com.google.android.gms.ads.interstitial.InterstitialAd
import com.lol.apex.ok.google.adlibrary.base.listener.AdLoadListener
import com.lol.apex.ok.google.adlibrary.base.listener.AdShowListener
import com.lol.apex.ok.google.adlibrary.base.listener.LolLoadError
import com.lol.apex.ok.google.adlibrary.base.listener.LolShowError
-import com.lol.apex.ok.google.adlibrary.bean.AdType
import com.lol.apex.ok.google.adlibrary.inner.LOLAdsInnerDispatcher
import com.lol.apex.ok.google.adlibrary.inner.base.AdInnerLoadAdapter
import com.lol.apex.ok.google.adlibrary.inner.base.AdInnerShowAdapter
-import com.lol.apex.ok.google.adlibrary.inst.InstAdCache
import com.lol.apex.ok.google.adlibrary.inst.LOLAdsInstDispatcher
import com.lol.apex.ok.google.adlibrary.rewarded.LOLAdsRewardedDispatcher
-
class LolAdWrapper {
companion object {
@@ -34,16 +30,18 @@ class LolAdWrapper {
fun closed() {}
}
+ // 有插屏缓存
fun hasCache(placement: String): Boolean {
return LOLAdsInstDispatcher.canShow(placement, false)
}
-
+ // 有激励缓存
fun hasRewardCache(placement: String): Boolean {
return LOLAdsRewardedDispatcher.canShow(placement)
}
- private fun loadAd(act: Activity, placement: String, listener: LoLLoadListener? = null) {
+ // 无条件加载插屏
+ fun loadAd(act: Activity, placement: String, listener: LoLLoadListener? = null) {
if (act.isFinishing) return
LOLAdsInstDispatcher.getLoader(act, placement, object : AdLoadListener {
override fun onAdLoadFailed(error: LolLoadError?) {
@@ -61,6 +59,7 @@ class LolAdWrapper {
}).loadAd()
}
+ //无条件加载激励
fun loadRewardAd(act: Activity, placement: String, listener: LoLLoadListener? = null) {
if (act.isFinishing) return
LOLAdsRewardedDispatcher.getLoader(act, placement, object : AdLoadListener {
@@ -77,22 +76,40 @@ class LolAdWrapper {
}).loadAd()
}
+ //无缓存加载插屏
fun loadAdIfNotCached(act: Activity, placement: String, listener: LoLLoadListener? = null) {
if (act.isFinishing || hasCache(placement)) return
+
loadAd(act, placement, listener)
}
-
+ //有缓存(包含全局)展示
fun showAdIfCached(act: Activity, placement: String, listener: LolShowListener? = null) {
+// if (act.isFinishing || !hasCache(placement)) {
+//// val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, "No cache for ads"))
+//// AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOW_FAILED, map)
+// listener?.showFailed(LolShowError("No cache for ads"))
+// } else {
+// showAd(act, placement, listener)
+// }
+
+ //判断当前广告位是否可以show,不能show则判断补位广告是否可以show。
if (act.isFinishing || !hasCache(placement)) {
-// val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, "No cache for ads"))
-// AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOW_FAILED, map)
- listener?.showFailed(LolShowError("No cache for ads"))
+ if (hasCache(MyApp.Config.backup_int_auto)) {
+ showAd(act, MyApp.Config.backup_int_auto, listener)
+ } else {
+// val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, "No cache for ads"))
+// AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOW_FAILED, map)
+ listener?.showFailed(LolShowError("No cache for ads"))
+ }
} else {
showAd(act, placement, listener)
}
+
+
}
+ // 带时间带缓存展示
fun showAdTiming(act: Activity, placement: String, listener: LolShowListener? = null) {
//当前时间减去旧时间,才展示广告(满足间隔时间才show广告)
if (System.currentTimeMillis() - MyApp.app.lastAdDisplayTime.get() >= AppStore(MyApp.app).showAdIntervalTime) {
@@ -111,6 +128,47 @@ class LolAdWrapper {
}
}
+ // 无条件展示
+ private fun showAd(act: Activity, placement: String, listener: LolShowListener? = null) {
+ if (act.isFinishing) return
+ LOLAdsInstDispatcher.getShower(act, placement, object : AdShowListener {
+
+ override fun onAdClicked() {
+ MyApp.app.isAdShowing.set(true)
+ }
+
+ override fun onAdClosed() {
+ MyApp.app.isAdShowing.set(false)
+ listener?.closed()
+ }
+
+ override fun onAdRewarded() {}
+ override fun onAdShowFailed(error: LolShowError?) {
+ MyApp.app.isAdShowing.set(false)
+ //广告show失败打点
+// val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, "${error?.msg}"))
+// AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOW_FAILED, map)
+ listener?.showFailed(error)
+
+ }
+
+ override fun onAdShown() {
+ MyApp.app.isAdShowing.set(true)
+ listener?.shown()
+ // AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOWN)
+ if (placement != MyApp.Config.start_cold_int_auto) {
+ MyApp.app.lastAdDisplayTime.set(System.currentTimeMillis())
+ }
+ }
+
+ override fun onAfterClickClosed() {}
+
+ override fun onDelayClosed() {}
+
+ }).showAd()
+ }
+
+ //加载展示原生
fun loadAdShowNativeAd(
context: Activity, nativeId: String, frameAd: FrameLayout, admobLayout: Int, maxLayout: Int
) {
@@ -167,45 +225,6 @@ class LolAdWrapper {
})
}
- private fun showAd(act: Activity, placement: String, listener: LolShowListener? = null) {
- if (act.isFinishing) return
- LOLAdsInstDispatcher.getShower(act, placement, object : AdShowListener {
-
- override fun onAdClicked() {
- MyApp.app.isAdShowing.set(true)
- }
-
- override fun onAdClosed() {
- MyApp.app.isAdShowing.set(false)
- listener?.closed()
- }
-
- override fun onAdRewarded() {}
- override fun onAdShowFailed(error: LolShowError?) {
- MyApp.app.isAdShowing.set(false)
- //广告show失败打点
-// val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, "${error?.msg}"))
-// AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOW_FAILED, map)
- listener?.showFailed(error)
-
- }
-
- override fun onAdShown() {
- MyApp.app.isAdShowing.set(true)
- listener?.shown()
- // AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOWN)
- if (placement != MyApp.Config.start_cold_int_auto) {
- MyApp.app.lastAdDisplayTime.set(System.currentTimeMillis())
- }
- }
-
- override fun onAfterClickClosed() {}
-
- override fun onDelayClosed() {}
-
- }).showAd()
- }
-
}
diff --git a/app/src/main/java/com/assimilate/alltrans/common/MyTextTools.kt b/app/src/main/java/com/assimilate/alltrans/common/MyTextTools.kt
index 5200927..92c80ba 100644
--- a/app/src/main/java/com/assimilate/alltrans/common/MyTextTools.kt
+++ b/app/src/main/java/com/assimilate/alltrans/common/MyTextTools.kt
@@ -4,10 +4,19 @@ import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
+import android.graphics.Color
import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
+import android.text.Spannable
+import android.text.SpannableStringBuilder
+import android.text.TextPaint
import android.text.TextUtils
+import android.text.method.LinkMovementMethod
+import android.text.style.ClickableSpan
+import android.text.style.UnderlineSpan
import android.util.Log
+import android.view.View
+import android.widget.TextView
import android.widget.Toast
import com.assimilate.alltrans.R
import com.assimilate.alltrans.model.LanguagesConstants
@@ -21,6 +30,55 @@ object MyTextTools {
private lateinit var tts: TextToSpeech
+
+ // 分割文本,添加下划线并让其可点击
+ fun makeWordsClickableWithUnderline(
+ textView: TextView,
+ text: String,
+ listener: OnWordClickListener?
+ ) {
+ val spannableStringBuilder = SpannableStringBuilder(text)
+
+ val words = text.split(" ".toRegex()).dropLastWhile { it.isEmpty() }
+ .toTypedArray()
+ var start = 0
+
+ for (word in words) {
+ val end = start + word.length
+ spannableStringBuilder.setSpan(object : ClickableSpan() {
+ override fun onClick(widget: View) {
+ // Call the listener when the word is clicked
+ listener?.onWordClick(word)
+ }
+
+ override fun updateDrawState(ds: TextPaint) {
+ super.updateDrawState(ds)
+ ds.color = Color.BLUE // Change text color on click
+ ds.isUnderlineText = false // Remove default underline
+ }
+ }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
+
+ // Apply underline span
+ spannableStringBuilder.setSpan(
+ UnderlineSpan(),
+ start,
+ end,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+
+ start = end + 1 // Move start position for next word
+ }
+
+ textView.text = spannableStringBuilder
+ textView.movementMethod = LinkMovementMethod.getInstance() // Enable clicks
+ }
+ // Interface for click listener
+ interface OnWordClickListener {
+ fun onWordClick(word: String?)
+ }
+
+
+
// 添加历史
fun addToHistory(context: Context, rText: String, transResult: String?) {
val dbTranslation = DbTranslation(context)
diff --git a/app/src/main/java/com/assimilate/alltrans/common/ScreenCaptureManager.kt b/app/src/main/java/com/assimilate/alltrans/common/ScreenCaptureManager.kt
index 67b07f1..a674630 100644
--- a/app/src/main/java/com/assimilate/alltrans/common/ScreenCaptureManager.kt
+++ b/app/src/main/java/com/assimilate/alltrans/common/ScreenCaptureManager.kt
@@ -88,7 +88,6 @@ class ScreenCaptureManager(private val context: Context) {
}
fun getImageReader(): ImageReader {
-
return imageReader
}
}
diff --git a/app/src/main/java/com/assimilate/alltrans/common/TextGraphic.kt b/app/src/main/java/com/assimilate/alltrans/common/TextGraphic.kt
index 2e64707..f5b0837 100644
--- a/app/src/main/java/com/assimilate/alltrans/common/TextGraphic.kt
+++ b/app/src/main/java/com/assimilate/alltrans/common/TextGraphic.kt
@@ -9,6 +9,7 @@ import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import android.util.Log
+import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.curview.GraphicOverlay
import com.google.mlkit.vision.text.Text
import kotlin.math.max
@@ -17,14 +18,19 @@ import kotlin.math.min
class TextGraphic(
overlay: GraphicOverlay?,
private val text: Text,
- private val shouldGroupTextInBlocks: Boolean,
- private val showLanguageTag: Boolean,
- private val showConfidence: Boolean,
private val textShow: Boolean,
private val needTrans: Boolean,
private val fbFrom: String
) : GraphicOverlay.Graphic(overlay) {
+ private val shouldGroupRecognizedTextInBlocks: Boolean =
+ PreferenceUtils.shouldGroupRecognizedTextInBlocks(MyApp.applicationContext())
+ private val showLanguageTag: Boolean =
+ PreferenceUtils.showLanguageTag(MyApp.applicationContext())
+ private val showConfidence: Boolean =
+ PreferenceUtils.shouldShowTextConfidence(MyApp.applicationContext())
+
+
private val textPaint: TextPaint = TextPaint().apply {
color = TEXT_COLOR
textSize = TEXT_SIZE
@@ -39,16 +45,25 @@ class TextGraphic(
MutableList(text.textBlocks.size) { !textShow }
private var isVisible: Boolean
+ private var isLoading: Boolean = false
+
+ // 翻译后的文本
+ private var translatedTextBlocks: List = listOf()
+
+
init {
isVisible = textShow
if (needTrans) {
+ isLoading = true
TranslationManager(text, fbFrom) { translatedTextPairs ->
translatedTextBlocks = translatedTextPairs.map { it.first }
+ isLoading = false
// 可以同时打印原Text和翻译后的结果
translatedTextPairs.forEach { (translated, original) ->
Log.d("Translation", "Original: $original -> Translated: $translated")
}
+
postInvalidate()
}
}
@@ -56,7 +71,6 @@ class TextGraphic(
postInvalidate()
}
- private var translatedTextBlocks: List = listOf()
override fun draw(canvas: Canvas) {
if (!isVisible) return
@@ -67,10 +81,26 @@ class TextGraphic(
}
}
+ private fun drawLoadingIndicator(textBlock: Text.TextBlock, canvas: Canvas) {
+ val rect = RectF(textBlock.boundingBox)
+ val centerX = (rect.left + rect.right) / 2
+ val centerY = (rect.top + rect.bottom) / 2
+ val radius = min(rect.width(), rect.height()) / 4
+
+ val paint = Paint().apply {
+ color = Color.BLUE
+ style = Paint.Style.STROKE
+ strokeWidth = 8f
+ }
+
+ canvas.drawCircle(centerX, centerY, radius, paint)
+ }
+
+
private fun drawTextBlock(textBlock: Text.TextBlock, canvas: Canvas, index: Int) {
val translatedBlockText = translatedTextBlocks.getOrNull(index) ?: textBlock.text
- if (shouldGroupTextInBlocks) {
+ if (shouldGroupRecognizedTextInBlocks) {
val rect = RectF(textBlock.boundingBox)
drawText(
getFormattedText(translatedBlockText, textBlock.recognizedLanguage, null),
@@ -79,6 +109,9 @@ class TextGraphic(
textPaint
)
}
+// if (isLoading) {
+// drawLoadingIndicator(textBlock, canvas)
+// }
}
override fun contains(x: Float, y: Float): Boolean {
diff --git a/app/src/main/java/com/assimilate/alltrans/common/TextRecognitionProcessor.kt b/app/src/main/java/com/assimilate/alltrans/common/TextRecognitionProcessor.kt
index c6f7769..237914c 100644
--- a/app/src/main/java/com/assimilate/alltrans/common/TextRecognitionProcessor.kt
+++ b/app/src/main/java/com/assimilate/alltrans/common/TextRecognitionProcessor.kt
@@ -17,9 +17,6 @@ import com.google.mlkit.vision.text.TextRecognizerOptionsInterface
class TextRecognitionProcessor(
private val context: Context,
textRecognizerOptions: TextRecognizerOptionsInterface,
- private val textShow:Boolean,
- private val needTrans: Boolean,
- private val fbFrom:String,
private val callback: TextRecognitionCallback? = null
) : VisionProcessorBase(context) {
@@ -29,10 +26,6 @@ class TextRecognitionProcessor(
}
private val textRecognizer: TextRecognizer = TextRecognition.getClient(textRecognizerOptions)
- private val shouldGroupRecognizedTextInBlocks: Boolean =
- PreferenceUtils.shouldGroupRecognizedTextInBlocks(context)
- private val showLanguageTag: Boolean = PreferenceUtils.showLanguageTag(context)
- private val showConfidence: Boolean = PreferenceUtils.shouldShowTextConfidence(context)
override fun stop() {
super.stop()
@@ -44,30 +37,15 @@ class TextRecognitionProcessor(
}
override fun onSuccess(text: Text, graphicOverlay: GraphicOverlay) {
- //
PreferenceLanguageUtils.putString("language_source", getMostFrequentLanguage(text))
- graphicOverlay.add(
- TextGraphic(
- graphicOverlay,
- text,
- shouldGroupRecognizedTextInBlocks,
- showLanguageTag,
- showConfidence,
- textShow,
- needTrans,
- fbFrom
- )
- )
-
+ logExtrasForTesting(text)
// 调用回调
callback?.onTextRecognized(text,graphicOverlay)
- logExtrasForTesting(text)
-
}
override fun onFailure(e: Exception) {
- callback?.onTextFailure(e)
Log.w(TAG, "Text detection failed.$e")
+ callback?.onTextFailure(e)
}
// 推测最可能的语言
diff --git a/app/src/main/java/com/assimilate/alltrans/common/TranslationManager.kt b/app/src/main/java/com/assimilate/alltrans/common/TranslationManager.kt
index f239630..93dfe85 100644
--- a/app/src/main/java/com/assimilate/alltrans/common/TranslationManager.kt
+++ b/app/src/main/java/com/assimilate/alltrans/common/TranslationManager.kt
@@ -2,6 +2,7 @@ package com.assimilate.alltrans.common
import android.os.Handler
import android.os.Looper
+import android.widget.Toast
import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.http.GoogleTranslator
import com.assimilate.alltrans.http.Translator
@@ -18,6 +19,8 @@ class TranslationManager(
private val handler = Handler(Looper.getMainLooper())
private val executor = Executors.newSingleThreadExecutor()
private var translatedTextBlocks: MutableList> = mutableListOf()
+ private var errorShowed = false
+
init {
prepareTranslation()
@@ -62,30 +65,45 @@ class TranslationManager(
translator.translate(param, object : GoogleTranslator.GoogleTranslateCallback {
override fun onResponse(result: String?, errorMessage: String?) {
- if (result != null) {
- translatedTextBlocks.add(Pair(index, result))
- } else {
- translatedTextBlocks.add(Pair(index, text.textBlocks[index].text))
- }
+ handler.post {
+ if (result != null) {
+ translatedTextBlocks.add(Pair(index, result))
+ } else {
+ translatedTextBlocks.add(
+ Pair(
+ index,
+ text.textBlocks[index].text
+ )
+ )
+ }
- if (translatedTextBlocks.size == text.textBlocks.size) {
- handler.post {
+ if (translatedTextBlocks.size == text.textBlocks.size) {
callback(translatedTextBlocks.sortedBy { it.first }
.map { it.second to text.textBlocks[it.first].text })
+
}
}
}
override fun onFailure(errorMessage: String?) {
- translatedTextBlocks.add(Pair(index, text.textBlocks[index].text))
- if (translatedTextBlocks.size == text.textBlocks.size) {
- handler.post {
+ handler.post {
+ translatedTextBlocks.add(Pair(index, text.textBlocks[index].text))
+ if (translatedTextBlocks.size == text.textBlocks.size) {
callback(translatedTextBlocks.sortedBy { it.first }
.map { it.second to text.textBlocks[it.first].text })
}
- }
- transFailEvent(errorMessage)
+ if (!errorShowed) {
+ Toast.makeText(
+ MyApp.applicationContext(),
+ errorMessage,
+ Toast.LENGTH_SHORT
+ ).show()
+ transFailEvent(errorMessage)
+ errorShowed = true
+ }
+
+ }
}
})
}
diff --git a/app/src/main/java/com/assimilate/alltrans/common/Widget.java b/app/src/main/java/com/assimilate/alltrans/common/Widget.java
index 8d4ef59..ccbf0bb 100644
--- a/app/src/main/java/com/assimilate/alltrans/common/Widget.java
+++ b/app/src/main/java/com/assimilate/alltrans/common/Widget.java
@@ -53,7 +53,7 @@ public class Widget {
Animation.RELATIVE_TO_SELF, 0.5f, // 以自身中心X轴为缩放中心
Animation.RELATIVE_TO_SELF, 0.5f // 以自身中心Y轴为缩放中心
);
- scaleAnimation.setDuration(700); // 动画持续时间,单位为毫秒
+ scaleAnimation.setDuration(900); // 动画持续时间,单位为毫秒
scaleAnimation.setFillAfter(true); // 动画结束后保持放大状态
scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
diff --git a/app/src/main/java/com/assimilate/alltrans/curview/ControlView.kt b/app/src/main/java/com/assimilate/alltrans/curview/ControlView.kt
index 27981c9..bf566be 100644
--- a/app/src/main/java/com/assimilate/alltrans/curview/ControlView.kt
+++ b/app/src/main/java/com/assimilate/alltrans/curview/ControlView.kt
@@ -117,35 +117,36 @@ class ControlView(private val context: Context) {
listener?.onCopyClick()
}
- binding.tvSusPhoto.setOnClickListener {
- val intent = Intent(context, PhotoImageActivity::class.java)
- intent.putExtra("key_start_ph", "hover")
- val pendingIntent = PendingIntent.getActivity(
- context,
- 0,
- intent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
- pendingIntent.send()
- removeControlView()
- }
-
binding.tvSusDistrict.setOnClickListener {
binding.susControlRoot.visibility = View.GONE
Log.d("ControlViewManager", "District translation clicked")
listener?.onDistrictClick()
}
- binding.ivSusHome.setOnClickListener {
- Log.d("ControlViewManager", "Home clicked")
- val intent = Intent(context, MainActivity::class.java)
+ binding.tvSusPhoto.setOnClickListener {
+ val intentPh = Intent(context, PhotoImageActivity::class.java)
+ intentPh.putExtra("sus_ph", "sus_ph")
val pendingIntent = PendingIntent.getActivity(
context,
0,
- intent,
+ intentPh,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
pendingIntent.send()
+ removeControlView()
+ }
+
+ binding.ivSusHome.setOnClickListener {
+ val intentHome = Intent(context, MainActivity::class.java)
+ intentHome.putExtra("sus_home","sus_home")
+ val pendingIntent = PendingIntent.getActivity(
+ context,
+ 0,
+ intentHome,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
+ pendingIntent.send()
+ removeControlView()
}
}
diff --git a/app/src/main/java/com/assimilate/alltrans/curview/CopyTextView.kt b/app/src/main/java/com/assimilate/alltrans/curview/CopyTextView.kt
index 7edbdac..465e8d6 100644
--- a/app/src/main/java/com/assimilate/alltrans/curview/CopyTextView.kt
+++ b/app/src/main/java/com/assimilate/alltrans/curview/CopyTextView.kt
@@ -1,22 +1,25 @@
package com.assimilate.alltrans.curview
-import android.content.ClipData
-import android.content.ClipboardManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.media.Image
import android.media.ImageReader
import android.os.Build
-import android.text.TextUtils
import android.util.Log
+import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
+import android.widget.TextView
import android.widget.Toast
+import com.assimilate.alltrans.R
+import com.assimilate.alltrans.common.MyTextTools
+import com.assimilate.alltrans.common.TextGraphic
import com.assimilate.alltrans.common.TextRecognitionProcessor
import com.assimilate.alltrans.common.VisionImageProcessor
import com.assimilate.alltrans.databinding.LayoutSusCopyBinding
+import com.google.android.material.snackbar.Snackbar
import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions
import java.io.IOException
@@ -39,7 +42,7 @@ class CopyTextView(private val context: Context) :
// 这里还需要调整
imageProcessor = TextRecognitionProcessor(
context,
- ChineseTextRecognizerOptions.Builder().build(), true, false, "", this
+ ChineseTextRecognizerOptions.Builder().build(), this
)
val inflater = LayoutInflater.from(context)
@@ -68,9 +71,8 @@ class CopyTextView(private val context: Context) :
removeView()
}
binding?.btSusCopyAll?.setOnClickListener {
+ MyTextTools.copyToClipboard(context, recognizedText.toString())
- Log.d("gdsfsfsadf", recognizedText.toString())
- copyToClipboard(recognizedText.toString())
// removeView()
}
@@ -124,7 +126,6 @@ class CopyTextView(private val context: Context) :
imageProcessor!!.processBitmap(bitmap, binding?.susGraphicOverlay)
-
} else {
Log.e(
"SusService",
@@ -136,29 +137,19 @@ class CopyTextView(private val context: Context) :
}
}
-
override fun onTextRecognized(text: Text, graphicOverlay: GraphicOverlay) {
recognizedText = text.text
+ graphicOverlay.add(
+ TextGraphic(
+ graphicOverlay,
+ text, true, false, ""
+ )
+ )
+
}
override fun onTextFailure(e: Exception) {
- Log.d("copy_", e.toString())
+ // Log.d("copy_", e.toString())
}
- // 复制到粘贴板
- private fun copyToClipboard(text: String?) {
- val tip = "Copied to clipboard!"
- val tipNull = "Text is null!"
- if (!TextUtils.isEmpty(text)) {
- val clipboardManager =
- context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
- val clipData = ClipData.newPlainText("targetValue", text)
- clipboardManager.setPrimaryClip(clipData)
- Toast.makeText(context, tip, Toast.LENGTH_SHORT).show()
- } else {
- Toast.makeText(context, tipNull, Toast.LENGTH_SHORT).show()
- }
- }
-
-
}
diff --git a/app/src/main/java/com/assimilate/alltrans/curview/DistrictView.kt b/app/src/main/java/com/assimilate/alltrans/curview/DistrictView.kt
index 5b4cc53..e47dd95 100644
--- a/app/src/main/java/com/assimilate/alltrans/curview/DistrictView.kt
+++ b/app/src/main/java/com/assimilate/alltrans/curview/DistrictView.kt
@@ -19,6 +19,7 @@ import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.R
import com.assimilate.alltrans.common.FirebaseAnalyticsHelper
import com.assimilate.alltrans.common.Logger
+import com.assimilate.alltrans.common.MyTextTools
import com.assimilate.alltrans.databinding.LayoutSusDistrictBinding
import com.assimilate.alltrans.http.GoogleTranslator
import com.assimilate.alltrans.http.Translator
@@ -63,7 +64,10 @@ class DistrictView(
} else {
WindowManager.LayoutParams.TYPE_PHONE
},
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
+ WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
+ WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR,
PixelFormat.TRANSLUCENT
)
@@ -128,6 +132,48 @@ class DistrictView(
}
private fun initDistrictClick() {
+ bindingSusDistrict.ivSourceTts.setOnClickListener {
+ val lanSourceCode = LanguagesConstants.getInstance().getLanguageCodeByLanguage(
+ PreferenceLanguageUtils.getString("language_source"),
+ MyApp.applicationContext()
+ )
+ MyTextTools.ttsReadText(
+ bindingSusDistrict.tvTrSource.text.toString(), lanSourceCode, context
+ )
+ }
+ bindingSusDistrict.ivTrCopy.setOnClickListener {
+ MyTextTools.copyToClipboard(context, bindingSusDistrict.tvTrTarget.text.toString())
+ }
+ bindingSusDistrict.ivTrTargetDic.setOnClickListener {
+ if (bindingSusDistrict.tvTrTarget.text.toString().isNotEmpty()) {
+ MyTextTools.makeWordsClickableWithUnderline(
+ bindingSusDistrict.tvTrTarget,
+ bindingSusDistrict.tvTrTarget.text.toString(),
+ object : MyTextTools.OnWordClickListener {
+ override fun onWordClick(word: String?) {
+ Log.d("gvsdacd", "$word is clicked")
+ }
+
+ })
+ }
+
+ }
+// bindingSusDistrict.ivTrTargetShare.setOnClickListener {
+// MyTextTools.shareText(
+// context,
+// bindingSusDistrict.tvTrTarget.text.toString()
+// )
+// }
+ bindingSusDistrict.ivTargetTts.setOnClickListener {
+ val lanTargetCode = LanguagesConstants.getInstance().getLanguageCodeByLanguage(
+ PreferenceLanguageUtils.getString("language_target"),
+ MyApp.applicationContext()
+ )
+
+ MyTextTools.ttsReadText(
+ bindingSusDistrict.tvTrTarget.text.toString(), lanTargetCode, context
+ )
+ }
bindingSusDistrict.ivTrCollect.setOnClickListener { addCollect() }
bindingSusDistrict.ivSourceClear.setOnClickListener {
bindingSusDistrict.tvTrSource.text = ""
@@ -205,9 +251,11 @@ class DistrictView(
Handler(Looper.getMainLooper()).post {
if (!result.isNullOrEmpty()) {
bindingSusDistrict.tvTrTarget.text = result
+
} else if (!errorMessage.isNullOrEmpty()) {
Log.e("TranslationError", errorMessage)
bindingSusDistrict.tvTrTarget.text = "Translation error: $errorMessage"
+
}
}
}
@@ -219,6 +267,7 @@ class DistrictView(
"district" + errorMessage.toString()
)
bindingSusDistrict.tvTrTarget.text = "Translation failed: $errorMessage"
+
}
}
})
diff --git a/app/src/main/java/com/assimilate/alltrans/curview/FloatingView.kt b/app/src/main/java/com/assimilate/alltrans/curview/FloatingView.kt
index 4176bfd..df32a1f 100644
--- a/app/src/main/java/com/assimilate/alltrans/curview/FloatingView.kt
+++ b/app/src/main/java/com/assimilate/alltrans/curview/FloatingView.kt
@@ -21,12 +21,13 @@ import com.assimilate.alltrans.R
import com.assimilate.alltrans.common.TextGraphic
import com.assimilate.alltrans.common.TextRecognitionProcessor
import com.assimilate.alltrans.common.VisionImageProcessor
+import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions
import java.io.IOException
class FloatingView(
private val context: Context
-) {
+) : TextRecognitionProcessor.TextRecognitionCallback {
private var isAttachedToWindow = false
private var imageProcessor: VisionImageProcessor? = null
@@ -57,7 +58,7 @@ class FloatingView(
// 初始化语言识别
imageProcessor = TextRecognitionProcessor(
context,
- ChineseTextRecognizerOptions.Builder().build(), false, true, "float"
+ ChineseTextRecognizerOptions.Builder().build(), this
)
graphicOverlay = GraphicOverlay(context, null)
@@ -159,13 +160,20 @@ class FloatingView(
hasCapturedScreenshot = false
}
- try {
- windowManager.removeView(graphicOverlay)
- windowManager.updateViewLayout(imageView, params)
- } catch (e: IllegalArgumentException) {
- Log.e("FloatingView", "View not attached to window manager", e)
+ if (graphicOverlay?.isAttachedToWindow == true) {
+ try {
+ windowManager.removeView(graphicOverlay)
+ } catch (e: IllegalArgumentException) {
+ Log.e("FloatingView", "View not attached to window manager", e)
+ }
+ } else {
+ Log.e(
+ "FloatingView",
+ "Attempted to remove a view that is not attached to the window manager"
+ )
}
+ windowManager.updateViewLayout(imageView, params)
return true
}
@@ -367,4 +375,17 @@ class FloatingView(
windowManager.addView(graphicOverlay, fullScreenParams)
}
}
+
+ override fun onTextRecognized(text: Text, graphicOverlay: GraphicOverlay) {
+ graphicOverlay.add(
+ TextGraphic(
+ graphicOverlay,
+ text,
+ false, true, "float"
+ )
+ )
+ }
+
+ override fun onTextFailure(e: Exception) {
+ }
}
diff --git a/app/src/main/java/com/assimilate/alltrans/curview/GlobalView.kt b/app/src/main/java/com/assimilate/alltrans/curview/GlobalView.kt
index a0fb400..972e308 100644
--- a/app/src/main/java/com/assimilate/alltrans/curview/GlobalView.kt
+++ b/app/src/main/java/com/assimilate/alltrans/curview/GlobalView.kt
@@ -11,14 +11,16 @@ import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
+import com.assimilate.alltrans.common.TextGraphic
import com.assimilate.alltrans.common.TextRecognitionProcessor
import com.assimilate.alltrans.common.VisionImageProcessor
import com.assimilate.alltrans.databinding.LayoutSusGlobalBinding
+import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions
import java.io.IOException
-class GlobalView(private val context: Context) {
+class GlobalView(private val context: Context) : TextRecognitionProcessor.TextRecognitionCallback {
private var imageProcessor: VisionImageProcessor? = null
@@ -32,7 +34,7 @@ class GlobalView(private val context: Context) {
// 这里还需要调整
imageProcessor = TextRecognitionProcessor(
context,
- ChineseTextRecognizerOptions.Builder().build(), true, true, "global"
+ ChineseTextRecognizerOptions.Builder().build(), this
)
bindingSubGlobal = LayoutSusGlobalBinding.inflate(LayoutInflater.from(context))
globalView = bindingSubGlobal.root
@@ -125,5 +127,18 @@ class GlobalView(private val context: Context) {
}
}
+ override fun onTextRecognized(text: Text, graphicOverlay: GraphicOverlay) {
+ graphicOverlay.add(
+ TextGraphic(
+ graphicOverlay,
+ text,
+ true, true, "global"
+ )
+ )
+ }
+
+ override fun onTextFailure(e: Exception) {
+
+ }
}
diff --git a/app/src/main/java/com/assimilate/alltrans/curview/GraphicOverlay.java b/app/src/main/java/com/assimilate/alltrans/curview/GraphicOverlay.java
index a1c3950..dcaf236 100755
--- a/app/src/main/java/com/assimilate/alltrans/curview/GraphicOverlay.java
+++ b/app/src/main/java/com/assimilate/alltrans/curview/GraphicOverlay.java
@@ -297,7 +297,6 @@ public class GraphicOverlay extends View {
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
-
synchronized (lock) {
updateTransformationIfNeeded();
diff --git a/app/src/main/java/com/assimilate/alltrans/curview/SelectionView.kt b/app/src/main/java/com/assimilate/alltrans/curview/SelectionView.kt
index 26d3c94..1c77a00 100644
--- a/app/src/main/java/com/assimilate/alltrans/curview/SelectionView.kt
+++ b/app/src/main/java/com/assimilate/alltrans/curview/SelectionView.kt
@@ -12,12 +12,8 @@ import android.view.ViewGroup
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.Toast
-import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.R
-import com.assimilate.alltrans.common.CurrentActivityHolder
-import com.assimilate.alltrans.common.LolAdWrapper
import com.assimilate.alltrans.databinding.LayoutSusSelectBinding
-import com.lol.apex.ok.google.adlibrary.base.listener.LolShowError
class SelectionView(private val context: Context) {
private lateinit var binding: LayoutSusSelectBinding
@@ -51,7 +47,10 @@ class SelectionView(private val context: Context) {
} else {
WindowManager.LayoutParams.TYPE_PHONE
},
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
+ WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
+ WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR,
PixelFormat.TRANSLUCENT
)
diff --git a/app/src/main/java/com/assimilate/alltrans/model/PreferenceLanguageUtils.kt b/app/src/main/java/com/assimilate/alltrans/model/PreferenceLanguageUtils.kt
index 30b7340..a87e2af 100644
--- a/app/src/main/java/com/assimilate/alltrans/model/PreferenceLanguageUtils.kt
+++ b/app/src/main/java/com/assimilate/alltrans/model/PreferenceLanguageUtils.kt
@@ -12,6 +12,7 @@ object PreferenceLanguageUtils {
private const val KEY_RECENT_LANGUAGES = "recent_languages"
private const val MAX_RECENT_LANGUAGES = 5
private const val PREF_KEY_FIRST_TIME = "first_time"
+ private const val PREF_KEY_FIRST_ALLOW = "first_allow"
private val LANGUAGE_LIST_TYPE = object : TypeToken>() {}.type
@Volatile
@@ -85,4 +86,19 @@ object PreferenceLanguageUtils {
fun setNotFirstTime() {
getSharedPreferences().edit().putBoolean(PREF_KEY_FIRST_TIME, false).apply()
}
+
+
+ // 检查是否是第一次进入应用
+ fun isFirstAllow(): Boolean {
+ return getSharedPreferences().getBoolean(PREF_KEY_FIRST_ALLOW, true)
+ }
+
+ // 设置已经不是第一次进入应用了
+ fun setNotFirstAllow() {
+ getSharedPreferences().edit().putBoolean(PREF_KEY_FIRST_ALLOW, false).apply()
+ }
+
+
+
+
}
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/DicActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/DicActivity.kt
index 088f3a9..0b755a9 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/DicActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/DicActivity.kt
@@ -1,86 +1,310 @@
package com.assimilate.alltrans.viewui
-import android.os.AsyncTask
+import android.content.Intent
+import android.net.Uri
import android.os.Bundle
-import android.widget.Button
-import android.widget.EditText
-import android.widget.TextView
+import android.view.View
+import android.view.inputmethod.EditorInfo
+import android.view.inputmethod.InputMethodManager
+import android.webkit.WebChromeClient
+import android.webkit.WebResourceError
+import android.webkit.WebResourceRequest
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.widget.FrameLayout
+import android.widget.Toast
+import androidx.activity.OnBackPressedCallback
+import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.PopupMenu
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.R
-import org.json.JSONArray
-import org.json.JSONException
-import java.io.BufferedReader
-import java.io.InputStreamReader
-import java.net.HttpURLConnection
-import java.net.URL
+import com.assimilate.alltrans.common.FirebaseAnalyticsHelper
+import com.assimilate.alltrans.common.LolAdWrapper
+import com.assimilate.alltrans.databinding.ActivityDicBinding
+import com.lol.apex.ok.google.adlibrary.base.listener.LolLoadError
+import com.lol.apex.ok.google.adlibrary.base.listener.LolShowError
+import java.util.Locale
class DicActivity : AppCompatActivity() {
- private lateinit var editTextWord: EditText
- private lateinit var buttonSearch: Button
- private lateinit var textViewDefinition: TextView
+ private lateinit var binding: ActivityDicBinding
+ private var isWikiIng = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_dic)
-
- editTextWord = findViewById(R.id.editTextWord)
- buttonSearch = findViewById(R.id.buttonSearch)
- textViewDefinition = findViewById(R.id.textViewDefinition)
-
- buttonSearch.setOnClickListener {
- val word = editTextWord.text.toString().trim()
- if (word.isNotEmpty()) {
- FetchDefinitionTask().execute(word)
- }
+ binding = ActivityDicBinding.inflate(layoutInflater)
+ enableEdgeToEdge()
+ setContentView(binding.root)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.dic_root)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
}
+
+ // 初始化ProgressBar
+ binding.wikiProgressBar.visibility = View.GONE
+ adLoad(MyApp.Config.directory_int_auto)
+
+ intiClick()
+ backPressedCall()
+
}
- private inner class FetchDefinitionTask : AsyncTask() {
- override fun doInBackground(vararg params: String): String? {
- val word = params[0]
- val apiUrl = "https://api.dictionaryapi.dev/api/v2/entries/en/$word"
- return try {
- val url = URL(apiUrl)
- val urlConnection = url.openConnection() as HttpURLConnection
- urlConnection.requestMethod = "GET"
- val responseCode = urlConnection.responseCode
- if (responseCode == HttpURLConnection.HTTP_OK) {
- val inputStream = BufferedReader(InputStreamReader(urlConnection.inputStream))
- val response = StringBuilder()
- var inputLine: String?
- while (inputStream.readLine().also { inputLine = it } != null) {
- response.append(inputLine)
+ private fun intiClick() {
+ binding.ivDicMore.setOnClickListener {
+ // 创建 PopupMenu
+ val popupMenu = PopupMenu(this, it)
+ // 关联菜单资源文件
+ popupMenu.menuInflater.inflate(R.menu.popup_menu, popupMenu.menu)
+ // 设置菜单项点击事件
+ popupMenu.setOnMenuItemClickListener { menuItem ->
+ when (menuItem.itemId) {
+ R.id.action_one -> {
+
+ if (binding.editTextWord.text.toString().isNotEmpty()) {
+ val url = generateWiktionaryUrl(binding.editTextWord.text.toString())
+ // 创建Intent
+ val intent = Intent(Intent.ACTION_VIEW).apply {
+ data = Uri.parse(url)
+ }
+
+ // 启动浏览器
+ startActivity(intent)
+ } else {
+ Toast.makeText(this, R.string.dic_et, Toast.LENGTH_SHORT).show()
+ }
+
+ // 处理第一个菜单项的点击事件
+ true
}
- inputStream.close()
- response.toString()
- } else {
- null
+
+ else -> false
}
- } catch (e: Exception) {
- e.printStackTrace()
- null
+ }
+
+ // 显示 PopupMenu
+ popupMenu.show()
+ }
+
+ binding.editTextWord.setOnEditorActionListener { _, actionId, _ ->
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ // 隐藏键盘
+ val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
+ imm.hideSoftInputFromWindow(binding.editTextWord.windowToken, 0)
+ true
+ } else {
+ false
}
}
- override fun onPostExecute(result: String?) {
- if (result != null) {
- try {
- val jsonArray = JSONArray(result)
- val jsonObject = jsonArray.getJSONObject(0)
- val meanings = jsonObject.getJSONArray("meanings")
- val meaning = meanings.getJSONObject(0)
- val definitions = meaning.getJSONArray("definitions")
- val definition = definitions.getJSONObject(0)
- val definitionText = definition.getString("definition")
- textViewDefinition.text = definitionText
- } catch (e: JSONException) {
- e.printStackTrace()
- textViewDefinition.text = "Error parsing definition"
+ binding.ivDicBack.setOnClickListener {
+ showInstAdFromCache(MyApp.Config.directory_int_auto)
+ finish()
+ }
+ binding.buttonSearch.setOnClickListener {
+ val word = binding.editTextWord.text.toString().trim()
+ if (word.isNotEmpty()) {
+ if (!isWikiIng) {
+ getWeb(word)
+ } else {
+ Toast.makeText(this, R.string.dic_wikiing, Toast.LENGTH_SHORT).show()
}
+
} else {
- textViewDefinition.text = "Definition not found"
+ Toast.makeText(this, R.string.dic_et, Toast.LENGTH_SHORT).show()
}
+ FirebaseAnalyticsHelper.directoryTransClickEvent()
}
}
+
+
+ private fun backPressedCall() {
+ val callback = object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ showInstAdFromCache(MyApp.Config.directory_int_auto)
+ finish()
+ }
+ }
+ onBackPressedDispatcher.addCallback(this, callback)
+ }
+
+ private fun getWeb(word: String) {
+ // 显示 ProgressBar
+ binding.wikiProgressBar.visibility = View.VISIBLE
+ isWikiIng = true
+ // 创建 WebView 实例并配置
+ val webView = createConfiguredWebView()
+
+ // 设置 WebView 浏览器客户端
+ webView.webViewClient = object : WebViewClient() {
+ override fun onPageFinished(view: WebView?, url: String?) {
+ super.onPageFinished(view, url)
+ // 注入 JavaScript 隐藏指定区域
+ injectJavaScript(view)
+ // 加载完成后隐藏 ProgressBar
+ binding.wikiProgressBar.visibility = View.GONE
+ isWikiIng = false
+
+ }
+
+ override fun onReceivedError(
+ view: WebView?,
+ request: WebResourceRequest?,
+ error: WebResourceError?
+ ) {
+ super.onReceivedError(view, request, error)
+ // 加载失败后隐藏 ProgressBar
+ binding.wikiProgressBar.visibility = View.GONE
+ isWikiIng = false
+ FirebaseAnalyticsHelper.directoryTransResultEvent(
+ MyApp.Config.FAIL_REASON,
+ error.toString()
+ )
+ }
+ }
+
+ webView.webChromeClient = WebChromeClient()
+
+ // 设置 WebView 布局参数并添加到视图中
+ val params = FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT
+ )
+ webView.layoutParams = params
+ binding.toUrl.addView(webView)
+ // 加载指定的 URL
+ webView.loadUrl(generateWiktionaryUrl(word))
+ }
+
+ // 创建并配置 WebView
+ private fun createConfiguredWebView(): WebView {
+ val webView = WebView(this)
+ val settings = webView.settings
+
+ settings.loadsImagesAutomatically = true
+ settings.javaScriptEnabled = true
+ settings.domStorageEnabled = true
+ WebView.setWebContentsDebuggingEnabled(false)
+
+ return webView
+ }
+
+ // 注入 JavaScript 脚本隐藏指定区域
+ private fun injectJavaScript(view: WebView?) {
+ view?.loadUrl(
+ """
+ javascript:(function() {
+
+ var mainTitle = document.getElementById('firstHeading');
+ if (mainTitle) {
+ mainTitle.style.color = 'rgb(16, 171, 251)';
+ mainTitle.style.fontWeight = 'bold';
+ mainTitle.style.fontSize = '43px';
+ }
+
+ var bodyContent = document.getElementById('bodyContent');
+ if (bodyContent) {
+ bodyContent.style.marginBottom = '55px';
+ }
+
+ var header = document.getElementsByClassName('minerva-header');
+ if (header.length > 0) {
+ header[0].style.display = 'none';
+ }
+
+ var footer = document.getElementsByClassName('post-content footer-content');
+ if (footer.length > 0) {
+ footer[0].style.display = 'none';
+ }
+
+ var minerva_footer = document.getElementsByClassName('mw-footer minerva-footer');
+ if (minerva_footer.length > 0) {
+ minerva_footer[0].style.display = 'none';
+ }
+
+ var last_modified_bar = document.getElementsByClassName('post-content last-modified-bar__content');
+ if (last_modified_bar.length > 0) {
+ last_modified_bar[0].style.display = 'none';
+ }
+
+ var actionsMenu = document.getElementsByClassName('page-actions-menu');
+ if (actionsMenu.length > 0) {
+ actionsMenu[0].style.display = 'none';
+ }
+
+ var editSections = document.getElementsByClassName('mw-editsection');
+ for (var i = 0; i < editSections.length; i++) {
+ editSections[i].style.display = 'none';
+ }
+ })();
+ """.trimIndent()
+ )
+ }
+
+ private fun generateWiktionaryUrl(word: String?): String {
+ // 检查传入的字符串是否为空或null
+ if (word.isNullOrBlank()) {
+ throw IllegalArgumentException("Word cannot be null or blank")
+ }
+
+ val language = try {
+ // 获取本地语言,若获取失败则抛出异常
+ Locale.getDefault().language
+ } catch (e: Exception) {
+ throw RuntimeException("Unable to retrieve the default language", e)
+ }
+
+ val lowerCaseWord = try {
+ // 将传入字符串转换为小写,若转换失败则抛出异常
+ word.lowercase(Locale.ROOT)
+ } catch (e: Exception) {
+ throw RuntimeException("Unable to convert word to lowercase", e)
+ }
+
+ return "https://$language.m.wiktionary.org/wiki/$lowerCaseWord"
+ }
+
+
+ private fun adLoad(place: String) {
+ // 加载广告
+ LolAdWrapper.shared.loadAdIfNotCached(
+ this,
+ place,
+ object : LolAdWrapper.LoLLoadListener {
+ override fun loadFailed(error: LolLoadError?) {
+ }
+
+ override fun loaded() {
+ // 处理加载成功
+ }
+ })
+
+ }
+
+ private fun showInstAdFromCache(place: String) {
+ // 如果需要立刻展示广告,可以调用展示方法
+ LolAdWrapper.shared.showAdIfCached(
+ this,
+ place,
+ object : LolAdWrapper.LolShowListener {
+ override fun shown() {
+ // 处理广告展示成功
+ }
+
+ override fun showFailed(error: LolShowError?) {
+ // 处理广告展示失败
+ finish()
+ }
+
+ override fun closed() {
+ // 处理广告关闭
+ finish()
+ }
+ })
+ }
+
+
}
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/LanguageChangeActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/LanguageChangeActivity.kt
index 189e743..2ccc659 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/LanguageChangeActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/LanguageChangeActivity.kt
@@ -121,16 +121,22 @@ class LanguageChangeActivity : AppCompatActivity() {
}
private fun handleLanguageSelection(language: Language) {
- Log.d("LanguageChange", language.language)
+ // Log.d("LanguageChange", language.language)
if (lastTranslateLanguage) {
PreferenceLanguageUtils.putString("language_target", language.language)
+
+ FirebaseAnalyticsHelper.languageChooseEvent(
+ MyApp.Config.LAN_TARGET,
+ "target_${language.language}"
+ )
} else {
PreferenceLanguageUtils.putString("language_source", language.language)
+ FirebaseAnalyticsHelper.languageChooseEvent(
+ MyApp.Config.LAN_SOURCE,
+ "source_${language.language}"
+ )
}
- FirebaseAnalyticsHelper.languageChooseEvent(
- MyApp.Config.CLICK_FROM,
- if (lastTranslateLanguage) "target_${language.language}" else "source_${language.language}"
- )
+
FirebaseAnalyticsHelper.languageFromEvent(
MyApp.Config.CLICK_FROM,
if (lastTranslateLanguage) "home_target" else "home_source"
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/MainActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/MainActivity.kt
index ec4c3b7..b3170bc 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/MainActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/MainActivity.kt
@@ -34,6 +34,7 @@ import com.assimilate.alltrans.databinding.ActivityMainBinding
import com.assimilate.alltrans.model.LanguagesConstants
import com.assimilate.alltrans.model.PreferenceLanguageUtils
import com.google.mlkit.nl.languageid.LanguageIdentification
+import java.util.Locale
class MainActivity : AppCompatActivity() {
@@ -100,6 +101,8 @@ class MainActivity : AppCompatActivity() {
Widget.makeToast(this, "To allow floating windows for quick translation.")
}
} else if (requestCode == REQUEST_CODE_MEDIA_PROJECTION) {
+ // 第一次授权后将正常走hot
+ MyApp.app.isFirstPremisiton = false
// 处理mediaProjectionManager权限请求结果
if (resultCode == RESULT_OK) {
serverIsStart = true
@@ -128,10 +131,11 @@ class MainActivity : AppCompatActivity() {
}
- private fun initView(){
+ private fun initView() {
binding.chSourceLanguage.text = PreferenceLanguageUtils.getString("language_source")
binding.chTargetLanguage.text = PreferenceLanguageUtils.getString("language_target")
}
+
private fun initSet() {
loadNative()
@@ -156,7 +160,8 @@ class MainActivity : AppCompatActivity() {
private fun initClick() {
binding.tvMainDic.setOnClickListener {
- // startActivity(Intent(this,DicActivity::class.java))
+ startActivity(Intent(this, DicActivity::class.java))
+ FirebaseAnalyticsHelper.directoryClickEvent()
}
binding.tvMainPhotoTrans.setOnClickListener {
@@ -206,6 +211,7 @@ class MainActivity : AppCompatActivity() {
// )
}
binding.ivQuickStart.setOnClickListener {
+
if (!serverIsStart) {
// 检查并请求悬浮窗权限
if (!Settings.canDrawOverlays(this)) {
@@ -214,6 +220,7 @@ class MainActivity : AppCompatActivity() {
Uri.parse("package:$packageName")
)
startActivityForResult(intent, REQUEST_CODE_OVERLAY)
+ MyApp.app.isFirstPremisiton = true
} else {
FirebaseAnalyticsHelper.hoverLimitAgreeEvent()
checkAndRequestMediaProjectionPermission()
@@ -283,6 +290,7 @@ class MainActivity : AppCompatActivity() {
}
private fun checkAndRequestMediaProjectionPermission() {
+
// 启动截图
startActivityForResult(
mediaProjectionManager.createScreenCaptureIntent(),
@@ -383,7 +391,7 @@ class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
- initView()
+ initView()
}
override fun onRestart() {
@@ -427,7 +435,7 @@ class MainActivity : AppCompatActivity() {
)
}
- private fun reconText(text:String){
+ private fun reconText(text: String) {
val languageIdentifier = LanguageIdentification.getClient()
languageIdentifier.identifyLanguage(text)
.addOnSuccessListener { languageCode ->
@@ -436,9 +444,11 @@ class MainActivity : AppCompatActivity() {
} else {
Log.i("dsafdsf", "Language: $languageCode")
- val lan = LanguagesConstants.getInstance().getLanguageByLanguageCode(languageCode,this)
- PreferenceLanguageUtils.putString("language_source",lan.language)
- binding.chSourceLanguage.text = PreferenceLanguageUtils.getString("language_source")
+ val lan = LanguagesConstants.getInstance()
+ .getLanguageByLanguageCode(languageCode, this)
+ PreferenceLanguageUtils.putString("language_source", lan.language)
+ binding.chSourceLanguage.text =
+ PreferenceLanguageUtils.getString("language_source")
}
}
.addOnFailureListener {
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/PhotoImageActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/PhotoImageActivity.kt
index e9367e3..698cc62 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/PhotoImageActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/PhotoImageActivity.kt
@@ -37,16 +37,19 @@ import com.assimilate.alltrans.adapters.LanguageAdapter
import com.assimilate.alltrans.common.BitmapUtils
import com.assimilate.alltrans.common.FirebaseAnalyticsHelper
import com.assimilate.alltrans.common.LolAdWrapper
+import com.assimilate.alltrans.common.TextGraphic
import com.assimilate.alltrans.model.Language
import com.assimilate.alltrans.model.LanguagesConstants
import com.assimilate.alltrans.model.PreferenceLanguageUtils
import com.assimilate.alltrans.common.TextRecognitionProcessor
import com.assimilate.alltrans.common.VisionImageProcessor
import com.assimilate.alltrans.common.Widget
+import com.assimilate.alltrans.curview.GraphicOverlay
import com.assimilate.alltrans.databinding.ActivityStillImageBinding
import com.google.android.gms.common.annotation.KeepName
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.common.util.concurrent.ListenableFuture
+import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions
import com.google.mlkit.vision.text.devanagari.DevanagariTextRecognizerOptions
import com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions
@@ -62,7 +65,7 @@ import kotlin.math.max
import kotlin.math.min
@KeepName
-class PhotoImageActivity : AppCompatActivity() {
+class PhotoImageActivity : AppCompatActivity(), TextRecognitionProcessor.TextRecognitionCallback {
private var selectedMode = TEXT_RECOGNITION_CHINESE
private var selectedSize: String? = SIZE_SCREEN
@@ -74,8 +77,10 @@ class PhotoImageActivity : AppCompatActivity() {
private lateinit var imageCapture: ImageCapture
private lateinit var outputDirectory: File
private lateinit var cameraProviderFuture: ListenableFuture
+
private var isFlashOn = false
private var fbFrom = "photo"
+ private var needReshoot = false
private val REQUEST_CAMERA_PERMISSION = 100
private lateinit var bottomSheetDialog: BottomSheetDialog
@@ -151,7 +156,7 @@ class PhotoImageActivity : AppCompatActivity() {
}
- private fun initView() {
+ private fun initView() {
binding.photoPreview.visibility = View.VISIBLE
@@ -216,7 +221,7 @@ class PhotoImageActivity : AppCompatActivity() {
private fun initList() {
val languages: ArrayList = LanguagesConstants.getInstance().getList(this)
if (languages.isNotEmpty()) {
- val adapter = LanguageAdapter(this, languages) { _, language ->
+ val myAdapter = LanguageAdapter(this, languages) { _, language ->
if (!chooseLanguage) {
PreferenceLanguageUtils.putString("language_source", language.language)
@@ -245,9 +250,16 @@ class PhotoImageActivity : AppCompatActivity() {
binding.stillTargetLanguage.text =
PreferenceLanguageUtils.getString("language_target")
}
- bottomSheetDialog.findViewById(R.id.list_languages)?.layoutManager =
- LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
- bottomSheetDialog.findViewById(R.id.list_languages)?.adapter = adapter
+ bottomSheetDialog.findViewById(R.id.list_languages)?.apply {
+ layoutManager =
+ LinearLayoutManager(
+ this@PhotoImageActivity,
+ LinearLayoutManager.VERTICAL,
+ false
+ )
+ adapter = myAdapter
+ }
+
}
}
@@ -257,11 +269,21 @@ class PhotoImageActivity : AppCompatActivity() {
startChooseImageIntentForResult()
FirebaseAnalyticsHelper.imageTransPhotoEvent()
}
- binding.ivStillTake.setOnClickListener {
- binding.photoPreview.visibility = View.VISIBLE
+ binding.ivReshoot.setOnClickListener {
+ needReshoot = false
+ binding.photoPreview.visibility = View.VISIBLE
+ binding.preview.setImageBitmap(null)
+ binding.graphicOverlay.clear()
+
+ }
+ binding.ivStillTake.setOnClickListener {
+
+ if (needReshoot) return@setOnClickListener
+ binding.photoPreview.visibility = View.VISIBLE
takePhoto()
FirebaseAnalyticsHelper.imageTransCameraEvent()
+ needReshoot = true
}
binding.ivStillBack.setOnClickListener {
showInstAdFromCache(MyApp.Config.image_camera_int_auto)
@@ -413,31 +435,30 @@ class PhotoImageActivity : AppCompatActivity() {
private fun createImageProcessor() {
imageProcessor?.stop()
try {
-
imageProcessor = when (selectedMode) {
TEXT_RECOGNITION_CHINESE -> TextRecognitionProcessor(
this,
- ChineseTextRecognizerOptions.Builder().build(), true, true, fbFrom
+ ChineseTextRecognizerOptions.Builder().build(), this
)
"Hindi", "Marathi", "Nepali", "Sanskrit" -> TextRecognitionProcessor(
this,
- DevanagariTextRecognizerOptions.Builder().build(), true, true, fbFrom
+ DevanagariTextRecognizerOptions.Builder().build(), this
)
TEXT_RECOGNITION_JAPANESE -> TextRecognitionProcessor(
this,
- JapaneseTextRecognizerOptions.Builder().build(), true, true, fbFrom
+ JapaneseTextRecognizerOptions.Builder().build(), this
)
TEXT_RECOGNITION_KOREAN -> TextRecognitionProcessor(
this,
- KoreanTextRecognizerOptions.Builder().build(), true, true, fbFrom
+ KoreanTextRecognizerOptions.Builder().build(), this
)
else -> TextRecognitionProcessor(
this,
- TextRecognizerOptions.Builder().build(), true, true, fbFrom
+ TextRecognizerOptions.Builder().build(), this
)
}
@@ -586,6 +607,22 @@ class PhotoImageActivity : AppCompatActivity() {
private const val REQUEST_CHOOSE_IMAGE = 1001
}
+ override fun onTextRecognized(text: Text, graphicOverlay: GraphicOverlay) {
+ graphicOverlay.add(
+ TextGraphic(
+ graphicOverlay,
+ text,
+ true, true,
+ fbFrom
+ )
+ )
+
+ }
+
+ override fun onTextFailure(e: Exception) {
+
+ }
+
}
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/QuickSetActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/QuickSetActivity.kt
index 67261e7..a6e4a1f 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/QuickSetActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/QuickSetActivity.kt
@@ -35,7 +35,6 @@ class QuickSetActivity : AppCompatActivity() {
}
private fun sliderSet() {
-
binding.slider1.setLabelFormatter { value ->
val percentage = ((value / 5) * 100).toInt()
"$percentage%"
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/SettingsActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/SettingsActivity.kt
index 3113b4a..2d9786a 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/SettingsActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/SettingsActivity.kt
@@ -2,18 +2,25 @@ package com.assimilate.alltrans.viewui
import android.content.Intent
import android.content.pm.PackageManager
+import android.content.res.Configuration
import android.net.Uri
+import android.os.Build
import android.os.Bundle
+import android.view.Gravity
+import android.view.MenuInflater
+import android.view.View
import android.widget.RatingBar
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.PopupMenu
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.assimilate.alltrans.R
import com.assimilate.alltrans.databinding.ActivitySettingsBinding
import com.google.android.material.bottomsheet.BottomSheetDialog
+import java.util.Locale
class SettingsActivity
@@ -22,6 +29,8 @@ class SettingsActivity
private lateinit var bottomSheetDialog: BottomSheetDialog
private var userChoose = 1
+ private val languageCodes = mutableListOf("en", "zh")
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
@@ -44,6 +53,9 @@ class SettingsActivity
}
private fun initClick() {
+
+// binding.llLanguages.setOnClickListener(this::showLanguagePopup)
+
binding.ivSetBack.setOnClickListener { finish() }
binding.llRate.setOnClickListener {
bottomSheetDialog.show()
@@ -96,7 +108,7 @@ class SettingsActivity
private fun setBottomSheet() {
// 设置 BottomSheetDialog
- bottomSheetDialog = BottomSheetDialog(this,R.style.CustomBottomSheetDialogTheme)
+ bottomSheetDialog = BottomSheetDialog(this, R.style.CustomBottomSheetDialogTheme)
bottomSheetDialog.setContentView(R.layout.bottomsheet_rate)
bottomSheetDialog.dismissWithAnimation = true
@@ -145,4 +157,56 @@ class SettingsActivity
}
+ private fun showLanguagePopup(view: View) {
+ val popupMenu = PopupMenu(this, view, Gravity.END)
+ val inflater: MenuInflater = popupMenu.menuInflater
+ inflater.inflate(R.menu.language_menu, popupMenu.menu)
+
+ popupMenu.setOnMenuItemClickListener { item ->
+ when (item.itemId) {
+ R.id.language_english -> {
+ setLocale(languageCodes[0])
+ return@setOnMenuItemClickListener true
+ }
+
+ R.id.language_chinese -> {
+ setLocale(languageCodes[1])
+ return@setOnMenuItemClickListener true
+ }
+
+ else -> return@setOnMenuItemClickListener false
+ }
+ }
+
+ popupMenu.show()
+ }
+
+ private fun setLocale(lang: String) {
+ val locale = Locale(lang)
+ Locale.setDefault(locale)
+ val config = Configuration()
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ config.setLocale(locale)
+ } else {
+ config.locale = locale
+ }
+
+ // 更新资源配置
+ resources.updateConfiguration(config, resources.displayMetrics)
+ // 创建新的配置上下文
+ baseContext.createConfigurationContext(config)
+
+// // 保存用户选择的语言
+// val editor = getSharedPreferences("Settings", MODE_PRIVATE).edit()
+// editor.putString("My_Lang", lang)
+// editor.apply()
+
+ // 重新启动Activity以应用语言更改
+// val intent = Intent(this, SettingsActivity::class.java)
+// startActivity(intent)
+// finish()
+ }
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/TextResultActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/TextResultActivity.kt
index ad28d16..1cc90ca 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/TextResultActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/TextResultActivity.kt
@@ -47,6 +47,7 @@ class TextResultActivity : AppCompatActivity() {
}
private fun initSet() {
+ loadNative()
backPressedCall()
adLoad(MyApp.Config.text_trans_int_auto)
adLoad(MyApp.Config.text_new_int_auto)
@@ -59,6 +60,16 @@ class TextResultActivity : AppCompatActivity() {
}
+ private fun loadNative() {
+ LolAdWrapper.shared.loadAdShowNativeAd(
+ this,
+ MyApp.Config.text_trans_native_auto,
+ binding.textNative,
+ R.layout.ad_layout_admob_banner,
+ R.layout.ad_layout_max_banner
+ )
+ }
+
private fun backPressedCall() {
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
@@ -70,6 +81,8 @@ class TextResultActivity : AppCompatActivity() {
}
private fun initClick() {
+
+
binding.ivTrBack.setOnClickListener {
showInstAdFromCache(MyApp.Config.text_trans_int_auto)
finish()
@@ -86,7 +99,7 @@ class TextResultActivity : AppCompatActivity() {
MyTextTools.copyToClipboard(this, binding.tvTrTarget.text.toString())
FirebaseAnalyticsHelper.textTransCopyEvent()
}
- binding.ivSourceClear.setOnClickListener { finish() }
+// binding.ivSourceClear.setOnClickListener { finish() }
binding.ivSourceTts.setOnClickListener {
MyTextTools.ttsReadText(
binding.tvTrSource.text.toString(),
@@ -201,7 +214,6 @@ class TextResultActivity : AppCompatActivity() {
}
-
private fun doBack() {
finish()
}
@@ -247,7 +259,6 @@ class TextResultActivity : AppCompatActivity() {
doBack()
}
-
}
override fun closed() {
diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/WelActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/WelActivity.kt
index b4d9e31..1621aed 100644
--- a/app/src/main/java/com/assimilate/alltrans/viewui/WelActivity.kt
+++ b/app/src/main/java/com/assimilate/alltrans/viewui/WelActivity.kt
@@ -2,9 +2,9 @@ package com.assimilate.alltrans.viewui
import android.content.Intent
import android.os.Bundle
-import android.util.Log
-import android.view.ViewGroup
-import android.widget.Button
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
import androidx.activity.OnBackPressedCallback
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
@@ -17,14 +17,80 @@ import com.assimilate.alltrans.databinding.ActivityWelBinding
import com.lol.apex.ok.google.adlibrary.base.listener.LolLoadError
import com.lol.apex.ok.google.adlibrary.base.listener.LolShowError
-class WelActivity : AppCompatActivity(){
+class WelActivity : AppCompatActivity() {
+ companion object {
+ private const val MSG_PROGRESS = 0
+ private const val MSG_LOAD_AD_LOADED = 1
+ private const val MSG_LOAD_AD_FAIL = 2
+ }
+
private lateinit var binding: ActivityWelBinding
+
+ private val mMaxLoading = 10 * 1000L//最大超时
+ private var progress = 0f
+ private val delayMillis = mMaxLoading / 100
+ private var place: String = MyApp.Config.start_cold_int_auto
+
+
+ private val handler = object : Handler(Looper.getMainLooper()) {
+ override fun handleMessage(msg: Message) {
+ val progressBar = binding.customProgressBar
+ if (!isFinishing && !isDestroyed) {
+
+ when (msg.what) {
+ MSG_PROGRESS -> {
+ if (progress >= 100f) {//超时
+ //超时就是没有广告,就是广告show失败了
+ toNextPage()
+ return
+ }
+ if (adCanShow()) {
+ //能展示走展示,移除进度,结束循环
+ sendEmptyMessageDelayed(MSG_LOAD_AD_LOADED, delayMillis)
+ removeMessages(MSG_PROGRESS)
+ return
+ }
+
+ // 继续加载进度,除非上面条件有成立
+ progress += 1
+ progressBar.progress = progress.toInt()
+ sendEmptyMessageDelayed(MSG_PROGRESS, delayMillis)
+ }
+
+ MSG_LOAD_AD_LOADED -> {
+
+ //展示广告,移除加载,移除进度条,结束循环
+ // if (progress >= 100f) {
+ showAd()
+ removeMessages(MSG_LOAD_AD_LOADED)
+ removeMessages(MSG_PROGRESS)
+ return
+ // }
+
+// progress += 1
+// progressBar.progress = progress.toInt()
+// sendEmptyMessageDelayed(MSG_LOAD_AD_LOADED, delayMillis)
+ }
+
+ MSG_LOAD_AD_FAIL -> {
+ if (progress < 77f) {
+ progress = 77f
+ }
+ // 失败走进度条,移除失败
+ sendEmptyMessageDelayed(MSG_PROGRESS, delayMillis)
+ removeMessages(MSG_LOAD_AD_FAIL)
+ // removeMessages(MSG_PROGRESS)
+ }
+ }
+ }
+ }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
binding = ActivityWelBinding.inflate(layoutInflater)
setContentView(binding.root)
- //debugFirebase()
ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
@@ -35,30 +101,20 @@ class WelActivity : AppCompatActivity(){
initSet()
}
- private fun debugFirebase() {
- val crashButton = Button(this)
- crashButton.text = "Test Crash"
- crashButton.setOnClickListener {
- throw RuntimeException("Test Crash") // Force a crash
- }
-
- addContentView(
- crashButton, ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- )
- }
-
private fun initSet() {
backPressedCall()
- if (MyApp.app.isFirstLaunch) {
- adSplash(MyApp.Config.start_cold_int_auto)
- } else {
- adSplashHot(MyApp.Config.start_hot_int_auto)
- }
- }
+ // 判断走冷启动还是热启动广告
+ place = if (!MyApp.app.isFirstLaunch) {
+ MyApp.Config.start_cold_int_auto
+ } else {
+ MyApp.Config.start_hot_int_auto
+
+ }
+ //请求广告,启动进度条
+ loadAd()
+ handler.sendEmptyMessageDelayed(MSG_PROGRESS, delayMillis)
+ }
private fun backPressedCall() {
val callback = object : OnBackPressedCallback(true) {
@@ -73,83 +129,45 @@ class WelActivity : AppCompatActivity(){
FirebaseAnalyticsHelper.launchPvEvent()
}
-
private fun toNextPage() {
- startActivity(Intent(this@WelActivity, MainActivity::class.java))
+ // 热启动关闭加载页,冷启动进入主页
+ if (MyApp.app.isFirstLaunch) {
+ startActivity(Intent(this@WelActivity, MainActivity::class.java))
+ } else {
+ finish()
+ }
}
- private fun adSplash(place: String) {
- // 加载广告
- LolAdWrapper.shared.loadAdIfNotCached(
+ private fun loadAd() {
+ LolAdWrapper.shared.loadAd(
this,
place,
object : LolAdWrapper.LoLLoadListener {
override fun loadFailed(error: LolLoadError?) {
- // 处理加载失败
+ handler.sendEmptyMessage(MSG_LOAD_AD_FAIL)
+ }
+ })
+ LolAdWrapper.shared.loadAdIfNotCached(this, MyApp.Config.backup_int_auto)
+
+
+ }
+
+ private fun adCanShow(): Boolean {
+ return LolAdWrapper.shared.hasCache(place)
+ }
+
+ private fun showAd() {
+ LolAdWrapper.shared.showAdIfCached(
+ this,
+ place,
+ object : LolAdWrapper.LolShowListener {
+ override fun closed() {
toNextPage()
}
- override fun loaded() {
- // 处理加载成功
- // 如果需要立刻展示广告,可以调用展示方法
- LolAdWrapper.shared.showAdIfCached(
- this@WelActivity,
- place,
- object : LolAdWrapper.LolShowListener {
- override fun shown() {
- // 处理广告展示成功
- Log.d("fcasc", place)
- }
-
- override fun showFailed(error: LolShowError?) {
- // 处理广告展示失败
- toNextPage()
- }
-
- override fun closed() {
- // 处理广告关闭
- toNextPage()
- }
- })
+ override fun showFailed(error: LolShowError?) {
+ toNextPage()
}
})
-
- }
-
- private fun adSplashHot(place: String) {
- // 加载广告
- LolAdWrapper.shared.loadAdIfNotCached(
- this,
- place,
- object : LolAdWrapper.LoLLoadListener {
- override fun loadFailed(error: LolLoadError?) {
- // 处理加载失败
- finish()
- }
-
- override fun loaded() {
- // 处理加载成功
- // 如果需要立刻展示广告,可以调用展示方法
- LolAdWrapper.shared.showAdIfCached(
- this@WelActivity,
- place,
- object : LolAdWrapper.LolShowListener {
- override fun shown() {
- // 处理广告展示成功
- }
-
- override fun showFailed(error: LolShowError?) {
- // 处理广告展示失败
- finish()
- }
-
- override fun closed() {
- // 处理广告关闭
- finish()
- }
- })
- }
- })
-
}
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_wel_bg.xml b/app/src/main/res/drawable/ic_wel_bg.xml
index 6e3b365..4f24740 100644
--- a/app/src/main/res/drawable/ic_wel_bg.xml
+++ b/app/src/main/res/drawable/ic_wel_bg.xml
@@ -1,10 +1,9 @@
-
diff --git a/app/src/main/res/layout/activity_dic.xml b/app/src/main/res/layout/activity_dic.xml
index 7a78140..ce1ab75 100644
--- a/app/src/main/res/layout/activity_dic.xml
+++ b/app/src/main/res/layout/activity_dic.xml
@@ -1,25 +1,114 @@
-
-
+ android:padding="16dp"
+ android:src="@drawable/ic_back"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ android:layout_marginTop="30dp"
+ android:layout_marginBottom="40dp"
+ android:minHeight="500dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/fl_e">
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index e6a5764..2f7ea65 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -206,8 +206,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
- android:background="@drawable/button_r20_white_bg"
- android:minHeight="120dp" />
+ android:background="@drawable/button_r20_white_bg" />
-
+
diff --git a/app/src/main/res/layout/activity_still_image.xml b/app/src/main/res/layout/activity_still_image.xml
index a0ad5b4..183cf66 100755
--- a/app/src/main/res/layout/activity_still_image.xml
+++ b/app/src/main/res/layout/activity_still_image.xml
@@ -61,6 +61,7 @@
android:paddingEnd="10dp"
android:src="@drawable/ic_still_pic" />
+
-
+ android:orientation="horizontal">
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_text_result.xml b/app/src/main/res/layout/activity_text_result.xml
index b3acf7e..b5ad243 100644
--- a/app/src/main/res/layout/activity_text_result.xml
+++ b/app/src/main/res/layout/activity_text_result.xml
@@ -66,13 +66,13 @@
android:textSize="16sp"
android:textStyle="bold" />
-
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_sus_district.xml b/app/src/main/res/layout/layout_sus_district.xml
index b45ce2c..3ebc99b 100644
--- a/app/src/main/res/layout/layout_sus_district.xml
+++ b/app/src/main/res/layout/layout_sus_district.xml
@@ -77,9 +77,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
+ android:padding="5dp"
android:layout_marginBottom="10dp"
- android:src="@drawable/ic_voice"
- android:visibility="invisible" />
+ android:src="@drawable/ic_voice" />
+ android:orientation="horizontal">
-
+
+
+
+
+
+
+
Delete
History
- Empty no history...
+ Empty no history…
Favorite
- Empty no favorite...
+ Empty no favorite…
Translate Now
+
+ Directory
+ Search
+ Enter a word
+ loading…
+ Open in browser
+
Settings
@@ -94,5 +101,9 @@
双击悬浮球
Click the \"Favorite\" button at the end\nafter translation.\nEasily bookmark sentences.
+
+ English
+ Chinese
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index ef3a9ce..d3a96f4 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -8,7 +8,7 @@
\ No newline at end of file