diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f54c50b..b30e44e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,12 +14,12 @@ android { //com.funny.sounds.hd defaultConfig { - applicationId = "com.funny.sounds.hd.test" + applicationId = "com.funny.sounds.hd" minSdk = 23 targetSdk = 34 - versionCode = 7 - versionName = "1.6" - setProperty("archivesBaseName", "FunnySounds_v" + versionName + "(${versionCode})_$timestamp") + versionCode = 8 + versionName = "1.0.7" + setProperty("archivesBaseName", "Funny Sounds_v" + versionName + "(${versionCode})_$timestamp") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -73,7 +73,7 @@ dependencies { implementation("com.google.firebase:firebase-analytics-ktx") implementation("com.google.firebase:firebase-crashlytics-ktx") - //-----------------------------TopOn 聚合(mintegral、unityads、liftoff(vungle)、Bigo) + //-----------------------------------------------TopOn(pangle、IronSource、mintegral、unityads、liftoff(vungle)、Bigo) //Anythink (Necessary) implementation("com.anythink.sdk:core-tpn:6.3.68") implementation("com.anythink.sdk:nativead-tpn:6.3.68") @@ -96,10 +96,22 @@ dependencies { implementation("com.anythink.sdk:adapter-tpn-unityads:6.3.68") implementation("com.unity3d.ads:unity-ads:4.9.3") + //Ironsource + implementation("com.anythink.sdk:adapter-tpn-ironsource:6.3.68") + implementation("com.ironsource.sdk:mediationsdk:8.1.0") + implementation("com.google.android.gms:play-services-appset:16.0.2") + implementation("com.google.android.gms:play-services-ads-identifier:18.0.1") + implementation("com.google.android.gms:play-services-basement:18.1.0") + //Bigo implementation("com.anythink.sdk:adapter-tpn-bigo:6.3.68") implementation("com.bigossp:bigo-ads:4.7.4") + //Pangle + implementation("com.anythink.sdk:adapter-tpn-pangle-nonchina:6.3.68.1") + implementation( "com.pangle.global:ads-sdk:6.0.0.3") + implementation( "com.google.android.gms:play-services-ads-identifier:18.0.1") + //Mintegral implementation("com.anythink.sdk:adapter-tpn-mintegral-nonchina:6.3.68") implementation("com.mbridge.msdk.oversea:reward:16.7.51") @@ -112,12 +124,12 @@ dependencies { implementation("androidx.recyclerview:recyclerview:1.1.0") //Tramini -// implementation("com.anythink.sdk:tramini-plugin-tpn:6.3.68") - //-----------------------------TopOn 聚合 - + // implementation("com.anythink.sdk:tramini-plugin-tpn:6.3.68") // Debugger UI Tools - implementation ("com.anythink.sdk:debugger-ui:1.0.7") +// implementation ("com.anythink.sdk:debugger-ui:1.0.7") + + //----------------------------------------------TopOn diff --git a/app/google-services.json b/app/google-services.json index 573ceb2..9bbc388 100644 --- a/app/google-services.json +++ b/app/google-services.json @@ -9,7 +9,7 @@ "client_info": { "mobilesdk_app_id": "1:15060781613:android:cae5beb7e5d3e8946586a4", "android_client_info": { - "package_name": "com.funny.sounds.hd.test" + "package_name": "com.funny.sounds.hd" } }, "oauth_client": [], diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 4a2a235..93026b2 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -19,105 +19,109 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile --keep class com.omicronapplications.** { *; } --keep class net.sf.sevenzipjbinding.** { *; } --keep class com.google.gson.reflect.TypeToken { *; } --keep class * extends com.google.gson.reflect.TypeToken +# 保持 Room 的核心类不被混淆 +-keep class androidx.room.** { *; } +-keep class androidx.sqlite.db.** { *; } --keep class com.example.funnysounds.data.MyData { *; } --keep class com.example.funnysounds.data.CategoryList { *; } +# 保持 Room 数据库类的基本结构 +-keep class * extends androidx.room.RoomDatabase { *; } + +# 保持 Room DAO 接口 +-keep @androidx.room.Dao interface * { *; } +-keep @androidx.room.Dao class * { *; } + +# 保持 Room 实体类 +-keep @androidx.room.Entity class * { *; } + +# 保持 Room 的注解类 +-keep @androidx.room.Database class * { *; } + +#---------------------------------------------Topon +# Vungle +-dontwarn com.vungle.ads.** +-keepclassmembers class com.vungle.ads.** { + *; +} + +# Google +-keep class com.google.android.gms.** { *; } +-dontwarn com.google.android.gms.** + + + + +# START OkHttp + Okio +# JSR 305 annotations are for embedding nullability information. +-dontwarn javax.annotation.** + + +# A resource is loaded with a relative path so the package of this class must be preserved. +-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz + + +# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java. +-dontwarn org.codehaus.mojo.animal_sniffer.* + + +# OkHttp platform used only on JVM and when Conscrypt and other security providers are available. +-dontwarn okhttp3.internal.platform.** +-dontwarn org.conscrypt.** +-dontwarn org.bouncycastle.** +-dontwarn org.openjsse.** + + +# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java. +-dontwarn org.codehaus.mojo.animal_sniffer.* + + +# END OkHttp + Okio + + +# START Protobuf +-dontwarn com.google.protobuf.** +-keepclassmembers class com.google.protobuf.** { + *; +} +-keep class * extends com.google.protobuf.GeneratedMessageLite { *; } + + +# END Protobuf +-keepclassmembers class com.ironsource.sdk.controller.IronSourceWebView$JSInterface { + public *; +} +-keepclassmembers class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} +-keep public class com.google.android.gms.ads.** { + public *; +} +-keep class com.ironsource.adapters.** { *; +} +-dontwarn com.ironsource.mediationsdk.** +-dontwarn com.ironsource.adapters.** +-keepattributes JavascriptInterface +-keepclassmembers class * { + @android.webkit.JavascriptInterface ; +} +-keep class com.bytedance.sdk.** { *; } -keepattributes Signature -keepattributes *Annotation* -keep class com.mbridge.** {*; } -keep interface com.mbridge.** {*; } +-keep class android.support.v4.** { *; } -dontwarn com.mbridge.** --keepclassmembers class **.R$* { public static final int mbridge*; } - +-keep class **.R$* { public static final int mbridge*; } -keep public class com.mbridge.* extends androidx.** { *; } --keep public class androidx.viewpager.widget.PagerAdapter{*;} --keep interface androidx.annotation.IntDef{*;} --keep interface androidx.annotation.Nullable{*;} --keep interface androidx.annotation.CheckResult{*;} --keep interface androidx.annotation.NonNull{*;} --keep public class androidx.fragment.app.Fragment{*;} --keep public class androidx.core.content.FileProvider{*;} --keep public class androidx.core.app.NotificationCompat{*;} --keep public class androidx.appcompat.widget.AppCompatImageView {*;} --keep public class androidx.recyclerview.*{*;} --keep class com.mbridge.msdk.foundation.tools.FastKV{*;} --keep class com.mbridge.msdk.foundation.tools.FastKV$Builder{*;} - - #---------------------------------TopOn 聚合 - # Vungle - -dontwarn com.vungle.ads.** - -keepclassmembers class com.vungle.ads.** { - *; - } - - - - - # Google - -keep class com.google.android.gms.** { *; } - -dontwarn com.google.android.gms.** - - - - - # START OkHttp + Okio - # JSR 305 annotations are for embedding nullability information. - -dontwarn javax.annotation.** - - - # A resource is loaded with a relative path so the package of this class must be preserved. - -adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz - - - # Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java. - -dontwarn org.codehaus.mojo.animal_sniffer.* - - - # OkHttp platform used only on JVM and when Conscrypt and other security providers are available. - -dontwarn okhttp3.internal.platform.** - -dontwarn org.conscrypt.** - -dontwarn org.bouncycastle.** - -dontwarn org.openjsse.** - - - # Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java. - -dontwarn org.codehaus.mojo.animal_sniffer.* - - - # END OkHttp + Okio - - - # START Protobuf - -dontwarn com.google.protobuf.** - -keepclassmembers class com.google.protobuf.** { - *; - } - -keep class * extends com.google.protobuf.GeneratedMessageLite { *; } - - - # END Protobuf - -keepattributes Signature - -keepattributes *Annotation* - -keep class com.mbridge.** {*; } - -keep interface com.mbridge.** {*; } - -keep class android.support.v4.** { *; } - -dontwarn com.mbridge.** - -keep class **.R$* { public static final int mbridge*; } - -keep public class com.mbridge.* extends androidx.** { *; } - -keep public class androidx.viewpager.widget.PagerAdapter{ *; } - -keep interface androidx.annotation.IntDef{ *; } - -keep interface androidx.annotation.Nullable{ *; } - -keep interface androidx.annotation.CheckResult{ *; } - -keep interface androidx.annotation.NonNull{ *; } - -keep public class androidx.fragment.app.Fragment{ *; } - -keep public class androidx.core.content.FileProvider{ *; } - -keep public class androidx.core.app.NotificationCompat{ *; } - -keep public class androidx.appcompat.widget.AppCompatImageView { *; } - -keep public class androidx.recyclerview.*{ *; } - - #---------------------------------TopOn 聚合 +-keep public class androidx.viewpager.widget.PagerAdapter{ *; } +-keep public class androidx.viewpager.widget.ViewPager.OnPageChangeListener{ *; } +-keep interface androidx.annotation.IntDef{ *; } +-keep interface androidx.annotation.Nullable{ *; } +-keep interface androidx.annotation.CheckResult{ *; } +-keep interface androidx.annotation.NonNull{ *; } +-keep public class androidx.fragment.app.Fragment{ *; } +-keep public class androidx.core.content.FileProvider{ *; } +-keep public class androidx.core.app.NotificationCompat{ *; } +-keep public class androidx.appcompat.widget.AppCompatImageView { *; } +-keep public class androidx.recyclerview.*{ *; } +#---------------------------------------------Topon diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8f14ecf..8cfd6e8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -38,6 +38,9 @@ + @@ -48,7 +51,7 @@ diff --git a/app/src/main/assets/myfont.ttf b/app/src/main/assets/myfont.ttf deleted file mode 100644 index 15181a4..0000000 Binary files a/app/src/main/assets/myfont.ttf and /dev/null differ diff --git a/app/src/main/java/com/example/funnysounds/activity/DetailActivity.java b/app/src/main/java/com/example/funnysounds/activity/DetailActivity.java index 9d2343a..5823e86 100644 --- a/app/src/main/java/com/example/funnysounds/activity/DetailActivity.java +++ b/app/src/main/java/com/example/funnysounds/activity/DetailActivity.java @@ -1,6 +1,7 @@ package com.example.funnysounds.activity; import android.content.Intent; +import android.content.IntentFilter; import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.media.AudioManager; @@ -14,6 +15,7 @@ import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; +import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; @@ -47,7 +49,7 @@ public class DetailActivity extends AppCompatActivity { private TextView textView; private ImageView imageView, imageView2; private MediaPlayer mediaPlayer; - protected Button btn_play_pause; + protected ImageView btn_play_pause; private boolean play = false; private SeekBar volumeSeekbar; private ImageView imLoop, imAddLove; @@ -58,6 +60,22 @@ public class DetailActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_detail); + RelativeLayout loadingAd = findViewById(R.id.loading_ad); + AdManager.loadAllAd(); + StaticValue.enterDetailCount++; + + if (StaticValue.enterDetailCount % 2 != 0) { + loadingAd.setVisibility(View.VISIBLE); + AdManager.showTopOn(DetailActivity.this, new onActionListener() { + @Override + public void onAction() { + loadingAd.setVisibility(View.GONE); + } + }); + }else { + loadingAd.setVisibility(View.GONE); + } + textView = findViewById(R.id.data_name); imageView = findViewById(R.id.data_image); imageView2 = findViewById(R.id.imageview_back); @@ -88,8 +106,9 @@ public class DetailActivity extends AppCompatActivity { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); - int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - seekBar.setMax(maxVolume); + int curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + Log.d(Sounds.TAG,"---------onChange selfChange="+selfChange); + seekBar.setProgress(curVolume); } }); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @@ -114,7 +133,7 @@ public class DetailActivity extends AppCompatActivity { textView.setText(resource.getTitle()); media = resource.getMp3Url(); - Log.d("----", "---media" + media); + MyRoom.getInstance().getDataDao().queryAudioIsLove(resource.getId()).observe(this, new Observer() { @Override public void onChanged(MyData myData) { @@ -153,7 +172,7 @@ public class DetailActivity extends AppCompatActivity { mediaPlayer.setDataSource(this, parse); } - mediaPlayer.prepare(); + mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { @@ -164,6 +183,7 @@ public class DetailActivity extends AppCompatActivity { mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { + Log.d(Sounds.TAG, "--onCompletion-false"); btn_play_pause.setSelected(false); } }); @@ -213,18 +233,14 @@ public class DetailActivity extends AppCompatActivity { public void onClick(View v) { btn_play_pause.setSelected(!btn_play_pause.isSelected()); if (btn_play_pause.isSelected()) { - AdManager.showTopOn(DetailActivity.this, new onActionListener() { - @Override - public void onAction() { - if (mediaPlayer != null && !mediaPlayer.isPlaying()) { - mediaPlayer.start(); - } - - } - }); + Log.d(Sounds.TAG, "---true"); + if (mediaPlayer != null && !mediaPlayer.isPlaying()) { + mediaPlayer.start(); + } } else { + Log.d(Sounds.TAG, "---false"); if (mediaPlayer != null && mediaPlayer.isPlaying()) { - mediaPlayer.stop(); + mediaPlayer.pause(); } } } diff --git a/app/src/main/java/com/example/funnysounds/activity/IntoActivity.java b/app/src/main/java/com/example/funnysounds/activity/IntoActivity.java index 241071f..dcee2e8 100644 --- a/app/src/main/java/com/example/funnysounds/activity/IntoActivity.java +++ b/app/src/main/java/com/example/funnysounds/activity/IntoActivity.java @@ -3,13 +3,11 @@ package com.example.funnysounds.activity; import android.content.Intent; import android.os.Bundle; import android.os.CountDownTimer; -import android.util.Log; import android.widget.ProgressBar; import androidx.appcompat.app.AppCompatActivity; import com.example.funnysounds.R; -import com.example.funnysounds.resolve.Sounds; import com.example.funnysounds.topon.CountAction; import com.example.funnysounds.topon.GoMainAction; import com.example.funnysounds.topon.AdManager; @@ -18,8 +16,9 @@ public class IntoActivity extends AppCompatActivity { protected CountDownTimer countDownTimer; - private long tim = 1000L; + private long tim = 12000L; private ProgressBar progressBar; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -29,9 +28,15 @@ public class IntoActivity extends AppCompatActivity { countDownTimer = AdManager.showWelcomeAd(IntoActivity.this, tim, new CountAction() { @Override public void onCount(long millisUntilFinished) { - float l1 = (float)millisUntilFinished / tim; - float v = 100-l1 * 100; + float l1 = (float) millisUntilFinished / tim; + float v = 100 - l1 * 100; progressBar.setProgress((int) v); + if (AdManager.place1LoadFail && AdManager.place2LoadFail && AdManager.place3LoadFail) { + if (countDownTimer != null) { + countDownTimer.cancel(); + } + startMainActivity(); + } } }, new GoMainAction() { @Override @@ -43,11 +48,9 @@ public class IntoActivity extends AppCompatActivity { } - - private void startMainActivity() { progressBar.setProgress(100); - Intent intent = new Intent(this, MainActivity.class); + Intent intent = new Intent(this, MainActivity.class); startActivity(intent); finish(); } diff --git a/app/src/main/java/com/example/funnysounds/activity/LogActivity.kt b/app/src/main/java/com/example/funnysounds/activity/LogActivity.kt new file mode 100644 index 0000000..2f5ae96 --- /dev/null +++ b/app/src/main/java/com/example/funnysounds/activity/LogActivity.kt @@ -0,0 +1,381 @@ +package com.example.funnysounds.activity + +import android.annotation.SuppressLint +import android.app.Activity +import android.app.ActivityManager +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.graphics.Point +import android.hardware.Sensor +import android.hardware.SensorManager +import android.os.Build +import android.os.Bundle +import android.os.StrictMode +import android.os.SystemClock +import android.telephony.TelephonyManager +import android.text.TextUtils +import android.util.Log +import android.view.WindowManager +import android.webkit.WebView +import androidx.appcompat.app.AppCompatActivity +import com.example.funnysounds.databinding.LayoutLogBinding +import org.json.JSONArray +import org.json.JSONObject +import java.io.File +import java.text.SimpleDateFormat +import java.util.Arrays +import java.util.Date +import java.util.Locale +import java.util.TimeZone +import kotlin.math.pow +import kotlin.math.sqrt + + +@SuppressLint("WrongConstant") +class LogActivity : AppCompatActivity() { + + private lateinit var binding: LayoutLogBinding + + @SuppressLint("SetJavaScriptEnabled") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = LayoutLogBinding.inflate(layoutInflater) + setContentView(binding.root) + val json = getJson() + + binding.log.text = json.toString(2) + } + + private fun getJson(): JSONObject { + val jSONObject = JSONObject() + + val info = getWebViewPackageInfo(this) + val versionCode = info?.versionCode + val versionName = info?.versionName + val packageName = info?.packageName + val glEsVersion = glEsVersion() + + jSONObject.put("当前手机时间", convertTimestampToDate(System.currentTimeMillis())) + jSONObject.put("WebView versionCode", versionCode) + jSONObject.put("WebView versionName", versionName) + jSONObject.put("WebView packageName", packageName) + jSONObject.put("OpenGL ES", glEsVersion) + jSONObject.put("当前app的版本", "此后对应线上的版本") + jSONObject.put("sdk_version", "前使用的广告 SDK 的版本号") + jSONObject.put("first_install", "是否是第一次安装应用") + jSONObject.put("Android版本的API级别(api_level)", Build.VERSION.SDK_INT) + jSONObject.put("设备的制造商名称(brand)", Build.MANUFACTURER) + jSONObject.put("制造商的品牌名称(brand_name)", Build.BRAND) + jSONObject.put("设备的硬件名称(hardware)", Build.HARDWARE) + jSONObject.put("唯一标识此构建的字符串(fingerprint)", Build.FINGERPRINT) + jSONObject.put("检测设备是否为模拟器(sim)", isEmulator()) + jSONObject.put("aida", "判断是否") + jSONObject.put("当前设备的默认区域设置(locale)", Locale.getDefault().toString()) + jSONObject.put("设备的具体型号(model)", Build.MODEL) + jSONObject.put("设备当前操作系统的版本号(os)", Build.VERSION.RELEASE) + jSONObject.put( + "判断设备是否是 Amazon 的 Fire OS 系统或 Fire TV (platform)", + isFireOS(this) + ) + jSONObject.put("设备的内部代码名(revision)", Build.DEVICE) + jSONObject.put("当前时区的偏移量(tz_offset)", tzOffset()) + jSONObject.put("设备是否配备了特定类型的传感器(gy)", gy()) + jSONObject.put("设备当前 SIM 卡的国家代码(country_code)", getSimCountryIso(this)) + jSONObject.put("获取当前设备的移动国家码(MCC)", mcc()) + jSONObject.put("获取当前设备的移动网络码(MNC)", mnc()) + jSONObject.put("获取当前设备的运营商名称(carrier)", networkOperatorName()) + jSONObject.put("获取设备SIM卡状态", getSimState(this)) + jSONObject.put("is_tablet", "是否为平板") + jSONObject.put("是否为电视(tv)", isTv(this)) + jSONObject.put("可用处理器数量(pc)", Runtime.getRuntime().availableProcessors()) + jSONObject.put("获取 HDR 屏幕信息(hdr)", isScreenHdr()) + jSONObject.put("此设备支持的 ABI (supported_abis)", cpu()) + val displayMetrics = resources.displayMetrics + if (displayMetrics != null) { + jSONObject.put("屏幕宽度", displayMetrics.widthPixels); + jSONObject.put("屏幕高度", displayMetrics.heightPixels); + jSONObject.put("存储屏幕密度(adns)", displayMetrics.density) + jSONObject.put( + "存储屏幕密度 DPI(adnsd)", + Integer.valueOf(displayMetrics.densityDpi) + ) + jSONObject.put("存储 X 方向的像素密度(xdpi)", displayMetrics.xdpi) + jSONObject.put("存储 Y 方向的像素密度(ydpi)", displayMetrics.ydpi) + // 获取屏幕尺寸(宽度和高度) + val screenSize = Point().apply { + // 获取屏幕宽度和高度 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + display?.getRealSize(this) + } else { + windowManager.defaultDisplay.getRealSize(this) + } + + } + val screenWidthInInches = screenSize.x.toDouble() / displayMetrics.xdpi + val screenHeightInInches = screenSize.y.toDouble() / displayMetrics.ydpi + val screenSizeInInches = + sqrt(screenWidthInInches.pow(2.0) + screenHeightInInches.pow(2.0)) + + jSONObject.put("屏幕尺寸(screen_size_in)", screenSizeInInches) + } + jSONObject.put( + "当前系统时间与系统启动时间之间的差值(bt_ms)", + convertTimestampToDate(System.currentTimeMillis() - SystemClock.elapsedRealtime()) + ) + jSONObject.put( + "psase", + "如何>34 && 不是亚马逊os系统和fire tv && 检查广告服务状态是否启用" + ) + jSONObject.put("process_name", "通过当前进程 ID 查找并返回对应的进程名称") + jSONObject.put("is_main_process", "判断当前进程是否为应用的主进程") + jSONObject.put("com.android.vending", "获取google商店的versionCode与versionName") + val lastModified = File(applicationInfo.sourceDir).lastModified() + jSONObject.put( + "获取当前安装的应用程序的APK文件的最后修改时间(ia)", + convertTimestampToDate(lastModified) + ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + jSONObject.put( + "安装应用程序的来源(installer_name_info)", + "${packageManager.getInstallSourceInfo(applicationInfo.packageName).installingPackageName}" + ) + } else { + jSONObject.put( + "安装应用程序的来源(installer_name)", + "${packageManager.getInstallerPackageName(applicationInfo.packageName)}" + ) + } + jSONObject.put("omid 版本", "用于检测广告是否有效曝光及检测广告的可见性") + + Log.d("tang", jSONObject.toString()) + return jSONObject + } + + fun toJSONArray(strArr: Array?): JSONArray? { + if (strArr == null) { + return null + } + val jsonArray = JSONArray() + for (str in strArr) { + jsonArray.put(str) + } + return jsonArray + } + + private fun cpu(): JSONArray? { + val array = toJSONArray(Build.SUPPORTED_ABIS) + return array + } + + private fun isScreenHdr(): Boolean? { + return if (Build.VERSION.SDK_INT >= 26) { + resources.configuration.isScreenHdr + } else { + null + } + } + + fun isTv(context: Activity): Boolean { + if (isFireTv(context)) { + return true + } + val packageManager: PackageManager = context.packageManager + if (Build.VERSION.SDK_INT >= 21) { + return packageManager.hasSystemFeature("android.software.leanback") + } + return packageManager.hasSystemFeature("android.hardware.type.television") + } + + + private fun networkOperatorName(): String { + val telephonyManager = getSystemService("phone") as TelephonyManager + return try { + telephonyManager.networkOperatorName + } catch (e: Exception) { + "" + } + } + + + private fun mnc(): String { + val telephonyManager = getSystemService("phone") as TelephonyManager + return try { + val networkOperator = telephonyManager.networkOperator + networkOperator.substring(3.coerceAtMost(networkOperator.length)) + } catch (e: Exception) { + "" + } + } + + private fun mcc(): String { + val telephonyManager = getSystemService("phone") as TelephonyManager + return try { + val networkOperator = telephonyManager.networkOperator + networkOperator.substring(0, minOf(3, networkOperator.length)) + } catch (e: Exception) { + "" + } + } + + private fun gy(): Boolean { + val sensorManager = getSystemService("sensor") as SensorManager + return sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR) != null + } + + private fun tzOffset(): Double { + return Math.round( + (TimeZone.getDefault().getOffset(Date().getTime()) * 10.0) / 3600000.0 + ) / 10.0 + } + + fun getOrientation(): Int { + return resources.configuration.orientation + } + + + fun getWebViewPackageInfo(context: Activity): PackageInfo? { + val packageManager: PackageManager = context.packageManager + + // 如果系统支持直接获取 WebView 包信息 (Android 7.0 及以上) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return WebView.getCurrentWebViewPackage() + } + + // 如果不支持,尝试通过常见的 WebView 包名来获取信息 + val webviewPackageNames = listOf( + "com.google.android.webview", + "com.android.webview", + "com.android.chrome" + ) + + for (packageName in webviewPackageNames) { + try { + val packageInfo = packageManager.getPackageInfo(packageName, 0) + if (packageInfo != null) { + return packageInfo + } + } catch (e: PackageManager.NameNotFoundException) { + // 忽略异常,继续尝试下一个包名 + } + } + + // 如果都没有找到,返回 null + return null + } + + fun convertTimestampToDate(timestamp: Long): String { + // 创建 SimpleDateFormat 实例 + val format = "yyyy-MM-dd HH:mm:ss" + val dateFormat = SimpleDateFormat(format, Locale.getDefault()) + dateFormat.timeZone = TimeZone.getTimeZone("GMT") // 设置时区为 UTC,或者根据需要选择其他时区 + + // 将时间戳转换为 Date 对象 + val date = Date(timestamp) + + // 格式化 Date 对象为指定格式的字符串 + return dateFormat.format(date) + } + + + fun glEsVersion(): String? { + val activityManager = this.getSystemService("activity") as ActivityManager + return activityManager.deviceConfigurationInfo.glEsVersion + } + + fun isFireOS(context: Activity): Boolean { + return "amazon".equals(Build.MANUFACTURER, ignoreCase = true) || isFireTv(context) + } + + fun isFireTv(context: Activity): Boolean { + return context.packageManager.hasSystemFeature("amazon.hardware.fire_tv") + } + + private fun getSimCountryIso(context: Activity): String { + val telephonyManager = context.getSystemService("phone") as TelephonyManager? + return telephonyManager?.simCountryIso?.uppercase(Locale.ENGLISH) ?: "" + } + + private fun getSimState(context: Activity): Int { + val telephonyManager = context.getSystemService("phone") as TelephonyManager? + return telephonyManager?.simState ?: -1 + } + + private val a = HashMap(2) + + fun point(context: Activity): Point { + val orientation = getOrientation() + val map = a + + // Check if the point for the given orientation is already cached + if (map.containsKey(orientation)) { + return map[orientation]!! + } + + // Initialize default point + val point = Point() + point.x = 480 + point.y = 320 + + val vmPolicy = StrictMode.getVmPolicy() + StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX) + + // Get window manager + val windowManager = context.getSystemService("window") as? WindowManager + + windowManager?.let { + val defaultDisplay = it.defaultDisplay + when { + Build.VERSION.SDK_INT >= 30 -> { + val bounds = it.maximumWindowMetrics.bounds + point.set(bounds.width(), bounds.height()) + } + + else -> { + defaultDisplay.getRealSize(point) + } + } + } + + // Restore the original VM policy + StrictMode.setVmPolicy(vmPolicy) + + // Cache the point for the orientation + map[orientation] = point + + return point + } + + + fun isEmulator(): Boolean { + return checkText(Build.DEVICE, "goldfish,vbox") || checkText( + Build.HARDWARE, + "ranchu,generic,vbox" + ) || checkText(Build.MANUFACTURER, "Genymotion") || checkText( + Build.MODEL, + "Android SDK built for x86" + ) + } + + private fun checkText(str: String, str2: String): Boolean { + return startsWithAtLeastOnePrefix(str, explode(str2)) + } + + fun explode(str: String): List { + return explode(str, ",\\s*") + } + + fun explode(str: String, str2: String): List { + return if (TextUtils.isEmpty(str)) emptyList() else Arrays.asList( + *str.split(str2.toRegex()).dropLastWhile { it.isEmpty() } + .toTypedArray()) + } + + fun startsWithAtLeastOnePrefix(str: String, list: List): Boolean { + for (str2 in list) { + if (str.startsWith(str2!!)) { + return true + } + } + return false + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/funnysounds/activity/MainActivity.java b/app/src/main/java/com/example/funnysounds/activity/MainActivity.java index b859022..801d923 100644 --- a/app/src/main/java/com/example/funnysounds/activity/MainActivity.java +++ b/app/src/main/java/com/example/funnysounds/activity/MainActivity.java @@ -4,13 +4,12 @@ import android.annotation.SuppressLint; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Bundle; +import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; @@ -24,9 +23,12 @@ import com.example.funnysounds.databinding.ActivityMainBinding; import com.example.funnysounds.fragement.CategoryFragment; import com.example.funnysounds.fragement.LoveFragment; import com.example.funnysounds.fragement.RecordFragment; +import com.example.funnysounds.resolve.Sounds; +import com.example.funnysounds.topon.AdManager; import com.google.android.material.tabs.TabLayout; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class MainActivity extends AppCompatActivity { @@ -34,6 +36,11 @@ public class MainActivity extends AppCompatActivity { private ActivityMainBinding vb; + + private long lastClickTime = 0; + private int ContinuousClick = 1; + private static final int MIN_CLICK_DELAY_TIME = 1000; + @SuppressLint("MissingInflatedId") @Override protected void onCreate(Bundle savedInstanceState) { @@ -41,6 +48,7 @@ public class MainActivity extends AppCompatActivity { vb = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(vb.getRoot()); initTabVp(); + AdManager.loadAllAd(); vb.imageMenu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -62,6 +70,24 @@ public class MainActivity extends AppCompatActivity { vb.textVersion.setText(format); } + vb.version.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + long currentTime = System.currentTimeMillis(); + if (currentTime - lastClickTime < MIN_CLICK_DELAY_TIME) { + ContinuousClick++; + Log.d(Sounds.TAG, "----------连续点击次数--" + ContinuousClick); + if (ContinuousClick == 5) { + Intent intent = new Intent(MainActivity.this, LogActivity.class); + startActivity(intent); + } + } else { + ContinuousClick = 1; + } + lastClickTime = currentTime; + } + }); + } private void initTabVp() { @@ -138,9 +164,9 @@ public class MainActivity extends AppCompatActivity { private void updateTitle(int position) { if (position == 0) { vb.textviewSounds.setText(getString(R.string.app_name)); - }else if (position == 1) { + } else if (position == 1) { vb.textviewSounds.setText(getString(R.string.create_sounds)); - }else if (position == 2) { + } else if (position == 2) { vb.textviewSounds.setText(getString(R.string.favorites)); } } diff --git a/app/src/main/java/com/example/funnysounds/activity/RecordAudioActivity.java b/app/src/main/java/com/example/funnysounds/activity/RecordAudioActivity.java index df85a5b..6595a2d 100644 --- a/app/src/main/java/com/example/funnysounds/activity/RecordAudioActivity.java +++ b/app/src/main/java/com/example/funnysounds/activity/RecordAudioActivity.java @@ -12,6 +12,7 @@ import android.view.View; import com.example.funnysounds.R; import com.example.funnysounds.databinding.ActivityRecordAudioBinding; import com.example.funnysounds.resolve.Utils; +import com.example.funnysounds.topon.AdManager; import com.example.funnysounds.value.StaticValue; import java.io.File; @@ -30,7 +31,7 @@ public class RecordAudioActivity extends AppCompatActivity { vb = ActivityRecordAudioBinding.inflate(getLayoutInflater()); setContentView(vb.getRoot()); vb.top.imAddLove.setVisibility(View.GONE); - + AdManager.loadAllAd(); vb.top.dataName.setText(getString(R.string.new_record)); vb.top.imageviewBack.setOnClickListener((view) -> finish()); initMediaRecorder(); diff --git a/app/src/main/java/com/example/funnysounds/activity/SaveRecordActivity.java b/app/src/main/java/com/example/funnysounds/activity/SaveRecordActivity.java index d326420..8111b91 100644 --- a/app/src/main/java/com/example/funnysounds/activity/SaveRecordActivity.java +++ b/app/src/main/java/com/example/funnysounds/activity/SaveRecordActivity.java @@ -17,6 +17,7 @@ import com.example.funnysounds.resolve.Readfile; import com.example.funnysounds.resolve.Sounds; import com.example.funnysounds.resolve.Utils; import com.example.funnysounds.room.MyRoom; +import com.example.funnysounds.topon.AdManager; import com.example.funnysounds.value.StaticValue; import java.io.File; @@ -40,7 +41,7 @@ public class SaveRecordActivity extends AppCompatActivity { vb.top.imAddLove.setVisibility(View.GONE); vb.top.imageviewBack.setOnClickListener((view) -> finish()); init(); - + AdManager.loadAllAd(); } private void init() { diff --git a/app/src/main/java/com/example/funnysounds/activity/SpecifisoundsActivity.java b/app/src/main/java/com/example/funnysounds/activity/SpecifisoundsActivity.java index ce3c73c..88794e7 100644 --- a/app/src/main/java/com/example/funnysounds/activity/SpecifisoundsActivity.java +++ b/app/src/main/java/com/example/funnysounds/activity/SpecifisoundsActivity.java @@ -54,7 +54,7 @@ public class SpecifisoundsActivity extends AppCompatActivity implements MyDataSo }); getData(); setSpecificRecycleView(); - + AdManager.loadAllAd(); } diff --git a/app/src/main/java/com/example/funnysounds/activity/WebActivity.java b/app/src/main/java/com/example/funnysounds/activity/WebActivity.java index 9bcbcc5..f18765c 100644 --- a/app/src/main/java/com/example/funnysounds/activity/WebActivity.java +++ b/app/src/main/java/com/example/funnysounds/activity/WebActivity.java @@ -8,6 +8,7 @@ import androidx.appcompat.app.AppCompatActivity; import com.example.funnysounds.R; import com.example.funnysounds.databinding.ActivityWebBinding; +import com.example.funnysounds.topon.AdManager; public class WebActivity extends AppCompatActivity { @@ -18,6 +19,7 @@ public class WebActivity extends AppCompatActivity { super.onCreate(savedInstanceState); vb = ActivityWebBinding.inflate(getLayoutInflater()); setContentView(vb.getRoot()); + AdManager.loadAllAd(); vb.top.imAddLove.setVisibility(View.GONE); vb.top.dataName.setText(getString(R.string.privacy_policy)); vb.top.imageviewBack.setOnClickListener(new View.OnClickListener() { diff --git a/app/src/main/java/com/example/funnysounds/fragement/CategoryFragment.java b/app/src/main/java/com/example/funnysounds/fragement/CategoryFragment.java index f29b4a3..cfd5c33 100644 --- a/app/src/main/java/com/example/funnysounds/fragement/CategoryFragment.java +++ b/app/src/main/java/com/example/funnysounds/fragement/CategoryFragment.java @@ -14,9 +14,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.example.funnysounds.R; import com.example.funnysounds.action.CategoryNameSoundsrListener; -import com.example.funnysounds.activity.MainActivity; import com.example.funnysounds.data.CategoryList; import com.example.funnysounds.databinding.FragmentCategoryBinding; import com.example.funnysounds.resolve.MySpace; diff --git a/app/src/main/java/com/example/funnysounds/resolve/Sounds.java b/app/src/main/java/com/example/funnysounds/resolve/Sounds.java index 37c296d..75fe8c1 100644 --- a/app/src/main/java/com/example/funnysounds/resolve/Sounds.java +++ b/app/src/main/java/com/example/funnysounds/resolve/Sounds.java @@ -2,6 +2,10 @@ package com.example.funnysounds.resolve; import android.app.Application; import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; import android.util.Log; import androidx.lifecycle.LiveData; @@ -11,6 +15,8 @@ import com.anythink.core.api.NetTrafficeCallback; import com.example.funnysounds.data.CategoryList; import com.example.funnysounds.room.MyRoom; import com.example.funnysounds.topon.AdManager; +import com.example.funnysounds.value.StaticValue; +import com.google.firebase.analytics.FirebaseAnalytics; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -34,6 +40,7 @@ public class Sounds extends Application { public static final String TABLE_1 = "table_category"; public static final String TABLE_2 = "table_data"; + @Override public void onCreate() { super.onCreate(); @@ -43,7 +50,6 @@ public class Sounds extends Application { new Thread(new Runnable() { @Override public void run() { - List categoryLists = MyRoom.getInstance().getCategoryDao().queryAllData(); if (categoryLists.size() == 0) { try { @@ -60,6 +66,41 @@ public class Sounds extends Application { } }).start(); + initFirebaseLogEvent(); + + } + + private void initFirebaseLogEvent() { + Boolean firstInstall = SpSave.getFirstInstall(); + if (firstInstall) { + FirebaseAnalytics instance = FirebaseAnalytics.getInstance(this); + Bundle bundleEvent = new Bundle(); + String initiatingPackageName = ""; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + try { + initiatingPackageName = getPackageManager().getInstallSourceInfo(getApplicationInfo().packageName).getInitiatingPackageName(); + } catch (PackageManager.NameNotFoundException e) { + Log.d(TAG, "-firstInstall----NameNotFoundException=" + e.getMessage()); + } + } else { + initiatingPackageName = getPackageManager().getInstallerPackageName(getApplicationInfo().packageName); + } + Log.d(TAG, "-firstInstall----initiatingPackageName=" + initiatingPackageName); + bundleEvent.putString("installer_name", initiatingPackageName); + try { + PackageInfo packageInfo = getPackageManager().getPackageInfo("com.android.vending", 0); + bundleEvent.putString("ps_version", packageInfo.versionName); + bundleEvent.putInt("ps_version_code", packageInfo.versionCode); + } catch (Throwable unused) { + bundleEvent.putString("ps_version", "-1"); + bundleEvent.putInt("ps_version_code", -1); + } + instance.logEvent(StaticValue.Firebase_Key, bundleEvent); + SpSave.setFirstInstall(); + } else { + Log.d(TAG, "--firstInstall-else--"); + } + } public void init() { diff --git a/app/src/main/java/com/example/funnysounds/resolve/SpSave.java b/app/src/main/java/com/example/funnysounds/resolve/SpSave.java new file mode 100644 index 0000000..d2d8211 --- /dev/null +++ b/app/src/main/java/com/example/funnysounds/resolve/SpSave.java @@ -0,0 +1,35 @@ +package com.example.funnysounds.resolve; + +import static android.content.Context.MODE_PRIVATE; + +import android.content.Context; +import android.content.SharedPreferences; + +public class SpSave { + + private static SharedPreferences sp; + + + + + private static String spName = "funny"; + private static String firstInstall = "first_install"; + + public static void setFirstInstall() { + SharedPreferences.Editor edit = getSp().edit(); + edit.putBoolean(firstInstall, false).apply(); + } + + + private static SharedPreferences getSp() { + if (sp == null) { + sp = Sounds.mAppContext.getSharedPreferences(spName, MODE_PRIVATE); + } + return sp; + } + + + public static Boolean getFirstInstall() { + return getSp().getBoolean(firstInstall, true); + } +} diff --git a/app/src/main/java/com/example/funnysounds/soundsadapter/LoveAdapter.java b/app/src/main/java/com/example/funnysounds/soundsadapter/LoveAdapter.java index b3424e1..73adeec 100644 --- a/app/src/main/java/com/example/funnysounds/soundsadapter/LoveAdapter.java +++ b/app/src/main/java/com/example/funnysounds/soundsadapter/LoveAdapter.java @@ -82,7 +82,7 @@ public class LoveAdapter extends RecyclerView.Adapter { holder.getVb().imLove.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - notifyItemRemoved(position); + notifyItemRemoved(holder.getAdapterPosition()); Toast.makeText(Sounds.mAppContext,myContext.getString(R.string.remove),Toast.LENGTH_SHORT).show(); Readfile.onSwitchIO(new IOListener() { @Override diff --git a/app/src/main/java/com/example/funnysounds/topon/AdManager.java b/app/src/main/java/com/example/funnysounds/topon/AdManager.java index 2f7ccbf..c1b8ece 100644 --- a/app/src/main/java/com/example/funnysounds/topon/AdManager.java +++ b/app/src/main/java/com/example/funnysounds/topon/AdManager.java @@ -35,9 +35,9 @@ public class AdManager { private static final String place3Id = "n66a0be55b7bbe"; - private static boolean place1LoadFail = false; - private static boolean place2LoadFail = false; - private static boolean place3LoadFail = false; + public static boolean place1LoadFail = false; + public static boolean place2LoadFail = false; + public static boolean place3LoadFail = false; private static boolean alreadyShow = false; @@ -84,7 +84,7 @@ public class AdManager { } }); -// ad.load() + ad.load(); } } @@ -127,7 +127,7 @@ public class AdManager { public void onInterstitialAdShow(ATAdInfo atAdInfo) { Log.d(Sounds.TAG, "AdShow " + atAdInfo.getShowId()); listener.showSuccess(); -// ad.load() + ad.load(); } @Override diff --git a/app/src/main/java/com/example/funnysounds/value/StaticValue.java b/app/src/main/java/com/example/funnysounds/value/StaticValue.java index 6874e18..eb08df6 100644 --- a/app/src/main/java/com/example/funnysounds/value/StaticValue.java +++ b/app/src/main/java/com/example/funnysounds/value/StaticValue.java @@ -8,4 +8,8 @@ public class StaticValue { public static final String key_record_path= "key_path"; + public static int enterDetailCount = 0; + public static final String Firebase_Key= "install_source"; + + } diff --git a/app/src/main/res/drawable/add_record_bg_button.xml b/app/src/main/res/drawable/add_record_bg_button.xml index 790805f..0a94f99 100644 --- a/app/src/main/res/drawable/add_record_bg_button.xml +++ b/app/src/main/res/drawable/add_record_bg_button.xml @@ -3,6 +3,6 @@ android:shape="rectangle"> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/im_stop.xml b/app/src/main/res/drawable/im_stop.xml index 2d16125..0a8da0c 100644 --- a/app/src/main/res/drawable/im_stop.xml +++ b/app/src/main/res/drawable/im_stop.xml @@ -8,5 +8,5 @@ android:fillColor="@color/sounds_main"/> + android:fillColor="@color/white"/> diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 043ed24..c5cce90 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -7,7 +7,7 @@ android:orientation="vertical" tools:context=".activity.DetailActivity"> - + - + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_into.xml b/app/src/main/res/layout/activity_into.xml index b88cd18..984f00c 100644 --- a/app/src/main/res/layout/activity_into.xml +++ b/app/src/main/res/layout/activity_into.xml @@ -30,8 +30,7 @@ android:text="@string/app_name" android:textColor="@color/black" android:textSize="25sp" - - android:textStyle="italic" /> + android:textStyle="normal" /> + android:textSize="18sp" /> diff --git a/app/src/main/res/layout/item_love.xml b/app/src/main/res/layout/item_love.xml index d8baaa8..c84c866 100644 --- a/app/src/main/res/layout/item_love.xml +++ b/app/src/main/res/layout/item_love.xml @@ -23,9 +23,13 @@ android:layout_gravity="center" android:layout_marginStart="43dp" android:layout_marginTop="10dp" + android:layout_toStartOf="@id/im_love" + android:paddingEnd="5dp" android:layout_marginBottom="15dp" android:layout_toEndOf="@id/im_sounds" - android:text="@string/app_name" + android:ellipsize="end" + android:maxLines="2" + android:text="rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrsssssssssssssssssssssssssrrrrrrrrrrrrrrrrrrrrrrrrrr" android:textColor="@color/black" android:textSize="15sp" /> diff --git a/app/src/main/res/layout/item_record.xml b/app/src/main/res/layout/item_record.xml index 54c618c..1752470 100644 --- a/app/src/main/res/layout/item_record.xml +++ b/app/src/main/res/layout/item_record.xml @@ -23,9 +23,13 @@ android:layout_gravity="center" android:layout_marginStart="43dp" android:layout_marginTop="10dp" + android:layout_toStartOf="@id/im_delete" android:layout_marginBottom="15dp" + android:layout_marginEnd="5dp" + android:ellipsize="end" android:layout_toEndOf="@id/im_sounds" - android:text="@string/app_name" + android:text="rr" + android:maxLines="2" android:textColor="@color/black" android:textSize="15sp" /> diff --git a/app/src/main/res/layout/layout_log.xml b/app/src/main/res/layout/layout_log.xml new file mode 100644 index 0000000..98d872f --- /dev/null +++ b/app/src/main/res/layout/layout_log.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c068ad..17714c4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,4 +26,5 @@ Create sounds Deleted successfully Privacy Policy + Loading Ads \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index dc9e121..90098f8 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -2,7 +2,7 @@