diff --git a/app/.gitignore b/app/.gitignore index 42afabf..956c004 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,2 @@ -/build \ No newline at end of file +/build +/release \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3fe5400..e731c9c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,3 @@ -import java.text.SimpleDateFormat -import java.util.Date - plugins { alias(libs.plugins.android.application) alias(libs.plugins.jetbrains.kotlin.android) @@ -18,8 +15,8 @@ android { applicationId = "com.assimilate.alltrans" minSdk = 23 targetSdk = 34 - versionCode = 2 - versionName = "1.0.2" + versionCode = 3 + versionName = "1.0.3" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -27,18 +24,19 @@ android { buildFeatures { buildConfig = true viewBinding = true + buildConfig = true } buildTypes { - debug { - isShrinkResources = true - isMinifyEnabled = true - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } +// debug { +// isShrinkResources = true +// isMinifyEnabled = true +// proguardFiles( +// getDefaultProguardFile("proguard-android-optimize.txt"), +// "proguard-rules.pro" +// ) +// } release { isShrinkResources = true @@ -51,17 +49,6 @@ android { } -// applicationVariants.all { -// outputs.all { -// val appName = "Translark" // 替换为你的应用名称 -// val versionName = versionName -// val date = SimpleDateFormat("yyyyMMdd-HHmm").format(Date()) -// val newApkName = "${appName}-${date}-${versionName}.apk" -// (this as com.android.build.gradle.internal.api.BaseVariantOutputImpl).outputFileName = newApkName -// } -// } - - compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -73,6 +60,20 @@ android { dependencies { + implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar")))) + + //google ads + implementation("com.google.android.gms:play-services-ads:23.1.0") + implementation("com.google.ads.mediation:adcolony:4.8.0.2") + implementation("com.google.ads.mediation:applovin:12.5.0.0") + implementation("com.google.ads.mediation:vungle:6.12.0.0") + implementation("com.google.ads.mediation:facebook:6.17.0.0") + implementation("com.google.ads.mediation:mintegral:16.7.51.0") + implementation("com.google.ads.mediation:pangle:6.0.0.5.0") + implementation("com.unity3d.ads:unity-ads:4.6.1") + implementation("com.google.ads.mediation:unity:4.12.0.0") + // implementation("com.google.ads.mediation:ironsource:8.1.0.0") + // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:33.1.1")) @@ -80,6 +81,7 @@ dependencies { // 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 @@ -94,7 +96,6 @@ dependencies { implementation("com.google.mlkit:text-recognition-korean:16.0.0") // CameraX core library - implementation(libs.androidx.camera.core) // CameraX Camera2 extensions diff --git a/app/libs/adlibrary_20240614_1058_release.aar b/app/libs/adlibrary_20240614_1058_release.aar new file mode 100644 index 0000000..815b2e8 Binary files /dev/null and b/app/libs/adlibrary_20240614_1058_release.aar differ diff --git a/app/myadalltrans.json b/app/myadalltrans.json new file mode 100644 index 0000000..e98940f --- /dev/null +++ b/app/myadalltrans.json @@ -0,0 +1,420 @@ +{ + "AD_SHOW_LIMIT": { + "admob_inst": 100, + "admob_native": 100, + "max_banner": 100, + "max_inst": 100, + "max_native": 100 + }, + "sounds_inst_show_interval": 25000, + "LOLAds_EXPIRE_HOURS_NEW_USER": 20, + "alltrans_start_cold_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/2491776559": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_start_hot_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/8726012415": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_text_trans_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/8833823620": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_text_new_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/7552531544": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_text_camera_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/3473685732": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_image_camera_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/9094248890": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_history_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/9160460404": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_home_native_auto": { + "data": [ + { + "config": [ + [ + "admob_native", + { + "ca-app-pub-9280511366580942/6663526672": 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": [ + { + "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/8739025670": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + } +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 0ca3432..7ec7d10 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -17,7 +17,7 @@ #-keepattributes SourceFile,LineNumberTable # 保留com.assimilate.alltrans.keepmodel包及其子包的所有类 --keep class com.assimilate.alltrans.keepmodel.** { *; } +-keep class com.assimilate.alltrans.model.** { *; } # 保留com.assimilate.alltrans.http包及其子包的所有类 -keep class com.assimilate.alltrans.http.** { *; } diff --git a/app/release/baselineProfiles/0/app-release.dm b/app/release/baselineProfiles/0/app-release.dm deleted file mode 100644 index b3450ec..0000000 Binary files a/app/release/baselineProfiles/0/app-release.dm and /dev/null differ diff --git a/app/release/baselineProfiles/1/app-release.dm b/app/release/baselineProfiles/1/app-release.dm deleted file mode 100644 index f44e32b..0000000 Binary files a/app/release/baselineProfiles/1/app-release.dm and /dev/null differ diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json deleted file mode 100644 index 93c656d..0000000 --- a/app/release/output-metadata.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": 3, - "artifactType": { - "type": "APK", - "kind": "Directory" - }, - "applicationId": "com.assimilate.alltrans", - "variantName": "release", - "elements": [ - { - "type": "SINGLE", - "filters": [], - "attributes": [], - "versionCode": 2, - "versionName": "1.0.2", - "outputFile": "app-release.apk" - } - ], - "elementType": "File", - "baselineProfiles": [ - { - "minApi": 28, - "maxApi": 30, - "baselineProfiles": [ - "baselineProfiles/1/app-release.dm" - ] - }, - { - "minApi": 31, - "maxApi": 2147483647, - "baselineProfiles": [ - "baselineProfiles/0/app-release.dm" - ] - } - ], - "minSdkVersionForDexing": 23 -} \ No newline at end of file diff --git a/app/release/transk_app-08021155.apk b/app/release/transk_app-08021155.apk deleted file mode 100644 index 25f4e40..0000000 Binary files a/app/release/transk_app-08021155.apk and /dev/null differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 846564b..47f7121 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,6 +28,25 @@ android:supportsRtl="true" android:theme="@style/Theme.Alltrans" tools:targetApi="31"> + + + + + + + + + + + + = Build.VERSION_CODES.P) { @@ -65,9 +130,27 @@ class MyApp : Application() { return null } - object Config { - const val openSusViewMode: String = "open_sus_view" + private fun initAd() { + //初始化firebase,并获取firebase值 + RemoteConfigManager(this) + + LoLAds.initialize(this) + LoLAds.setLogEnable(BuildConfig.DEBUG)//是否打开⽇志和遮罩层颜色,release要设置成false + LoLAds.setTestEnable(BuildConfig.DEBUG)//false:使用 setAdConfig 中的广告配置 + LoLAds.setTestMode(TestMode.REMOTE_TEST)//setTestEnable为true时生效;LOCAL_TEST: 会使用sdk内的测试广告; REMOTE_TEST: 会将 setAdConfig 添加的配置中的广告id替换成测试id + //服务器端中⼴告json的key;⻅⼴告配置json详情 + LoLAds.setAdConfigKey(Config.adKey) + //设置自定义广告配置json + val config = AppStore(app).adMessage.takeIf { it.isNotEmpty() } ?: Config.adDefJson + LoLAds.setAdConfig(config) + } + + object Config { + + // firebase_event_map_key + const val CLICK_FROM = "clickfrom" + const val FAIL_REASON = "failreason" // firebase_event_key const val launchPv = "launch_pv" @@ -89,24 +172,459 @@ class MyApp : Application() { const val hoverButtonClick = "hover_button_click" + const val hoverLimitAgree = "hover_limit_agree" const val hoverButtonCancel = "hover_button_cancel" - const val hover_button_agree = "hover_button_agree" - const val hover_screen_click = "hover_screen_click" - const val hover_screen_imp = "hover_screen_imp" - const val hover_screen_global = "hover_screen_global" - const val hover_global_result = "hover_global_result" - const val hover_screen_district = "hover_screen_district" - const val hover_district_result = "hover_district_result" + const val hoverButtonAgree = "hover_button_agree" + const val hoverScreenClick = "hover_screen_click" + const val hoverScreenImp = "hover_screen_imp" + const val hoverScreenGlobal = "hover_screen_global" + const val hoverGlobalResult = "hover_global_result" + const val hoverScreenDistrict = "hover_screen_district" + const val hoverDistrictResult = "hover_district_result" - const val image_click = "image_click" - const val image_trans_camera = "image_trans_camera" - const val image_camera_result = "image_camera_result" - const val image_trans_photo = "image_trans_photo" - const val image_photo_result = "image_photo_result" + const val imageClick = "image_click" + const val imageTransCamera = "image_trans_camera" + const val imageCameraResult = "image_camera_result" + const val imageTransPhoto = "image_trans_photo" + const val imagePhotoResult = "image_photo_result" - const val history_click = "history_click" - const val history_delete = "history_delete" + const val historyClick = "history_click" + const val historyDelete = "history_delete" + // google_ad_place + const val start_cold_int_auto = "start_cold_int_auto" + const val start_hot_int_auto = "start_hot_int_auto" + const val text_trans_int_auto = "text_trans_int_auto" + const val text_new_int_auto = "text_new_int_auto" + const val text_camera_int_auto = "text_camera_int_auto" + const val image_camera_int_auto = "image_camera_int_auto" + const val history_int_auto = "history_int_auto" + const val home_native_auto = "home_native_auto" + const val backup_int_auto = "backup_int_auto" + + const val adKey = "alltrans" + const val adDefJson = """ + { + "AD_SHOW_LIMIT": { + "admob_inst": 100, + "admob_native": 100, + "max_banner": 100, + "max_inst": 100, + "max_native": 100 + }, + "sounds_inst_show_interval": 25000, + "LOLAds_EXPIRE_HOURS_NEW_USER": 20, + "alltrans_start_cold_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/2491776559": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_start_hot_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/8726012415": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_text_trans_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/8833823620": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_text_new_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/7552531544": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_text_camera_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/3473685732": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_image_camera_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/9094248890": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_history_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/9160460404": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + }, + "alltrans_home_native_auto": { + "data": [ + { + "config": [ + [ + "admob_native", + { + "ca-app-pub-9280511366580942/6663526672": 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": [ + { + "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/8739025670": 100 + } + ] + ], + "limit": { + "admob_inst": 100, + "max_inst": 100 + }, + "cycle": 0, + "timeout": 15000, + "showIntervalEnable": false + } + ] + } +} + """ } } diff --git a/app/src/main/java/com/assimilate/alltrans/adapters/LanguageAdapter.java b/app/src/main/java/com/assimilate/alltrans/adapters/LanguageAdapter.java index 879ecf8..c732002 100644 --- a/app/src/main/java/com/assimilate/alltrans/adapters/LanguageAdapter.java +++ b/app/src/main/java/com/assimilate/alltrans/adapters/LanguageAdapter.java @@ -12,7 +12,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.assimilate.alltrans.R; -import com.assimilate.alltrans.keepmodel.Language; +import com.assimilate.alltrans.model.Language; import com.assimilate.alltrans.databinding.LanguageItemLayoutBinding; import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; diff --git a/app/src/main/java/com/assimilate/alltrans/allservice/SusService.kt b/app/src/main/java/com/assimilate/alltrans/allservice/SusService.kt index 44f9928..218980f 100644 --- a/app/src/main/java/com/assimilate/alltrans/allservice/SusService.kt +++ b/app/src/main/java/com/assimilate/alltrans/allservice/SusService.kt @@ -14,6 +14,7 @@ import android.os.Looper import android.util.Log import androidx.core.app.NotificationCompat import com.assimilate.alltrans.R +import com.assimilate.alltrans.common.FirebaseAnalyticsHelper import com.assimilate.alltrans.common.ScreenCaptureManager import com.assimilate.alltrans.curview.ControlView import com.assimilate.alltrans.curview.CopyTextView @@ -79,6 +80,7 @@ class SusService : Service() { override fun onClick() { Log.d("SusService_f", "FloatingView clicked") addControlView() + FirebaseAnalyticsHelper.hoverScreenClickEvent() } }) } @@ -92,6 +94,8 @@ class SusService : Service() { Handler(Looper.getMainLooper()).postDelayed({ globalView.addGlobalView(screenCaptureManager.getImageReader()) }, 333) + + FirebaseAnalyticsHelper.hoverScreenGlobalEvent() } override fun onCopyClick() { @@ -102,6 +106,7 @@ class SusService : Service() { override fun onDistrictClick() { selectionView = SelectionView(this@SusService) selectionView.addSelectionView(screenCaptureManager.getImageReader()) + FirebaseAnalyticsHelper.hoverScreenDistrictEvent() } override fun onChangeLan() { @@ -161,4 +166,5 @@ class SusService : Service() { copyTextView.removeView() } } + } diff --git a/app/src/main/java/com/assimilate/alltrans/common/AppStore.kt b/app/src/main/java/com/assimilate/alltrans/common/AppStore.kt new file mode 100644 index 0000000..f0cbd58 --- /dev/null +++ b/app/src/main/java/com/assimilate/alltrans/common/AppStore.kt @@ -0,0 +1,29 @@ +package com.assimilate.alltrans.common + +import android.content.Context +import android.content.SharedPreferences +import com.assimilate.alltrans.MyApp + +class AppStore(context: Context) { + private val sharedPreferences: SharedPreferences = + context.getSharedPreferences("AppStore", Context.MODE_PRIVATE) + + val showAdIntervalTime: Long + get() = sharedPreferences.getLong("showAdIntervalTime", DEFAULT_INTERVAL_TIME) + + val adMessage: String + get() = sharedPreferences.getString(MyApp.Config.adKey, DEFAULT_WELCOME_MESSAGE) ?: DEFAULT_WELCOME_MESSAGE + + fun saveLong(key: String, value: Long) { + sharedPreferences.edit().putLong(key, value).apply() + } + + fun saveString(key: String, value: String) { + sharedPreferences.edit().putString(key, value).apply() + } + + companion object { + private const val DEFAULT_INTERVAL_TIME: Long = 5000 // 默认间隔时间,单位毫秒 + private const val DEFAULT_WELCOME_MESSAGE: String = "" // 默认欢迎信息 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/assimilate/alltrans/common/CurrentActivityHolder.kt b/app/src/main/java/com/assimilate/alltrans/common/CurrentActivityHolder.kt new file mode 100644 index 0000000..888b615 --- /dev/null +++ b/app/src/main/java/com/assimilate/alltrans/common/CurrentActivityHolder.kt @@ -0,0 +1,7 @@ +package com.assimilate.alltrans.common + +import android.app.Activity + +object CurrentActivityHolder { + var currentActivity: Activity? = null +} diff --git a/app/src/main/java/com/assimilate/alltrans/common/FirebaseAnalyticsHelper.kt b/app/src/main/java/com/assimilate/alltrans/common/FirebaseAnalyticsHelper.kt index 93ae522..0c18e11 100644 --- a/app/src/main/java/com/assimilate/alltrans/common/FirebaseAnalyticsHelper.kt +++ b/app/src/main/java/com/assimilate/alltrans/common/FirebaseAnalyticsHelper.kt @@ -1,10 +1,12 @@ package com.assimilate.alltrans.common import android.os.Bundle +import android.text.TextUtils import com.assimilate.alltrans.MyApp import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.ktx.analytics import com.google.firebase.ktx.Firebase +import org.json.JSONObject object FirebaseAnalyticsHelper { private val firebaseAnalytics: FirebaseAnalytics by lazy { @@ -23,7 +25,7 @@ object FirebaseAnalyticsHelper { } } } - // firebaseAnalytics.logEvent(eventName, bundle) + firebaseAnalytics.logEvent(eventName, bundle) } @@ -32,42 +34,32 @@ object FirebaseAnalyticsHelper { } - fun homePvEvent(from: String) { - val params = when (from) { - "cap" -> mapOf("cap" to 1) - "create" -> mapOf("cap" to 1) - else -> { - null - } - } - + fun homePvEvent(from: String, value: String) { + val params = mapOf(from to value) logCusEvent(MyApp.Config.homePv, params) } - fun textTransSwitchEvent(from: String) { - val params = when (from) { - "cap" -> mapOf("cap" to 1) - "create" -> mapOf("cap" to 1) - else -> { - null - } - } - + fun textTransSwitchEvent(from: String, value: String) { + val params = mapOf(from to value) + logCusEvent(MyApp.Config.textTransSwitch, params) } - - fun languageChooseEvent(from: String) { - val params = mapOf(from to 1) + fun languageChooseEvent(from: String,value: String) { + val params = mapOf(from to value) logCusEvent(MyApp.Config.languageChoose, params) } + fun languageFromEvent(clickFrom: String,value: String) { + val params = mapOf(clickFrom to value) + logCusEvent(MyApp.Config.languageFrom, params) + } fun textTransClickEvent() { logCusEvent(MyApp.Config.textTransClick, null) } - fun textTransResultEvent(result: String) { - val params = mapOf(result to 1) + fun textTransResultEvent(result: String,value: String) { + val params = mapOf(result to value) logCusEvent(MyApp.Config.textTransResult, params) } @@ -85,8 +77,8 @@ object FirebaseAnalyticsHelper { } - fun textVoiceResultEvent(failReason: String) { - val params = mapOf(failReason to 1) + fun textVoiceResultEvent(failReason: String,value: String) { + val params = mapOf(failReason to value) logCusEvent(MyApp.Config.textVoiceResult, params) } @@ -113,10 +105,106 @@ object FirebaseAnalyticsHelper { logCusEvent(MyApp.Config.hoverButtonClick, null) } + fun hoverLimitAgreeEvent() { + logCusEvent(MyApp.Config.hoverLimitAgree, null) + } + fun hoverButtonCancelEvent() { logCusEvent(MyApp.Config.hoverButtonCancel, null) } + fun hoverButtonAgreeEvent() { + logCusEvent(MyApp.Config.hoverButtonAgree, null) + } + + fun hoverScreenClickEvent() { + logCusEvent(MyApp.Config.hoverScreenClick, null) + } + + fun hoverScreenImpEvent() { + logCusEvent(MyApp.Config.hoverScreenImp, null) + } + + fun hoverScreenGlobalEvent() { + logCusEvent(MyApp.Config.hoverScreenGlobal, null) + } + + fun hoverScreenDistrictEvent() { + logCusEvent(MyApp.Config.hoverScreenDistrict, null) + } + + fun imageClickEvent(clickFrom: String,value: String) { + val params = mapOf(clickFrom to value) + logCusEvent(MyApp.Config.imageClick, params) + } + + fun imageTransCameraEvent() { + logCusEvent(MyApp.Config.imageTransCamera, null) + } + fun imageTransPhotoEvent() { + logCusEvent(MyApp.Config.imageTransPhoto, null) + } + + fun historyClickEvent() { + logCusEvent(MyApp.Config.historyClick, null) + } + + fun historyDeleteEvent() { + logCusEvent(MyApp.Config.historyDelete, null) + } + + fun hoverGlobalResultEvent(failReason: String,value: String) { + val params = mapOf(failReason to value) + logCusEvent(MyApp.Config.hoverGlobalResult, params) + } + + + fun hoverDistrictResultEvent(failReason: String,value: String) { + val params = mapOf(failReason to value) + logCusEvent(MyApp.Config.hoverDistrictResult, params) + } + + fun imageCameraResultEvent(failReason: String,value: String) { + val params = mapOf(failReason to value) + logCusEvent(MyApp.Config.imageCameraResult, params) + } + + + fun imagePhotoResultEvent(failReason: String,value: String) { + val params = mapOf(failReason to value) + logCusEvent(MyApp.Config.imagePhotoResult, params) + } + + +// +// fun logEvent(eventName: String, myParam: Map? = null) { +// +// val jsonObject = JSONObject() +// jsonObject.put("fail", e.toString()) +// val map = mutableMapOf(Pair(MyApp.Config.CLICK_FROM, jsonObject.toString())) +// FirebaseAnalyticsHelper.logEvent(AnalysisUtil.APP_FIRST_OPEN_FAIL, map) +// +// +// +// if (myParam != null) { +// val bundle = Bundle() +// try { +// for ((key, value) in myParam) { +// if (!TextUtils.isEmpty(value) && !TextUtils.isEmpty(key)) { +// bundle.putString(key, value) +// } +// } +// firebaseAnalytics.logEvent(eventName, bundle) +// } catch (ignore: Exception) { +// } +// } else { +// try { +// firebaseAnalytics.logEvent(eventName, null) +// } catch (ignore: Exception) { +// } +// } +// } +// } diff --git a/app/src/main/java/com/assimilate/alltrans/common/LolAdWrapper.kt b/app/src/main/java/com/assimilate/alltrans/common/LolAdWrapper.kt new file mode 100644 index 0000000..4f7672c --- /dev/null +++ b/app/src/main/java/com/assimilate/alltrans/common/LolAdWrapper.kt @@ -0,0 +1,206 @@ +package com.assimilate.alltrans.common + +import android.app.Activity +import android.util.Log +import android.widget.FrameLayout +import com.assimilate.alltrans.MyApp +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.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.LOLAdsInstDispatcher +import com.lol.apex.ok.google.adlibrary.rewarded.LOLAdsRewardedDispatcher + + +class LolAdWrapper { + + companion object { + val shared: LolAdWrapper by lazy { LolAdWrapper() } + } + + interface LoLLoadListener { + fun loadFailed(error: LolLoadError?) {} + fun loaded() {} + } + + interface LolShowListener { + fun shown() {} + fun showFailed(error: LolShowError?) {} + 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) { + if (act.isFinishing) return + LOLAdsInstDispatcher.getLoader(act, placement, object : AdLoadListener { + override fun onAdLoadFailed(error: LolLoadError?) { + //load广告失败打点 +// val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, "${error?.msg}")) +// AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_LOAD_FAILED, map) + + listener?.loadFailed(error) + } + + override fun onAdLoaded() { + listener?.loaded() + } + + }).loadAd() + } + + fun loadRewardAd(act: Activity, placement: String, listener: LoLLoadListener? = null) { + if (act.isFinishing) return + LOLAdsRewardedDispatcher.getLoader(act, placement, object : AdLoadListener { + override fun onAdLoadFailed(error: LolLoadError?) { +// val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, "${error?.msg}")) +// AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_LOAD_FAILED, map) + listener?.loadFailed(error) + } + + override fun onAdLoaded() { + listener?.loaded() + } + + }).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) + } + } + + fun showAdTiming(act: Activity, placement: String, listener: LolShowListener? = null) { + //当前时间减去旧时间,才展示广告(满足间隔时间才show广告) + if (System.currentTimeMillis() - MyApp.app.lastAdDisplayTime.get() >= AppStore(MyApp.app).showAdIntervalTime) { + //判断当前广告位是否可以show,不能show则判断补位广告是否可以show。 + if (act.isFinishing || !hasCache(placement)) { + 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 loadAdShowNativeAd( + context: Activity, nativeId: String, frameAd: FrameLayout, admobLayout: Int, maxLayout: Int + ) { + val inner = LOLAdsInnerDispatcher(context, object : AdInnerLoadAdapter() { + //设置广告位 + override fun getPlace(): String { + return nativeId + } + + //设置admob的native广告布局 + override fun getAdmobLayoutResId(): Int { + return admobLayout + } + + override fun getMaxLayoutResId(): Int { + return maxLayout + } + }) + + inner.addAdLoadListener(object : AdLoadListener { + + override fun onAdLoadFailed(error: LolLoadError?) { + + } + + override fun onAdLoaded() { + + } + }) + + //广告展示监听回调 + inner.addAdShowListener(object : AdShowListener { + override fun onAdClicked() { + + } + + override fun onAdRewarded() { + + } + + override fun onAdShowFailed(error: LolShowError?) { + } + + override fun onAdShown() {} + override fun onAdClosed() {} + override fun onAfterClickClosed() {} + override fun onDelayClosed() {} + }) + + inner.loadAd2Show(object : AdInnerShowAdapter() { + override fun getAdContainer(): FrameLayout { + return frameAd + } + }) + } + + 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/RemoteConfigManager.kt b/app/src/main/java/com/assimilate/alltrans/common/RemoteConfigManager.kt new file mode 100644 index 0000000..b607e25 --- /dev/null +++ b/app/src/main/java/com/assimilate/alltrans/common/RemoteConfigManager.kt @@ -0,0 +1,61 @@ +package com.assimilate.alltrans.common + +import android.content.Context +import android.util.Log +import com.assimilate.alltrans.MyApp +import com.google.firebase.ktx.Firebase +import com.google.firebase.remoteconfig.ConfigUpdate +import com.google.firebase.remoteconfig.ConfigUpdateListener +import com.google.firebase.remoteconfig.FirebaseRemoteConfig +import com.google.firebase.remoteconfig.FirebaseRemoteConfigException +import com.google.firebase.remoteconfig.ktx.remoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfigSettings + +class RemoteConfigManager(private val context: Context) { + + private val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig + + init { + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 3600 + } + remoteConfig.setConfigSettingsAsync(configSettings) + + remoteConfig.fetchAndActivate() + .addOnCompleteListener { task -> + if (task.isSuccessful) { + val updated = task.result + Log.d(TAG, "Config params updated: $updated") + // Toast.makeText(context, "Fetch and activate succeeded", Toast.LENGTH_SHORT).show() + saveConfigValuesToAppStore() + } else { + // Toast.makeText(context, "Fetch failed", Toast.LENGTH_SHORT).show() + } + } + + remoteConfig.addOnConfigUpdateListener(object : ConfigUpdateListener { + override fun onUpdate(configUpdate: ConfigUpdate) { + Log.d(TAG, "Updated keys: " + configUpdate.updatedKeys) + if (configUpdate.updatedKeys.contains(MyApp.Config.adKey)) { + remoteConfig.activate().addOnCompleteListener { + saveConfigValuesToAppStore() + } + } + } + + override fun onError(error: FirebaseRemoteConfigException) { + Log.w(TAG, "Config update error with code: " + error.code, error) + } + }) + } + + private fun saveConfigValuesToAppStore() { + val appStore = AppStore(context) + val adValue = remoteConfig.getString(MyApp.Config.adKey) + appStore.saveString(MyApp.Config.adKey, adValue) + } + + companion object { + private const val TAG = "RemoteConfigManager" + } +} 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 9dd692c..b03826e 100644 --- a/app/src/main/java/com/assimilate/alltrans/common/TextGraphic.kt +++ b/app/src/main/java/com/assimilate/alltrans/common/TextGraphic.kt @@ -21,7 +21,8 @@ class TextGraphic( private val showLanguageTag: Boolean, private val showConfidence: Boolean, private val textShow: Boolean, - private val needTrans: Boolean + private val needTrans: Boolean, + private val fbFrom:String ) : GraphicOverlay.Graphic(overlay) { private val textPaint: TextPaint = TextPaint().apply { @@ -41,7 +42,7 @@ class TextGraphic( isVisible = textShow if (needTrans) { - TranslationManager(text) { translatedTextPairs -> + TranslationManager(text,fbFrom) { translatedTextPairs -> translatedTextBlocks = translatedTextPairs.map { it.first } // 可以同时打印原Text和翻译后的结果 translatedTextPairs.forEach { (translated, original) -> 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 ffc468f..1e6b769 100644 --- a/app/src/main/java/com/assimilate/alltrans/common/TextRecognitionProcessor.kt +++ b/app/src/main/java/com/assimilate/alltrans/common/TextRecognitionProcessor.kt @@ -4,8 +4,8 @@ import android.content.Context import android.util.Log import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.curview.GraphicOverlay -import com.assimilate.alltrans.keepmodel.LanguagesConstants -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils +import com.assimilate.alltrans.model.LanguagesConstants +import com.assimilate.alltrans.model.PreferenceLanguageUtils import com.google.android.gms.tasks.Task import com.google.mlkit.vision.common.InputImage import com.google.mlkit.vision.text.Text @@ -19,6 +19,7 @@ class TextRecognitionProcessor( textRecognizerOptions: TextRecognizerOptionsInterface, private val textShow:Boolean, private val needTrans: Boolean, + private val fbFrom:String, private val callback: TextRecognitionCallback? = null // 添加回调 ) : VisionProcessorBase(context) { @@ -54,7 +55,8 @@ class TextRecognitionProcessor( showLanguageTag, showConfidence, textShow, - needTrans + needTrans, + fbFrom ) ) 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 cb48329..9c20c78 100644 --- a/app/src/main/java/com/assimilate/alltrans/common/TranslationManager.kt +++ b/app/src/main/java/com/assimilate/alltrans/common/TranslationManager.kt @@ -2,18 +2,17 @@ package com.assimilate.alltrans.common import android.os.Handler import android.os.Looper -import android.text.TextUtils -import android.util.Log import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.http.GoogleTranslator import com.assimilate.alltrans.http.Translator -import com.assimilate.alltrans.keepmodel.LanguagesConstants -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils +import com.assimilate.alltrans.model.LanguagesConstants +import com.assimilate.alltrans.model.PreferenceLanguageUtils import com.google.mlkit.vision.text.Text import java.util.concurrent.Executors class TranslationManager( private val text: Text, + private val fbFrom: String, private val callback: (List>) -> Unit // 修改callback的参数类型 ) { private val handler = Handler(Looper.getMainLooper()) @@ -49,7 +48,8 @@ class TranslationManager( translatedTextBlocks.add(Pair(index, textBlock.text)) if (translatedTextBlocks.size == text.textBlocks.size) { handler.post { - callback(translatedTextBlocks.sortedBy { it.first }.map { it.second to text.textBlocks[it.first].text }) + callback(translatedTextBlocks.sortedBy { it.first } + .map { it.second to text.textBlocks[it.first].text }) } } } else { @@ -69,7 +69,8 @@ class TranslationManager( if (translatedTextBlocks.size == text.textBlocks.size) { handler.post { - callback(translatedTextBlocks.sortedBy { it.first }.map { it.second to text.textBlocks[it.first].text }) + callback(translatedTextBlocks.sortedBy { it.first } + .map { it.second to text.textBlocks[it.first].text }) } } } @@ -78,9 +79,33 @@ class TranslationManager( translatedTextBlocks.add(Pair(index, "")) if (translatedTextBlocks.size == text.textBlocks.size) { handler.post { - callback(translatedTextBlocks.sortedBy { it.first }.map { it.second to text.textBlocks[it.first].text }) + callback(translatedTextBlocks.sortedBy { it.first } + .map { it.second to text.textBlocks[it.first].text }) } } + + when (fbFrom) { + "global" -> { + FirebaseAnalyticsHelper.hoverGlobalResultEvent(MyApp.Config.FAIL_REASON,fbFrom + "_" + errorMessage) + } + + "float" -> { + FirebaseAnalyticsHelper.hoverGlobalResultEvent(MyApp.Config.FAIL_REASON,fbFrom + "_" + errorMessage) + + } + + "photo" -> { + FirebaseAnalyticsHelper.imagePhotoResultEvent(MyApp.Config.FAIL_REASON,fbFrom + "_" + errorMessage) + + } + + "image" -> { + FirebaseAnalyticsHelper.imageCameraResultEvent(MyApp.Config.FAIL_REASON,fbFrom + "_" + errorMessage) + } + + } + + } }) } 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 19903ee..85058d0 100644 --- a/app/src/main/java/com/assimilate/alltrans/curview/ControlView.kt +++ b/app/src/main/java/com/assimilate/alltrans/curview/ControlView.kt @@ -13,6 +13,7 @@ import android.view.View import android.view.WindowManager import com.assimilate.alltrans.common.FirebaseAnalyticsHelper import com.assimilate.alltrans.databinding.SusControlViewBinding +import com.assimilate.alltrans.viewui.MainActivity import com.assimilate.alltrans.viewui.PhotoImageActivity import com.assimilate.alltrans.viewui.WelActivity @@ -77,6 +78,7 @@ class ControlView(private val context: Context) { layoutParams.y = 100 windowManager.addView(controlView, layoutParams) + FirebaseAnalyticsHelper.hoverScreenImpEvent() isAdded = true initControlClick() @@ -115,6 +117,7 @@ class ControlView(private val context: Context) { binding.tvSusPhoto.setOnClickListener { val intent = Intent(context, PhotoImageActivity::class.java) + intent.putExtra("key_start_ph", "hover") val pendingIntent = PendingIntent.getActivity( context, 0, @@ -133,7 +136,7 @@ class ControlView(private val context: Context) { binding.ivSusHome.setOnClickListener { Log.d("ControlViewManager", "Home clicked") - val intent = Intent(context, WelActivity::class.java) + val intent = Intent(context, MainActivity::class.java) val pendingIntent = PendingIntent.getActivity( context, 0, 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 0fc1755..e296a5e 100644 --- a/app/src/main/java/com/assimilate/alltrans/curview/CopyTextView.kt +++ b/app/src/main/java/com/assimilate/alltrans/curview/CopyTextView.kt @@ -14,10 +14,8 @@ import android.view.LayoutInflater import android.view.View import android.view.WindowManager import android.widget.Toast -import androidx.core.content.ContextCompat.getSystemService import com.assimilate.alltrans.common.TextRecognitionProcessor import com.assimilate.alltrans.common.VisionImageProcessor -import com.assimilate.alltrans.common.Widget import com.assimilate.alltrans.databinding.LayoutSusCopyBinding import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions import java.io.IOException @@ -40,7 +38,7 @@ class CopyTextView(private val context: Context) : // 这里还需要调整 imageProcessor = TextRecognitionProcessor( context, - ChineseTextRecognizerOptions.Builder().build(), true, false, this + ChineseTextRecognizerOptions.Builder().build(), true, false, "",this ) val inflater = LayoutInflater.from(context) @@ -72,7 +70,7 @@ class CopyTextView(private val context: Context) : Log.d("gdsfsfsadf",recognizedText.toString()) copyToClipboard(recognizedText.toString()) - removeView() + // removeView() } } 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 8ce2629..20ad9d3 100644 --- a/app/src/main/java/com/assimilate/alltrans/curview/DistrictView.kt +++ b/app/src/main/java/com/assimilate/alltrans/curview/DistrictView.kt @@ -8,7 +8,6 @@ import android.media.ImageReader import android.os.Build import android.os.Handler import android.os.Looper -import android.text.TextUtils import android.util.Log import android.view.Gravity import android.view.LayoutInflater @@ -18,12 +17,13 @@ import android.view.ViewGroup import android.view.WindowManager import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.R -import com.assimilate.alltrans.keepmodel.LanguagesConstants +import com.assimilate.alltrans.common.FirebaseAnalyticsHelper import com.assimilate.alltrans.common.Logger -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils import com.assimilate.alltrans.databinding.LayoutSusDistrictBinding import com.assimilate.alltrans.http.GoogleTranslator import com.assimilate.alltrans.http.Translator +import com.assimilate.alltrans.model.LanguagesConstants +import com.assimilate.alltrans.model.PreferenceLanguageUtils import com.google.mlkit.vision.common.InputImage import com.google.mlkit.vision.text.TextRecognition import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions @@ -131,12 +131,14 @@ class DistrictView( bindingSusDistrict.ivSourceClear.setOnClickListener { bindingSusDistrict.tvTrSource.text = "" bindingSusDistrict.tvTrTarget.text = "" + removeDistrictView() } } fun removeDistrictView() { windowManager.removeView(districtView) windowManager.removeView(overlayView) + } private fun takeDistrictScreenshot(image: Bitmap, rect: Rect) { @@ -199,37 +201,27 @@ class DistrictView( val translator: Translator = GoogleTranslator() translator.translate(param, object : GoogleTranslator.GoogleTranslateCallback { override fun onResponse(result: String?, errorMessage: String?) { - - if (!TextUtils.isEmpty(result)) { - bindingSusDistrict.tvTrTarget.text - } else { - // 处理错误信息 - if (!TextUtils.isEmpty(errorMessage)) { - // 显示错误信息或记录日志 - if (errorMessage != null) { - Log.e("TranslationError", errorMessage) - } + 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" } - bindingSusDistrict.tvTrTarget.text = "Translation failed: $errorMessage" } - } override fun onFailure(errorMessage: String?) { - - - // 显示失败信息或记录日志 - if (!TextUtils.isEmpty(errorMessage)) { - if (errorMessage != null) { - Log.e("TranslationFailure", errorMessage) - } + Handler(Looper.getMainLooper()).post { + FirebaseAnalyticsHelper.hoverDistrictResultEvent( + MyApp.Config.FAIL_REASON, + "district" + errorMessage.toString() + ) bindingSusDistrict.tvTrTarget.text = "Translation failed: $errorMessage" - } else { - bindingSusDistrict.tvTrTarget.text = "Translation failed: Unknown error" } - } }) - } + + } \ No newline at end of file diff --git a/app/src/main/java/com/assimilate/alltrans/curview/DrawChooseView.kt b/app/src/main/java/com/assimilate/alltrans/curview/DrawChooseView.kt deleted file mode 100644 index 4f927c6..0000000 --- a/app/src/main/java/com/assimilate/alltrans/curview/DrawChooseView.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.assimilate.alltrans.curview - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.Rect -import android.view.MotionEvent -import android.view.View -import com.assimilate.alltrans.listeners.OnRegionSelectedListener - -class DrawChooseView(context: Context) : View(context) { - private var paintTransparent: Paint = Paint() - private var paintSemiTransparent: Paint = Paint() - private var rect: Rect? = null - - private var startX: Float = 0f - private var startY: Float = 0f - - init { - paintTransparent.color = Color.TRANSPARENT - paintTransparent.style = Paint.Style.FILL - - paintSemiTransparent.color = Color.parseColor("#88000000") // 半透明黑色 - paintSemiTransparent.style = Paint.Style.FILL - } - - override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - rect?.let { - val left = Math.min(it.left, it.right) - val right = Math.max(it.left, it.right) - val top = Math.min(it.top, it.bottom) - val bottom = Math.max(it.top, it.bottom) - - // 绘制框选外的半透明区域 - canvas.drawRect(0f, 0f, width.toFloat(), top.toFloat(), paintSemiTransparent) - canvas.drawRect(0f, top.toFloat(), left.toFloat(), bottom.toFloat(), paintSemiTransparent) - canvas.drawRect(right.toFloat(), top.toFloat(), width.toFloat(), bottom.toFloat(), paintSemiTransparent) - canvas.drawRect(0f, bottom.toFloat(), width.toFloat(), height.toFloat(), paintSemiTransparent) - - // 绘制框选内的透明区域 - canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), paintTransparent) - } - } - - override fun onTouchEvent(event: MotionEvent): Boolean { - when (event.action) { - MotionEvent.ACTION_DOWN -> { - startX = event.x - startY = event.y - rect = Rect(startX.toInt(), startY.toInt(), startX.toInt(), startY.toInt()) - invalidate() - return true - } - - MotionEvent.ACTION_MOVE -> { - rect?.apply { - right = event.x.toInt() - bottom = event.y.toInt() - } - invalidate() - return true - } - - MotionEvent.ACTION_UP -> { - rect?.let { - (context as? OnRegionSelectedListener)?.onRegionSelected(it) - } - return true - } - } - return super.onTouchEvent(event) - } -} 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 1421e65..c052df5 100644 --- a/app/src/main/java/com/assimilate/alltrans/curview/FloatingView.kt +++ b/app/src/main/java/com/assimilate/alltrans/curview/FloatingView.kt @@ -14,6 +14,7 @@ import android.util.Log import android.view.Gravity import android.view.MotionEvent import android.view.View +import android.view.ViewConfiguration import android.view.WindowManager import android.widget.ImageView import com.assimilate.alltrans.R @@ -56,11 +57,10 @@ class FloatingView( // 初始化语言识别 imageProcessor = TextRecognitionProcessor( context, - ChineseTextRecognizerOptions.Builder().build(), false, true + ChineseTextRecognizerOptions.Builder().build(), false, true, "float" ) graphicOverlay = GraphicOverlay(context, null) - } interface OnMovePointListener { @@ -123,11 +123,15 @@ class FloatingView( private var initialTouchX = 0f private var initialTouchY = 0f private var isClick = true + private var downTime: Long = 0 + private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop + private val maxClickDuration = 500 // 最大点击时间(毫秒) override fun onTouch(v: View?, event: MotionEvent): Boolean { when (event.action) { MotionEvent.ACTION_DOWN -> { isClick = true + downTime = System.currentTimeMillis() initialX = params.x initialY = params.y initialTouchX = event.rawX @@ -139,20 +143,24 @@ class FloatingView( } MotionEvent.ACTION_UP -> { + val upTime = System.currentTimeMillis() + val duration = upTime - downTime + handler.postDelayed(fadeRunnable, 3000) imageView.setImageResource(originalImageResId) stickToEdge() - if (isClick) { + + if (isClick && duration < maxClickDuration) { onClickListener?.onClick() } else { - try { - windowManager.removeView(graphicOverlay) - hasCapturedScreenshot = false - windowManager.updateViewLayout(imageView, params) + hasCapturedScreenshot = false + } - } catch (e: IllegalArgumentException) { - Log.e("FloatingView", "View not attached to window manager", e) - } + try { + windowManager.removeView(graphicOverlay) + windowManager.updateViewLayout(imageView, params) + } catch (e: IllegalArgumentException) { + Log.e("FloatingView", "View not attached to window manager", e) } return true @@ -162,14 +170,15 @@ class FloatingView( val dx = event.rawX - initialTouchX val dy = event.rawY - initialTouchY - if (dx * dx + dy * dy > imageView.width * imageView.width) { + if (Math.abs(dx) > touchSlop || Math.abs(dy) > touchSlop) { isClick = false } if (!isClick) { // 将图片的位置设置为手指触摸点的上方 params.x = initialX + dx.toInt() - params.y = initialY + dy.toInt() - imageView.height / 2 // 调整y坐标,使图片位于手指的上方 + params.y = + initialY + dy.toInt() - imageView.height / 2 // 调整y坐标,使图片位于手指的上方 onMovePointListener?.onMovePoint() imageView.setImageResource(moveImageResId) @@ -177,9 +186,8 @@ class FloatingView( lastX = params.x + imageView.width / 2 lastY = params.y + imageView.height / 2 - updateGraphicOverlay(lastX, lastY) - try { + updateGraphicOverlay(lastX, lastY) windowManager.updateViewLayout(imageView, params) } catch (e: IllegalArgumentException) { Log.e("FloatingView", "View not attached to window manager", e) @@ -188,7 +196,6 @@ class FloatingView( return true } - } return false } @@ -247,6 +254,7 @@ class FloatingView( BitmapFactory.decodeResource(context.resources, originalImageResId).width val edgeImageWidth = BitmapFactory.decodeResource(context.resources, edgeImageResId).width + val isLeftEdge = params.x + originalImageWidth / 2 < screenWidth / 2 params.x = if (isLeftEdge) { 0 @@ -268,10 +276,21 @@ class FloatingView( val bitmap = BitmapFactory.decodeResource(context.resources, edgeImageResId) if (isLeftEdge) { imageView.setImageBitmap(flipBitmapHorizontally(bitmap)) - imageView.setPadding(0, 20, 30, 20) + imageView.setPadding(0, 30, 50, 30) } else { imageView.setImageBitmap(bitmap) - imageView.setPadding(30, 20, 0, 20) + imageView.setPadding(50, 30, 0, 30) + } + destroyGraphicOverlay() + } + + private fun destroyGraphicOverlay() { + try { + if (isAttachedToWindow && graphicOverlay?.parent != null) { + windowManager.removeView(graphicOverlay) + } + } catch (e: IllegalArgumentException) { + Log.e("FloatingView", "View not attached to window manager", e) } } @@ -289,8 +308,6 @@ class FloatingView( } fun detachFromWindow() { - Log.e("FloatingView", "View not attached to window manager") - if (isAttachedToWindow) { try { windowManager.removeView(imageView) @@ -339,7 +356,6 @@ class FloatingView( } fun setImageReader(reader: ImageReader) { - this.imageReader = reader if (!hasCapturedScreenshot) { hasCapturedScreenshot = true @@ -347,8 +363,5 @@ class FloatingView( windowManager.addView(graphicOverlay, fullScreenParams) } - - } - } 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 aa3a47d..a0fb400 100644 --- a/app/src/main/java/com/assimilate/alltrans/curview/GlobalView.kt +++ b/app/src/main/java/com/assimilate/alltrans/curview/GlobalView.kt @@ -32,7 +32,7 @@ class GlobalView(private val context: Context) { // 这里还需要调整 imageProcessor = TextRecognitionProcessor( context, - ChineseTextRecognizerOptions.Builder().build(),true,true + ChineseTextRecognizerOptions.Builder().build(), true, true, "global" ) bindingSubGlobal = LayoutSusGlobalBinding.inflate(LayoutInflater.from(context)) globalView = bindingSubGlobal.root @@ -125,4 +125,5 @@ class GlobalView(private val context: Context) { } } + } diff --git a/app/src/main/java/com/assimilate/alltrans/curview/LanguageSelectorView.kt b/app/src/main/java/com/assimilate/alltrans/curview/LanguageSelectorView.kt index d4568af..d4fdda4 100644 --- a/app/src/main/java/com/assimilate/alltrans/curview/LanguageSelectorView.kt +++ b/app/src/main/java/com/assimilate/alltrans/curview/LanguageSelectorView.kt @@ -12,11 +12,13 @@ import android.view.View import android.view.WindowManager import androidx.core.content.ContextCompat.getColor import androidx.recyclerview.widget.LinearLayoutManager +import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.R import com.assimilate.alltrans.adapters.LanguageAdapter -import com.assimilate.alltrans.keepmodel.Language -import com.assimilate.alltrans.keepmodel.LanguagesConstants -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils +import com.assimilate.alltrans.common.FirebaseAnalyticsHelper +import com.assimilate.alltrans.model.Language +import com.assimilate.alltrans.model.LanguagesConstants +import com.assimilate.alltrans.model.PreferenceLanguageUtils import com.assimilate.alltrans.databinding.LayoutSusChangelanBinding class LanguageSelectorView(private val context: Context) { @@ -141,10 +143,11 @@ class LanguageSelectorView(private val context: Context) { // 更新界面显示 binding?.tvChangeSource?.text = currentTargetLanguage binding?.tvChangeTarget?.text = currentSourceLanguage + FirebaseAnalyticsHelper.textTransSwitchEvent(MyApp.Config.CLICK_FROM, "hover") + removeFloatingView() } - } private fun initAllList() { @@ -153,9 +156,17 @@ class LanguageSelectorView(private val context: Context) { val adapter = LanguageAdapter(context, languages) { _, language -> Log.d("LanguageChange", language.language) if (lastTranslateLanguage) { + FirebaseAnalyticsHelper.languageFromEvent( + MyApp.Config.CLICK_FROM, + "hover_target" + ) PreferenceLanguageUtils.putString("language_target", language.language) removeFloatingView() } else { + FirebaseAnalyticsHelper.languageFromEvent( + MyApp.Config.CLICK_FROM, + "hover_source" + ) PreferenceLanguageUtils.putString("language_source", language.language) removeFloatingView() } @@ -170,11 +181,13 @@ class LanguageSelectorView(private val context: Context) { } } - - fun removeFloatingView() { + private fun removeFloatingView() { binding?.root?.let { windowManager.removeView(it) + windowManager.removeView(fullScreenView) } binding = null } + + } 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 7c07651..26d3c94 100644 --- a/app/src/main/java/com/assimilate/alltrans/curview/SelectionView.kt +++ b/app/src/main/java/com/assimilate/alltrans/curview/SelectionView.kt @@ -12,8 +12,12 @@ 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 @@ -132,4 +136,6 @@ class SelectionView(private val context: Context) { invalidate() } } + + } diff --git a/app/src/main/java/com/assimilate/alltrans/keepmodel/Language.java b/app/src/main/java/com/assimilate/alltrans/model/Language.java similarity index 97% rename from app/src/main/java/com/assimilate/alltrans/keepmodel/Language.java rename to app/src/main/java/com/assimilate/alltrans/model/Language.java index aa08721..4182459 100644 --- a/app/src/main/java/com/assimilate/alltrans/keepmodel/Language.java +++ b/app/src/main/java/com/assimilate/alltrans/model/Language.java @@ -1,4 +1,4 @@ -package com.assimilate.alltrans.keepmodel; +package com.assimilate.alltrans.model; import android.os.Parcel; import android.os.Parcelable; diff --git a/app/src/main/java/com/assimilate/alltrans/keepmodel/LanguagesConstants.java b/app/src/main/java/com/assimilate/alltrans/model/LanguagesConstants.java similarity index 99% rename from app/src/main/java/com/assimilate/alltrans/keepmodel/LanguagesConstants.java rename to app/src/main/java/com/assimilate/alltrans/model/LanguagesConstants.java index ce13f59..2ae276b 100644 --- a/app/src/main/java/com/assimilate/alltrans/keepmodel/LanguagesConstants.java +++ b/app/src/main/java/com/assimilate/alltrans/model/LanguagesConstants.java @@ -1,4 +1,4 @@ -package com.assimilate.alltrans.keepmodel; +package com.assimilate.alltrans.model; import android.content.Context; import android.net.Uri; diff --git a/app/src/main/java/com/assimilate/alltrans/keepmodel/PreferenceLanguageUtils.kt b/app/src/main/java/com/assimilate/alltrans/model/PreferenceLanguageUtils.kt similarity index 98% rename from app/src/main/java/com/assimilate/alltrans/keepmodel/PreferenceLanguageUtils.kt rename to app/src/main/java/com/assimilate/alltrans/model/PreferenceLanguageUtils.kt index d88217b..30b7340 100644 --- a/app/src/main/java/com/assimilate/alltrans/keepmodel/PreferenceLanguageUtils.kt +++ b/app/src/main/java/com/assimilate/alltrans/model/PreferenceLanguageUtils.kt @@ -1,4 +1,4 @@ -package com.assimilate.alltrans.keepmodel +package com.assimilate.alltrans.model import android.content.Context import android.content.SharedPreferences diff --git a/app/src/main/java/com/assimilate/alltrans/viewui/HistoryActivity.kt b/app/src/main/java/com/assimilate/alltrans/viewui/HistoryActivity.kt index f4232f1..1d5f3bd 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/HistoryActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/HistoryActivity.kt @@ -4,18 +4,24 @@ import android.content.Context import android.os.Bundle import android.speech.tts.TextToSpeech import android.view.View +import androidx.activity.OnBackPressedCallback import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.recyclerview.widget.LinearLayoutManager +import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.R import com.assimilate.alltrans.adapters.TranslationAdapter import com.assimilate.alltrans.adapters.TranslationAdapter.TranslationItemCallback +import com.assimilate.alltrans.common.FirebaseAnalyticsHelper +import com.assimilate.alltrans.common.LolAdWrapper import com.assimilate.alltrans.common.Widget import com.assimilate.alltrans.databinding.ActivityHistoryBinding import com.assimilate.alltrans.mydb.DbTranslation import com.assimilate.alltrans.mydb.Translations +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 HistoryActivity : AppCompatActivity() { @@ -123,6 +129,7 @@ class HistoryActivity : AppCompatActivity() { private fun remove(id: Long, index: Int) { ids!!.remove(id) items!!.remove(index) + FirebaseAnalyticsHelper.historyDeleteEvent() } private fun updateBtn() { @@ -175,13 +182,72 @@ class HistoryActivity : AppCompatActivity() { binding!!.histories.layoutManager = layoutManager binding!!.histories.adapter = adapter - } + adLoad(MyApp.Config.history_int_auto) + backPressedCall() + } private fun initClick() { - binding?.ivHisBack?.setOnClickListener { onBackPressed() } + binding?.ivHisBack?.setOnClickListener { + showInstAdFromCache(MyApp.Config.history_int_auto) + finish() + } } + + private fun backPressedCall() { + val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + showInstAdFromCache(MyApp.Config.history_int_auto) + finish() + } + } + onBackPressedDispatcher.addCallback(this, callback) + } + + + private fun adLoad(place: String) { + // 加载广告 + LolAdWrapper.shared.loadAdIfNotCached( + this, + place, + object : LolAdWrapper.LoLLoadListener { + override fun loadFailed(error: LolLoadError?) { + // Log.d("dsas",error.toString()) + + } + + override fun loaded() { + // 处理加载成功 + // Log.d("dsas","backSucc") + } + }) + + } + + 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() + } + }) + } + + companion object { const val COMMAND: String = "remove" const val COMMAND_COLLECTION: String = "remove_collection" 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 3ccf609..189e743 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/LanguageChangeActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/LanguageChangeActivity.kt @@ -16,10 +16,10 @@ import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.R import com.assimilate.alltrans.adapters.LanguageAdapter import com.assimilate.alltrans.common.FirebaseAnalyticsHelper -import com.assimilate.alltrans.keepmodel.Language -import com.assimilate.alltrans.keepmodel.LanguagesConstants -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils import com.assimilate.alltrans.databinding.ActivityLanguageChangeBinding +import com.assimilate.alltrans.model.Language +import com.assimilate.alltrans.model.LanguagesConstants +import com.assimilate.alltrans.model.PreferenceLanguageUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -41,32 +41,20 @@ class LanguageChangeActivity : AppCompatActivity() { } initView() - initSearch() // 添加这一行 + initSearch() lifecycleScope.launch { - withContext(Dispatchers.IO) { - // 耗时操作 - initAllList() - } + initAllList() } initClick() } private fun initSearch() { binding.chSearch.apply { - // 获取关闭按钮的ImageView val closeButton = findViewById(androidx.appcompat.R.id.search_close_btn) - - // 设置关闭按钮一直可见 closeButton.visibility = View.VISIBLE - - // 确保 SearchView 处于可点击状态 isFocusable = true isIconified = false - - // 延迟请求焦点以避免弹出软件盘 - post { - clearFocus() - } + post { clearFocus() } setOnQueryTextListener(object : androidx.appcompat.widget.SearchView.OnQueryTextListener { @@ -80,14 +68,9 @@ class LanguageChangeActivity : AppCompatActivity() { } }) - // 设置点击关闭按钮的行为 closeButton.setOnClickListener { - // 清空搜索框 setQuery("", false) - // 清除焦点 clearFocus() - - // 隐藏软件盘 val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(windowToken, 0) @@ -96,7 +79,6 @@ class LanguageChangeActivity : AppCompatActivity() { } private fun initView() { - val intentT = intent if (intentT.getBooleanExtra("choose_t", false)) { lastTranslateLanguage = true @@ -108,39 +90,60 @@ class LanguageChangeActivity : AppCompatActivity() { binding.tvChangeTarget.setTextColor(getColor(R.color.main_text_ff1f1724)) } - binding.tvChangeSource.text = PreferenceLanguageUtils.getString("language_source") binding.tvChangeTarget.text = PreferenceLanguageUtils.getString("language_target") - updateRecentLanguages() } - private fun updateRecentLanguages() { - val recentLanguages = PreferenceLanguageUtils.getRecentLanguages() - if (recentLanguages.isNotEmpty()) { - val recentAdapter = LanguageAdapter(this, ArrayList(recentLanguages)) { _, language -> - Log.d("LanguageChange", language.language) - if (lastTranslateLanguage) { - PreferenceLanguageUtils.putString("language_target", language.language) - onBackPressed() - } else { - PreferenceLanguageUtils.putString("language_source", language.language) - onBackPressed() + lifecycleScope.launch { + withContext(Dispatchers.IO) { + val recentLanguages = PreferenceLanguageUtils.getRecentLanguages() + withContext(Dispatchers.Main) { + if (recentLanguages.isNotEmpty()) { + val recentAdapter = LanguageAdapter( + this@LanguageChangeActivity, + ArrayList(recentLanguages) + ) { _, language -> + handleLanguageSelection(language) + } + binding.listLanCommon5.layoutManager = + LinearLayoutManager( + this@LanguageChangeActivity, + LinearLayoutManager.VERTICAL, + false + ) + binding.listLanCommon5.adapter = recentAdapter + } } - PreferenceLanguageUtils.addRecentLanguage(language) - binding.tvChangeSource.text = PreferenceLanguageUtils.getString("language_source") - binding.tvChangeTarget.text = PreferenceLanguageUtils.getString("language_target") - updateRecentLanguages() } - binding.listLanCommon5.layoutManager = - LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) - binding.listLanCommon5.adapter = recentAdapter } } + private fun handleLanguageSelection(language: Language) { + Log.d("LanguageChange", language.language) + if (lastTranslateLanguage) { + PreferenceLanguageUtils.putString("language_target", language.language) + } else { + PreferenceLanguageUtils.putString("language_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" + ) + PreferenceLanguageUtils.addRecentLanguage(language) + binding.tvChangeSource.text = PreferenceLanguageUtils.getString("language_source") + binding.tvChangeTarget.text = PreferenceLanguageUtils.getString("language_target") + updateRecentLanguages() + finish() + } + private fun initClick() { - binding.ivChBack.setOnClickListener { onBackPressed() } + binding.ivChBack.setOnClickListener { finish() } binding.tvChangeSource.setOnClickListener { lastTranslateLanguage = false binding.tvChangeSource.setTextColor(getColor(R.color.main_text_ff0e8ce8)) @@ -155,41 +158,35 @@ class LanguageChangeActivity : AppCompatActivity() { binding.tvExchange.setOnClickListener { val currentSourceLanguage = PreferenceLanguageUtils.getString("language_source") val currentTargetLanguage = PreferenceLanguageUtils.getString("language_target") - // 交换源语言和目标语言 PreferenceLanguageUtils.putString("language_source", currentTargetLanguage) PreferenceLanguageUtils.putString("language_target", currentSourceLanguage) - // 更新界面显示 binding.tvChangeSource.text = currentTargetLanguage binding.tvChangeTarget.text = currentSourceLanguage - onBackPressed() + FirebaseAnalyticsHelper.textTransSwitchEvent(MyApp.Config.CLICK_FROM, "home") + + finish() } - - } - private fun initAllList() { - val languages: ArrayList = LanguagesConstants.getInstance().getList(this) - if (languages.isNotEmpty()) { - val adapter = LanguageAdapter(this, languages) { _, language -> - Log.d("LanguageChange", language.language) - if (lastTranslateLanguage) { - PreferenceLanguageUtils.putString("language_target", language.language) - FirebaseAnalyticsHelper.languageChooseEvent("target_" + language.language) - onBackPressed() - } else { - PreferenceLanguageUtils.putString("language_source", language.language) - FirebaseAnalyticsHelper.languageChooseEvent("source_" + language.language) - onBackPressed() + private suspend fun initAllList() { + withContext(Dispatchers.IO) { + val languages: ArrayList = + LanguagesConstants.getInstance().getList(this@LanguageChangeActivity) + withContext(Dispatchers.Main) { + if (languages.isNotEmpty()) { + val adapter = + LanguageAdapter(this@LanguageChangeActivity, languages) { _, language -> + handleLanguageSelection(language) + } + binding.listLanguages.layoutManager = + LinearLayoutManager( + this@LanguageChangeActivity, + LinearLayoutManager.VERTICAL, + false + ) + binding.listLanguages.adapter = adapter } - PreferenceLanguageUtils.addRecentLanguage(language) - binding.tvChangeSource.text = PreferenceLanguageUtils.getString("language_source") - binding.tvChangeTarget.text = PreferenceLanguageUtils.getString("language_target") - updateRecentLanguages() } - binding.listLanguages.layoutManager = - LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) - binding.listLanguages.adapter = adapter } } - } 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 10b537b..8b7e8bf 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/MainActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/MainActivity.kt @@ -2,7 +2,6 @@ package com.assimilate.alltrans.viewui import android.app.ActivityManager import android.content.ActivityNotFoundException -import android.content.ClipDescription import android.content.ClipboardManager import android.content.Context import android.content.Intent @@ -18,7 +17,6 @@ import android.text.Editable import android.text.TextWatcher import android.util.Log import android.view.View -import android.widget.EditText import android.widget.Toast import androidx.activity.OnBackPressedCallback import androidx.activity.enableEdgeToEdge @@ -26,13 +24,16 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat +import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.R import com.assimilate.alltrans.allservice.SusService +import com.assimilate.alltrans.common.AppStore import com.assimilate.alltrans.common.FirebaseAnalyticsHelper +import com.assimilate.alltrans.common.LolAdWrapper import com.assimilate.alltrans.common.Widget import com.assimilate.alltrans.databinding.ActivityMainBinding -import com.assimilate.alltrans.keepmodel.LanguagesConstants -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils +import com.assimilate.alltrans.model.LanguagesConstants +import com.assimilate.alltrans.model.PreferenceLanguageUtils class MainActivity : AppCompatActivity() { @@ -50,7 +51,10 @@ class MainActivity : AppCompatActivity() { if (speech != null) { binding.etText.setText(speech) } else { - FirebaseAnalyticsHelper.textVoiceResultEvent("speech_is_null") + FirebaseAnalyticsHelper.textVoiceResultEvent( + MyApp.Config.FAIL_REASON, + "speech_is_null" + ) } } } @@ -71,6 +75,8 @@ class MainActivity : AppCompatActivity() { binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) + + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(26, systemBars.top + 26, 26, systemBars.bottom) @@ -98,7 +104,7 @@ class MainActivity : AppCompatActivity() { if (resultCode == RESULT_OK) { serverIsStart = true binding.ivQuickStart.setImageResource(R.drawable.main_setting_quick) - FirebaseAnalyticsHelper.hoverButtonClickEvent() + // 权限授予,启动截图 val serviceIntent = Intent(this, SusService::class.java).apply { @@ -110,23 +116,33 @@ class MainActivity : AppCompatActivity() { } else { startService(serviceIntent) } + FirebaseAnalyticsHelper.hoverButtonAgreeEvent() } else { Widget.makeToast( this, "Please allow access to screen information to identify the content that needs translation." ) + FirebaseAnalyticsHelper.hoverButtonCancelEvent() } } } private fun initView() { + LolAdWrapper.shared.loadAdShowNativeAd( + this, + "your_native_ad_placement", + binding.homeNative, + R.layout.ad_layout_admob_banner, + R.layout.ad_layout_max_banner + ) + binding.chSourceLanguage.text = PreferenceLanguageUtils.getString("language_source") binding.chTargetLanguage.text = PreferenceLanguageUtils.getString("language_target") } private fun initSet() { - FirebaseAnalyticsHelper.homePvEvent("create") + loadNative() val isRunning = isServiceRunning(this, SusService::class.java) if (isRunning) { @@ -142,17 +158,18 @@ class MainActivity : AppCompatActivity() { // 初始化截屏 mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager + FirebaseAnalyticsHelper.homePvEvent(MyApp.Config.CLICK_FROM, "create") } - private fun initClick() { binding.tvMainDic.setOnClickListener { // startActivity(Intent(this,DicActivity::class.java)) } + binding.tvMainPhotoTrans.setOnClickListener { startActivity( - Intent(this, PhotoImageActivity::class.java) + Intent(this, PhotoImageActivity::class.java).putExtra("key_start_ph", "camera") ) } binding.tvMainVoice.setOnClickListener { @@ -189,11 +206,12 @@ class MainActivity : AppCompatActivity() { startActivity( intent ) + FirebaseAnalyticsHelper.historyClickEvent() } binding.llQuickSet.setOnClickListener { - startActivity( - Intent(this, QuickSetActivity::class.java) - ) +// startActivity( +// Intent(this, QuickSetActivity::class.java) +// ) } binding.ivQuickStart.setOnClickListener { if (!serverIsStart) { @@ -205,6 +223,7 @@ class MainActivity : AppCompatActivity() { ) startActivityForResult(intent, REQUEST_CODE_OVERLAY) } else { + FirebaseAnalyticsHelper.hoverLimitAgreeEvent() checkAndRequestMediaProjectionPermission() } } else { @@ -212,9 +231,9 @@ class MainActivity : AppCompatActivity() { serverIsStart = false binding.ivQuickStart.setImageResource(R.drawable.main_setting_quick_def) - FirebaseAnalyticsHelper.hoverButtonCancelEvent() - } + } + FirebaseAnalyticsHelper.hoverButtonClickEvent() } @@ -270,7 +289,6 @@ class MainActivity : AppCompatActivity() { } - private fun checkAndRequestMediaProjectionPermission() { // 启动截图 startActivityForResult( @@ -321,7 +339,10 @@ class MainActivity : AppCompatActivity() { try { launcher.launch(speechIntent) } catch (ea: ActivityNotFoundException) { - FirebaseAnalyticsHelper.textVoiceResultEvent("device_not_support") + FirebaseAnalyticsHelper.textVoiceResultEvent( + MyApp.Config.FAIL_REASON, + "device_not_support" + ) Widget.makeToast(this, getString(R.string.main_voice_to_text)) } @@ -374,7 +395,7 @@ class MainActivity : AppCompatActivity() { override fun onRestart() { super.onRestart() - FirebaseAnalyticsHelper.homePvEvent("cap") + FirebaseAnalyticsHelper.homePvEvent(MyApp.Config.CLICK_FROM, "cap") } override fun onDestroy() { @@ -403,5 +424,14 @@ class MainActivity : AppCompatActivity() { onBackPressedDispatcher.addCallback(this, callback) } + private fun loadNative() { + LolAdWrapper.shared.loadAdShowNativeAd( + this, + MyApp.Config.home_native_auto, + binding.homeNative, + R.layout.ad_layout_admob_banner, + R.layout.ad_layout_max_banner + ) + } } \ No newline at end of file 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 e98846b..4959fa2 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/PhotoImageActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/PhotoImageActivity.kt @@ -16,6 +16,7 @@ import android.view.View import android.view.ViewTreeObserver import android.view.inputmethod.InputMethodManager import android.widget.Toast +import androidx.activity.OnBackPressedCallback import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.camera.core.CameraSelector @@ -30,12 +31,15 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.R import com.assimilate.alltrans.adapters.LanguageAdapter import com.assimilate.alltrans.common.BitmapUtils -import com.assimilate.alltrans.keepmodel.Language -import com.assimilate.alltrans.keepmodel.LanguagesConstants -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils +import com.assimilate.alltrans.common.FirebaseAnalyticsHelper +import com.assimilate.alltrans.common.LolAdWrapper +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 @@ -48,6 +52,8 @@ import com.google.mlkit.vision.text.devanagari.DevanagariTextRecognizerOptions import com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions import com.google.mlkit.vision.text.korean.KoreanTextRecognizerOptions import com.google.mlkit.vision.text.latin.TextRecognizerOptions +import com.lol.apex.ok.google.adlibrary.base.listener.LolLoadError +import com.lol.apex.ok.google.adlibrary.base.listener.LolShowError import java.io.File import java.io.IOException import java.text.SimpleDateFormat @@ -69,6 +75,7 @@ class PhotoImageActivity : AppCompatActivity() { private lateinit var outputDirectory: File private lateinit var cameraProviderFuture: ListenableFuture private var isFlashOn = false + private var fbFrom = "photo" private val REQUEST_CAMERA_PERMISSION = 100 private lateinit var bottomSheetDialog: BottomSheetDialog @@ -85,6 +92,7 @@ class PhotoImageActivity : AppCompatActivity() { v.setPadding(0, systemBars.top + 26, 0, systemBars.bottom) insets } + firebaseEvent() Widget.makeSnackbar(this, "Photographing text for translation") @@ -113,9 +121,20 @@ class PhotoImageActivity : AppCompatActivity() { // 检查并启动相机 checkCameraPermission() initView() + adLoad(MyApp.Config.image_camera_int_auto) + backPressedCall() initClick() } + private fun firebaseEvent() { + // 获取意图中的数据 + val eventKey = intent.getStringExtra("key_start_ph") + // 记录Firebase Analytics事件 + if (eventKey != null) { + FirebaseAnalyticsHelper.imageClickEvent(MyApp.Config.CLICK_FROM, eventKey) + } + } + private fun checkCameraPermission() { if (ContextCompat.checkSelfPermission( this, Manifest.permission.CAMERA @@ -131,7 +150,8 @@ class PhotoImageActivity : AppCompatActivity() { } } - private fun initView() { + + private fun initView() { binding.photoPreview.visibility = View.VISIBLE @@ -201,9 +221,18 @@ class PhotoImageActivity : AppCompatActivity() { PreferenceLanguageUtils.putString("language_source", language.language) selectedMode = PreferenceLanguageUtils.getString("language_source") + FirebaseAnalyticsHelper.languageFromEvent( + MyApp.Config.CLICK_FROM, + "photo_source" + ) + tryReloadAndDetectInImage() bottomSheetDialog.dismiss() } else { + FirebaseAnalyticsHelper.languageFromEvent( + MyApp.Config.CLICK_FROM, + "photo_target" + ) PreferenceLanguageUtils.putString("language_target", language.language) tryReloadAndDetectInImage() @@ -222,25 +251,28 @@ class PhotoImageActivity : AppCompatActivity() { } } - private fun initClick() { binding.ivStillPic.setOnClickListener { binding.photoPreview.visibility = View.INVISIBLE startChooseImageIntentForResult() + FirebaseAnalyticsHelper.imageTransPhotoEvent() } binding.ivStillTake.setOnClickListener { binding.photoPreview.visibility = View.VISIBLE takePhoto() + FirebaseAnalyticsHelper.imageTransCameraEvent() + } + binding.ivStillBack.setOnClickListener { + showInstAdFromCache(MyApp.Config.image_camera_int_auto) + finish() } - binding.ivStillBack.setOnClickListener { onBackPressed() } binding.ivStillBuling.setOnClickListener { toggleFlash() updateFlashButtonUI() } binding.stillSourceLanguage.setOnClickListener { chooseLanguage = false - bottomSheetDialog.show() } binding.stillTargetLanguage.setOnClickListener { @@ -257,6 +289,8 @@ class PhotoImageActivity : AppCompatActivity() { // 更新界面显示 binding.stillSourceLanguage.text = currentTargetLanguage binding.stillTargetLanguage.text = currentSourceLanguage + FirebaseAnalyticsHelper.textTransSwitchEvent(MyApp.Config.CLICK_FROM, "photo") + } } @@ -293,6 +327,7 @@ class PhotoImageActivity : AppCompatActivity() { } private fun takePhoto() { + fbFrom = "photo" val photoFile = File( outputDirectory, SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + ".jpg" @@ -378,30 +413,31 @@ class PhotoImageActivity : AppCompatActivity() { private fun createImageProcessor() { imageProcessor?.stop() try { + imageProcessor = when (selectedMode) { TEXT_RECOGNITION_CHINESE -> TextRecognitionProcessor( this, - ChineseTextRecognizerOptions.Builder().build(), true, true + ChineseTextRecognizerOptions.Builder().build(), true, true, fbFrom ) "Hindi", "Marathi", "Nepali", "Sanskrit" -> TextRecognitionProcessor( this, - DevanagariTextRecognizerOptions.Builder().build(), true, true + DevanagariTextRecognizerOptions.Builder().build(), true, true, fbFrom ) TEXT_RECOGNITION_JAPANESE -> TextRecognitionProcessor( this, - JapaneseTextRecognizerOptions.Builder().build(), true, true + JapaneseTextRecognizerOptions.Builder().build(), true, true, fbFrom ) TEXT_RECOGNITION_KOREAN -> TextRecognitionProcessor( this, - KoreanTextRecognizerOptions.Builder().build(), true, true + KoreanTextRecognizerOptions.Builder().build(), true, true, fbFrom ) else -> TextRecognitionProcessor( this, - TextRecognizerOptions.Builder().build(), true, true + TextRecognizerOptions.Builder().build(), true, true, fbFrom ) } @@ -481,6 +517,59 @@ class PhotoImageActivity : AppCompatActivity() { } } + private fun backPressedCall() { + val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + showInstAdFromCache(MyApp.Config.image_camera_int_auto) + finish() + } + } + onBackPressedDispatcher.addCallback(this, callback) + } + + + private fun adLoad(place: String) { + // 加载广告 + LolAdWrapper.shared.loadAdIfNotCached( + this, + place, + object : LolAdWrapper.LoLLoadListener { + override fun loadFailed(error: LolLoadError?) { + // Log.d("dsas",error.toString()) + + } + + override fun loaded() { + // 处理加载成功 + // Log.d("dsas","backSucc") + } + }) + + } + + 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() + } + }) + } + + companion object { private const val TAG = "StillImageActivity" private const val KEY_IMAGE_URI = "com.google.mlkit.demo.stillImage.KEY_IMAGE_URI" @@ -496,5 +585,7 @@ class PhotoImageActivity : AppCompatActivity() { private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS" private const val REQUEST_CHOOSE_IMAGE = 1001 } + + } 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 0a3f6ee..67261e7 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/QuickSetActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/QuickSetActivity.kt @@ -1,12 +1,15 @@ package com.assimilate.alltrans.viewui + import android.os.Bundle +import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.assimilate.alltrans.R import com.assimilate.alltrans.databinding.ActivityQuickSetBinding +import com.google.android.material.slider.Slider class QuickSetActivity : AppCompatActivity() { @@ -22,5 +25,25 @@ class QuickSetActivity : AppCompatActivity() { v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } + + sliderSet() + initClick() + } + + private fun initClick() { + binding.qsBack.setOnClickListener { finish() } + } + + private fun sliderSet() { + + binding.slider1.setLabelFormatter { value -> + val percentage = ((value / 5) * 100).toInt() + "$percentage%" + } + binding.slider1.addOnChangeListener(Slider.OnChangeListener { _, value, _ -> + val percentage = ((value / 5) * 100).toInt() + Toast.makeText(this, "Value: $percentage", Toast.LENGTH_SHORT).show() + + }) } } \ No newline at end of file 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 d65c648..e1fa658 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/SettingsActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/SettingsActivity.kt @@ -1,15 +1,17 @@ package com.assimilate.alltrans.viewui import android.content.Intent +import android.content.pm.PackageManager import android.net.Uri import android.os.Bundle +import android.widget.RatingBar import android.widget.TextView +import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.assimilate.alltrans.R -import com.assimilate.alltrans.common.Widget import com.assimilate.alltrans.databinding.ActivitySettingsBinding import com.google.android.material.bottomsheet.BottomSheetDialog @@ -18,6 +20,7 @@ class SettingsActivity : AppCompatActivity() { private lateinit var binding: ActivitySettingsBinding private lateinit var bottomSheetDialog: BottomSheetDialog + private var userChoose = 1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -30,25 +33,18 @@ class SettingsActivity insets } - initView() initClick() } private fun initView() { - // 设置 BottomSheetDialog - bottomSheetDialog = BottomSheetDialog(this) - bottomSheetDialog.setContentView(R.layout.bottomsheet_rate) - bottomSheetDialog.dismissWithAnimation = true - bottomSheetDialog.findViewById(R.id.tv_rate_commit)?.setOnClickListener { - Widget.makeSnackbar(this, getString(R.string.settings_rate_toast)) - bottomSheetDialog.dismiss() - } + setBottomSheet() + setVersion() } private fun initClick() { - binding.ivSetBack.setOnClickListener { onBackPressed() } + binding.ivSetBack.setOnClickListener { finish() } binding.llRate.setOnClickListener { bottomSheetDialog.show() @@ -66,6 +62,87 @@ class SettingsActivity intent.data = Uri.parse(url) startActivity(intent) } + binding.llShareApp.setOnClickListener { + val textDescription = "choose please." + val intentShare = Intent().setAction(Intent.ACTION_SEND).setType("text/plain") + var sAux = "\n" + getString(R.string.app_name) + "\n\n" + sAux += "https://play.google.com/store/apps/details?id=" + this.packageName + intentShare.putExtra(Intent.EXTRA_TEXT, sAux) + startActivity(Intent.createChooser(intentShare, textDescription)) + } } + + private fun setVersion() { + try { + // 获取 PackageInfo 对象 + val packageInfo = packageManager.getPackageInfo(packageName, 0) + val versionName = packageInfo.versionName + val versionCode = + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + packageInfo.longVersionCode + } else { + @Suppress("DEPRECATION") + packageInfo.versionCode.toLong() + } + + // 将版本信息设置到 TextView + binding.tvVersion.text = versionName.toString() + } catch (e: PackageManager.NameNotFoundException) { + e.printStackTrace() + binding.tvVersion.text = "1.1.1" + } + } + + private fun setBottomSheet() { + // 设置 BottomSheetDialog + bottomSheetDialog = BottomSheetDialog(this) + bottomSheetDialog.setContentView(R.layout.bottomsheet_rate) + bottomSheetDialog.dismissWithAnimation = true + + bottomSheetDialog.findViewById(R.id.tv_rate_commit)?.setOnClickListener { + toGoogleStar() + bottomSheetDialog.dismiss() + } + + bottomSheetDialog.findViewById(R.id.ratingBar) + ?.setOnRatingBarChangeListener { _, rating, fromUser -> + if (fromUser) { + userChoose = rating.toInt() + } + } + } + + private fun toGoogleStar() { + if (userChoose < 4) { + // 显示感谢消息 + Toast.makeText( + this, + "Thank you for your feedback; we will strive to do better.", + Toast.LENGTH_LONG + ).show() + + bottomSheetDialog.dismiss() + } else { + + // 构建 Google Play 评价页面的 URL + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$packageName")) + + // 检查是否有能够处理这个 Intent 的应用(如 Google Play 应用) + if (intent.resolveActivity(packageManager) != null) { + startActivity(intent) + } else { + // 如果 Google Play 应用不可用,则打开浏览器中的 Google Play 页面 + val webIntent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://play.google.com/store/apps/details?id=$packageName") + ) + startActivity(webIntent) + } + + bottomSheetDialog.dismiss() + } + } + + } \ 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 e9e1314..8cc337b 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/TextResultActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/TextResultActivity.kt @@ -10,6 +10,7 @@ import android.speech.tts.TextToSpeech import android.text.TextUtils import android.util.Log import android.widget.Toast +import androidx.activity.OnBackPressedCallback import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat @@ -17,15 +18,18 @@ import androidx.core.view.WindowInsetsCompat import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.R import com.assimilate.alltrans.common.FirebaseAnalyticsHelper -import com.assimilate.alltrans.keepmodel.LanguagesConstants +import com.assimilate.alltrans.model.LanguagesConstants import com.assimilate.alltrans.common.Logger -import com.assimilate.alltrans.keepmodel.PreferenceLanguageUtils +import com.assimilate.alltrans.common.LolAdWrapper +import com.assimilate.alltrans.model.PreferenceLanguageUtils import com.assimilate.alltrans.common.Widget import com.assimilate.alltrans.databinding.ActivityTextResultBinding import com.assimilate.alltrans.http.GoogleTranslator import com.assimilate.alltrans.http.Translator import com.assimilate.alltrans.mydb.DbTranslation import com.assimilate.alltrans.mydb.Translations +import com.lol.apex.ok.google.adlibrary.base.listener.LolLoadError +import com.lol.apex.ok.google.adlibrary.base.listener.LolShowError import java.util.Locale @@ -50,6 +54,10 @@ class TextResultActivity : AppCompatActivity() { } private fun initSet() { + backPressedCall() + adLoad(MyApp.Config.text_trans_int_auto) + adLoad(MyApp.Config.text_new_int_auto) + adLoad(MyApp.Config.text_camera_int_auto) // 获取Intent val intent = intent val receivedString = intent.getStringExtra("source_text") @@ -62,21 +70,36 @@ class TextResultActivity : AppCompatActivity() { Locale.getDefault() ) } - // checkLastTranslationCollectedAndSetIcon() + } + private fun backPressedCall() { + val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + showInstAdFromCache(MyApp.Config.text_trans_int_auto) + finish() + } + } + onBackPressedDispatcher.addCallback(this, callback) } private fun initClick() { - binding.ivTrBack.setOnClickListener { onBackPressed() } - binding.tvTrNewTrans.setOnClickListener { onBackPressed() } + binding.ivTrBack.setOnClickListener { + showInstAdFromCache(MyApp.Config.text_trans_int_auto) + finish() + } + binding.tvTrNewTrans.setOnClickListener { + + showInstAdFromCache(MyApp.Config.text_new_int_auto) + finish() + } binding.ivReToPhoto.setOnClickListener { - startActivity(Intent(this, PhotoImageActivity::class.java)) + showInstAdFromCache(MyApp.Config.text_camera_int_auto) } binding.ivTrCopy.setOnClickListener { copyToClipboard() FirebaseAnalyticsHelper.textTransCopyEvent() } - binding.ivSourceClear.setOnClickListener { onBackPressed() } + binding.ivSourceClear.setOnClickListener { finish() } binding.ivSourceTts.setOnClickListener { readText( binding.tvTrSource.text.toString(), @@ -111,7 +134,6 @@ class TextResultActivity : AppCompatActivity() { } - // 更新图标状态的方法 private fun updateCollectIcon(isCollected: Boolean) { if (isCollected) { @@ -121,14 +143,6 @@ class TextResultActivity : AppCompatActivity() { } } - // 检查最后一个翻译是否被收藏并更新图标 - private fun checkLastTranslationCollectedAndSetIcon() { - val dbTranslation = DbTranslation(this) - val lastTranslationCollected = dbTranslation.isLastTranslationCollected - updateCollectIcon(lastTranslationCollected) - } - - private fun translate(text: String) { if (text.isEmpty() || translating) { Logger.d("log", "translating(not post data)...") @@ -176,7 +190,10 @@ class TextResultActivity : AppCompatActivity() { override fun onFailure(errorMessage: String?) { translating = false - FirebaseAnalyticsHelper.textTransResultEvent("Translation failed: $errorMessage") + FirebaseAnalyticsHelper.textTransResultEvent( + MyApp.Config.FAIL_REASON, + "failed: $errorMessage" + ) runOnUiThread { // 显示失败信息或记录日志 if (!TextUtils.isEmpty(errorMessage)) { @@ -265,4 +282,74 @@ class TextResultActivity : AppCompatActivity() { tts.shutdown() } + + private fun doBack() { + finish() + } + + 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@TextResultActivity, + place, + object : LolAdWrapper.LolShowListener { + override fun shown() { + // 处理广告展示成功 + } + + override fun showFailed(error: LolShowError?) { + // 处理广告展示失败 + if (place == MyApp.Config.text_camera_int_auto) { + startActivity( + Intent( + this@TextResultActivity, + PhotoImageActivity::class.java + ).putExtra( + "key_start_ph", + "text" + ) + ) + } else { + doBack() + } + + + } + + override fun closed() { + // 处理广告关闭 + if (place == MyApp.Config.text_camera_int_auto) { + startActivity( + Intent( + this@TextResultActivity, + PhotoImageActivity::class.java + ).putExtra( + "key_start_ph", + "text" + ) + ) + } else { + doBack() + } + + } + }) + } + + } \ No newline at end of file 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 92ccf37..b4d9e31 100644 --- a/app/src/main/java/com/assimilate/alltrans/viewui/WelActivity.kt +++ b/app/src/main/java/com/assimilate/alltrans/viewui/WelActivity.kt @@ -2,11 +2,9 @@ package com.assimilate.alltrans.viewui import android.content.Intent import android.os.Bundle -import android.os.Handler -import android.os.Looper +import android.util.Log import android.view.ViewGroup import android.widget.Button -import android.widget.Toast import androidx.activity.OnBackPressedCallback import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity @@ -14,9 +12,12 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.assimilate.alltrans.MyApp import com.assimilate.alltrans.common.FirebaseAnalyticsHelper +import com.assimilate.alltrans.common.LolAdWrapper 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(){ private lateinit var binding: ActivityWelBinding override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() @@ -25,7 +26,6 @@ class WelActivity : AppCompatActivity() { setContentView(binding.root) //debugFirebase() - ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) @@ -52,20 +52,17 @@ class WelActivity : AppCompatActivity() { private fun initSet() { backPressedCall() - Handler(Looper.getMainLooper()).postDelayed({ - startActivity( - Intent(this, MainActivity::class.java) - ) - }, 2444) - - + if (MyApp.app.isFirstLaunch) { + adSplash(MyApp.Config.start_cold_int_auto) + } else { + adSplashHot(MyApp.Config.start_hot_int_auto) + } } private fun backPressedCall() { val callback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { - } } onBackPressedDispatcher.addCallback(this, callback) @@ -77,4 +74,82 @@ class WelActivity : AppCompatActivity() { } + private fun toNextPage() { + startActivity(Intent(this@WelActivity, MainActivity::class.java)) + } + + private fun adSplash(place: String) { + // 加载广告 + LolAdWrapper.shared.loadAdIfNotCached( + this, + place, + object : LolAdWrapper.LoLLoadListener { + override fun loadFailed(error: LolLoadError?) { + // 处理加载失败 + 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() + } + }) + } + }) + + } + + 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-xxxhdpi/ic_action_dns.webp b/app/src/main/res/drawable-xxxhdpi/ic_action_dns.webp new file mode 100644 index 0000000..481b337 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_dns.webp differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_settings.webp b/app/src/main/res/drawable-xxxhdpi/ic_action_settings.webp new file mode 100644 index 0000000..96263d7 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_settings.webp differ diff --git a/app/src/main/res/drawable/button_r20_white_bg_tlr.xml b/app/src/main/res/drawable/button_r20_white_bg_tlr.xml new file mode 100644 index 0000000..201426f --- /dev/null +++ b/app/src/main/res/drawable/button_r20_white_bg_tlr.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/stars_selector.xml b/app/src/main/res/drawable/stars_selector.xml new file mode 100644 index 0000000..0bd3992 --- /dev/null +++ b/app/src/main/res/drawable/stars_selector.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 661602c..e6a5764 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -44,263 +44,275 @@ app:srcCompat="@drawable/main_setting" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:orientation="vertical"> - + + + + + + + + + + android:layout_marginTop="12dp" + android:background="@drawable/button_r20_white_bg" + android:orientation="vertical" + android:paddingStart="12dp" + android:paddingTop="16dp" + android:paddingEnd="12dp" + android:paddingBottom="16dp"> - + - + + + + + + + + + + + + + + + + android:layout_marginTop="20dp" + android:background="@drawable/button_r20_white_bg" + android:minHeight="120dp" /> + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_quick_set.xml b/app/src/main/res/layout/activity_quick_set.xml index 9a6de14..75d777c 100644 --- a/app/src/main/res/layout/activity_quick_set.xml +++ b/app/src/main/res/layout/activity_quick_set.xml @@ -8,7 +8,6 @@ android:orientation="vertical"> diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index e8e7748..bc57210 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -108,8 +108,7 @@ android:layout_height="wrap_content" android:layout_marginTop="12dp" android:background="@drawable/button_r20_white_bg" - android:orientation="vertical" - android:visibility="gone"> + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/ad_layout_admob_result.xml b/app/src/main/res/layout/ad_layout_admob_result.xml new file mode 100644 index 0000000..7aa0453 --- /dev/null +++ b/app/src/main/res/layout/ad_layout_admob_result.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/ad_layout_max_banner.xml b/app/src/main/res/layout/ad_layout_max_banner.xml new file mode 100644 index 0000000..4165495 --- /dev/null +++ b/app/src/main/res/layout/ad_layout_max_banner.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +