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" /> + + -